Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Traceroute is a computer networking diagnostic tool which allows a user to trace the route from a host running the traceroute program to any other

 

Traceroute is a computer networking diagnostic tool which allows a user to trace the route from a host running the traceroute program to any other host in the world. Traceroute is implemented with ICMP messages. It works by sending ICMP echo (ICMP type '8') messages to the same destination with increasing value of the time-to-live (TTL) field. The routers along the traceroute path return ICMP Time Exceeded (ICMP type '11') when the TTL field becomes zero. The final destination sends an ICMP reply

(ICMP type '0') messages on receiving the ICMP echo request. The IP addresses of the routers which send replies can be extracted from the received packets. The round-trip time between the sending host and a router is determined by setting a timer at the sending host.

Your task is to develop your own Traceroute application in python using ICMP. Your application will use ICMP but, in order to keep it simple, will not exactly follow the official specification in RFC 1739.

Testing the Pinger

Test your client by running your code to trace google.com or bing.com. Your output should return a list and meet the acceptance criteria format provided below.

Output Requirements (Acceptance Criteria)

Your code must produce the traceroute output in the format provided below for Gradescope to verify your code is working correctly.

  1. Your trace must collect hop number, roundtrip time (rtt), host ip, and the hostname. If a hostname is not available for a host, you should provide an explicit hostname as "hostname not returnable". Also, if a host is timing out (not responding), you must record this in your trace list item with the text "Request timed out". Example provided below:

Example: 1 12ms 10.10.111.10 hop1.com

2 30ms 10.10.112.10 hostname not returnable

3 * Request timed out

4 5ms 10.10.110.1 target-host.com

  1. Your get_route() function must return a nested list with trace output. That is, each trace row must be a list that includes the trace results as individual items in the list, which is also inside an overall traceroute list. Example provided below:

Example: [ ['1', '12ms', '10.10.111.10', 'hop1.com'], ['2', '30ms', '10.10.112.10',

'hostname not returnable'], ['3', '*', 'Request timed out'], ['4', '5ms',

'10.10.110.1', 'target-host.com'] ]

Note: Your output will be parsed to verify that it includes the relevant information, so if you do not provide the output of your function in a nested list, your solution will not work correctly and you will not receive points. Also, note that the example lists include all data as strings.

import os

import sys

import struct

import time

import select

import binascii

from socket import *

from socket import socket

#from socket import gethostname

ICMP_ECHO_REQUEST = 8

MAX_HOPS = 30

TIMEOUT = 2.0

TRIES = 2

# The packet that we shall send to each router along the path is the ICMP echo

# request packet, which is exactly what we had used in the ICMP ping exercise.

# We shall use the same packet that we built in the Ping exercise

def checksum(string):

# In this function we make the checksum of our packet

csum = 0

countTo = (len(string) // 2) * 2

count = 0

while count < countTo:

thisVal = (string[count + 1]) * 256 + (string[count])

csum += thisVal

csum &= 0xffffffff

count += 2

if countTo < len(string):

csum += (string[len(string) - 1])

csum &= 0xffffffff

csum = (csum >> 16) + (csum & 0xffff)

csum = csum + (csum >> 16)

answer = ~csum

answer = answer & 0xffff

answer = answer >> 8 | (answer << 8 & 0xff00)

return answer

def build_packet():

#Fill in start

# In the sendOnePing() method of the ICMP Ping exercise ,firstly the header of our

# packet to be sent was made, secondly the checksum was appended to the header and

# then finally the complete packet was sent to the destination.

# Make the header in a similar way to the ping exercise.

# Append checksum to the header.

# Don't send the packet yet , just return the final packet in this function.

#Fill in end

myChecksum = 0

pid = os.getpid() & 0xFFFF

header = struct.pack('bbHHh', ICMP_ECHO_REQUEST,0, myChecksum, pid, 1)

data = struct.pack('d', time.time())

myChecksum = checksum(header+data)

if sys.platform == 'darwin':

myChecksum = socket.htons(myChecksum) & 0xffff

else:

# So the function ending should look like this

myChecksum = htons(myChecksum)

packet = header + data

return packet

def get_route(hostname):

timeLeft = TIMEOUT

#tracelist1 = [] #This is your list to use when iterating through each trace

#tracelist2 = [] #This is your list to contain all traces

for ttl in range(1,MAX_HOPS):

for tries in range(TRIES):

destAddr = gethostbyname(hostname)

#Fill in start

# Make a raw socket named mySocket

mySocket = socket(AF_INET, SOCK_RAW, getprotobyname('icmp'))

mySocket.bind(("", 12000))

#Fill in end


mySocket.setsockopt(IPPROTO_IP, IP_TTL, struct.pack('I', ttl))

mySocket.settimeout(TIMEOUT)


try:

d = build_packet()

mySocket.sendto(d, (hostname, 0))

t= time.time()

startedSelect = time.time()

whatReady = select.select([mySocket], [], [], timeLeft)

howLongInSelect = (time.time() - startedSelect)

if whatReady[0] == []: # Timeout

print("* * * Request timed out.")

#Fill in start

#You should add the list above to your all traces list

#Fill in end

recvPacket, addr = mySocket.recvfrom(1024)

timeReceived = time.time()

timeLeft = timeLeft - howLongInSelect

if timeLeft <= 0:

print("* * * Request timed out.")


#Fill in end

except timeout:

continue

else:

#Fill in start

#Fetch the icmp type from the IP packet

icmp_header = recvPacket[20:28]

type, code, checksum, pid, sequence = struct.unpack('bbHHh', icmp_header)

#Fill in end

try:

#Fill in start

host_name = "Test"

#Fill in end

except herror:

host_name = ('hostname not returnable')

#Fill in start

#Fill in end

if types == 11:

bytes = struct.calcsize("d")

timeSent = struct.unpack("d", recvPacket[28:28 +

bytes])[0]

#Fill in start

#You should add your responses to your lists here

print('%d, %.0fms, %s, %s' %(ttl,(timeReceived - t)*1000, addr[0], host_name))

#Fill in end

elif types == 3:

bytes = struct.calcsize("d")

timeSent = struct.unpack("d", recvPacket[28:28 + bytes])[0]

#Fill in start

print('%d, %.0fms, %s, %s' %(ttl,(timeReceived - t)*1000, addr[0], host_name))

#You should add your responses to your lists here

#Fill in end

elif types == 0:

bytes = struct.calcsize("d")

timeSent = struct.unpack("d", recvPacket[28:28 + bytes])[0]

#Fill in start

#You should add your responses to your lists here and return your list if your destination IP is met

print('%d, %.0fms, %s, %s' %(ttl,(timeReceived - t)*1000, addr[0], host_name))

return

#Fill in end

else:

#Fill in start

print('Error')

#If there is an exception/error to your if statements, you should append that to your list here

#Fill in end

break

finally:

mySocket.close()

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Computer Networks

Authors: Andrew S. Tanenbaum, David J. Wetherall

5th edition

132126958, 978-0132126953

More Books

Students also viewed these Computer Network questions

Question

=+b) In which graph is a larger value of a used?

Answered: 1 week ago