Develop a 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..
Below you will find the skeleton code for the client. You are to complete the skeleton code. The places where you need to fill in code are marked with #Fill in start and #Fill in end.
Code
from socket import * import os import sys import struct import time import select import binascii ICMP_ECHO_REQUEST = 8 MAX_HOPS = 30 TIMEOUT = 2.0 TRIES = 2 def checksum(string): csum = 0 countTo = (len(string) // 2) * 2 count = 0 while count < countTo: thisVal = ord(string[count + 1]) * 256 + ord(string[count]) csum = csum + thisVal csum = csum & 0xffffffff count = count + 2 if countTo < len(string): csum = csum + ord(string[len(string) - 1]) csum = 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(data_size): # First, make the header of the packet, then append the checksum to the header, # then finally append the data # Dont send the packet yet, just return the final packet in this function. # So the function ending should look like this # Note: padding = bytes(data_size) packet = header + data + padding return packet def get_route(hostname, data_size): timeLeft = TIMEOUT for ttl in range(1, MAX_HOPS): for tries in range(TRIES): destAddr = gethostbyname(hostname) # SOCK_RAW is a powerful socket type. For more details: http://sock-raw.org/papers/sock_raw # Fill in start # Make a raw socket named mySocket # Fill in end # setsockopt method is used to set the time-to-live field. mySocket.setsockopt(IPPROTO_IP, IP_TTL, struct.pack('I', ttl)) mySocket.settimeout(TIMEOUT) try: d = build_packet(data_size) 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.") recvPacket, addr = mySocket.recvfrom(1024) timeReceived = time.time() timeLeft = timeLeft - howLongInSelect if timeLeft <= 0: print(" * * * Request timed out.") except timeout: continue else: # Fill in start # Fetch the icmp type from the IP packet # Fill in end if types == 11: bytes = struct.calcsize("d") timeSent = struct.unpack("d", recvPacket[28:28 + bytes])[0] print(" %d rtt=%.0f ms %s" % (ttl, (timeReceived - t) * 1000, addr[0])) elif types == 3: bytes = struct.calcsize("d") timeSent = struct.unpack("d", recvPacket[28:28 + bytes])[0] print(" %d rtt=%.0f ms %s" % (ttl, (timeReceived - t) * 1000, addr[0])) elif types == 0: bytes = struct.calcsize("d") timeSent = struct.unpack("d", recvPacket[28:28 + bytes])[0] print(" %d rtt=%.0f ms %s" % (ttl, (timeReceived - timeSent) * 1000, addr[0])) return else: print("error") break finally: mySocket.close() print('Argument List: {0}'.format(str(sys.argv))) data_size = 0 if len(sys.argv) >= 2: data_size = int(sys.argv[1]) get_route("google.com", data_size)
Your code is completely coped and whereever the new code is to be inserted, it is done. Please see to that.
from socket import *
import os
import sys
import struct
import time
import select
import binascii
ICMP_ECHO_REQUEST = 8
MAX_HOPS = 30
TIMEOUT = 2.0
TRIES = 2
def checksum(string):
csum = 0
countTo = (len(string) // 2) * 2
count = 0
while count < countTo:
thisVal = ord(string[count + 1]) * 256 + ord(string[count])
csum = csum + thisVal
csum = csum & 0xffffffff
count = count + 2
if countTo < len(string):
csum = csum + ord(string[len(string) - 1])
csum = 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(data_size):
# First, make the header of the packet, then append the checksum to
the header,
# then finally append the data
# Dont send the packet yet, just return the final packet in this
function.
# So the function ending should look like this
# Note: padding = bytes(data_size)
packet = header + data + padding
return packet
def get_route(hostname, data_size):
timeLeft = TIMEOUT
for ttl in range(1, MAX_HOPS):
for tries in range(TRIES):
destAddr = gethostbyname(hostname)
# SOCK_RAW is a powerful socket type. For more details:
http://sock-raw.org/papers/sock_raw
# Fill in start
# Make a raw socket named mySocket
icmp = socket.getprotobyname("icmp")
mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
# Fill in end
# setsockopt method is used to set the time-to-live field.
mySocket.setsockopt(IPPROTO_IP, IP_TTL, struct.pack('I',
ttl))
mySocket.settimeout(TIMEOUT)
try:
d = build_packet(data_size)
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.")
recvPacket, addr = mySocket.recvfrom(1024)
timeReceived = time.time()
timeLeft = timeLeft - howLongInSelect
if timeLeft <= 0:
print(" * * * Request timed out.")
except timeout:
continue
else:
# Fill in start
# Fetch the icmp type from the IP packet
icmpHeaderContent = recvPacket[20:28]
type, code, checksum, packetID, sequence = struct.unpack("bbHHh",
icmpHeaderContent)
printname = get_name_or_ip(addr[0])
# Fill in end
if types == 11:
bytes = struct.calcsize("d")
timeSent = struct.unpack("d", recvPacket[28:28 + bytes])[0]
print(" %d rtt=%.0f ms %s" % (ttl, (timeReceived - t) * 1000,
addr[0]))
elif types == 3:
bytes = struct.calcsize("d")
timeSent = struct.unpack("d", recvPacket[28:28 + bytes])[0]
print(" %d rtt=%.0f ms %s" % (ttl, (timeReceived - t) * 1000,
addr[0]))
elif types == 0:
bytes = struct.calcsize("d")
timeSent = struct.unpack("d", recvPacket[28:28 + bytes])[0]
print(" %d rtt=%.0f ms %s" % (ttl, (timeReceived - timeSent) *
1000, addr[0]))
return
else:
print("error")
break
finally:
mySocket.close()
print('Argument List: {0}'.format(str(sys.argv)))
data_size = 0
if len(sys.argv) >= 2:
data_size = int(sys.argv[1])
get_route("google.com", data_size)
Get Answers For Free
Most questions answered within 1 hours.