
Python - Internet Control Message Protocol
- 22nd Sep, 2021
- 17:12 PM
In this lab, you will gain a better understanding of Internet Control Message Protocol (ICMP). You will learn to implement a Ping application using ICMP request and reply messages. from socket import * import os import sys import struct import time import select import binascii ICMP_ECHO_REQUEST = 8 packageSent = 0 packageReceive = 0 def checksum(string): 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> 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> return answer def receiveOnePing(mySocket, ID, timeout, destAddr): global packageReceive timeLeft = timeout while 1: startedSelect = time.time() whatReady = select.select([mySocket], [], [], timeLeft) howLongInSelect = (time.time() - startedSelect) if whatReady[0] == []: # Timeout return "Request timed out." timeReceived = time.time() recPacket, addr = mySocket.recvfrom(1024) # Fill in start # Fetch the ICMP header from the IP packet header = recPacket[20:28] type, code, checksum, packageID, sequence = struct.unpack("bbHHh", header) if packageID == ID: time_offset = struct.calcsize("d") timeSent = struct.unpack("d", recPacket[28:28 + time_offset])[0] packageReceive += 1 return timeReceived - timeSent # Fill in end timeLeft = timeLeft - howLongInSelect if timeLeft <= 0: return "Request timed out." def sendOnePing(mySocket, destAddr, ID): # Header is type (8), code (8), checksum (16), id (16), sequence (16) global packageSent myChecksum = 0 # Make a dummy header with a 0 checksum # struct -- Interpret strings as packed binary data header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1) data = struct.pack("d", time.time()) # Calculate the checksum on the data and the dummy header. myChecksum = checksum(header + data) # Get the right checksum, and put in the header if sys.platform == 'darwin': # Convert 16-bit integers from host to network byte order myChecksum = htons(myChecksum) & 0xffff else: myChecksum = htons(myChecksum) header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1) packet = header + data mySocket.sendto(packet, (destAddr, 1)) # AF_INET address must be tuple, not str packageSent += 1 # Both LISTS and TUPLES consist of a number of objects # which can be referenced by their position number within the object. def doOnePing(destAddr, timeout): icmp = getprotobyname("icmp") # SOCK_RAW is a powerful socket type. For more details: http://sockraw.org/papers/sock_raw mySocket = socket(AF_INET, SOCK_RAW, icmp) myID = os.getpid() & 0xFFFF # Return the current process i sendOnePing(mySocket, destAddr, myID) delay = receiveOnePing(mySocket, myID, timeout, destAddr) mySocket.close() return delay def average(arrays): avg_sum = 0 for i in arrays: avg_sum += i return (avg_sum / len(arrays)) def ping(host, timeout=1): # timeout=1 means: If one second goes by without a reply from the server, # the client assumes that either the client's ping or the server's pong is lost dest = gethostbyname(host) print("Pinging " + dest + " aka " + host + " using Python:") print("") delays = [] # Send ping requests to a server separated by approximately one second count = 5 while count: delay = doOnePing(dest, timeout) print("Ping times " + str(count) + " RTT = " + str(delay)) time.sleep(1) # one second count -= 1 delays.append(delay) print("") print("The maximum RTT is: " + str(max(delays))) print("The minimum RTT is: " + str(min(delays))) print("The average RTT is " + str(sum(delays)/len(delays))) print("The package loss rate is " + str(1 - packageReceive/packageSent)) return delays host = input("Enter address want to ping: ") ping(host) #ping("google.com")