Created
July 5, 2011 10:41
-
-
Save khajer/1064639 to your computer and use it in GitHub Desktop.
prang
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| data packet sent | |
| 0 1 2 3 | |
| 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| | Type | Code | Checksum | | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| | Identifier | Sequence Number | | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| | Data ... | |
| +-+-+-+-+- | |
| """ | |
| ICMP_ECHO_REQUEST = 8 | |
| import os, sys, socket, struct, select, time | |
| """ | |
| ----------------------------------------- | |
| send_one_ping | |
| ----------------------------------------- | |
| """ | |
| def send_one_ping(my_socket, dest_addr, ID): | |
| dest_addr = socket.gethostbyname(dest_addr) | |
| my_checksum = 0 | |
| header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, my_checksum, ID, 1) | |
| bytesInDouble = struct.calcsize("d") | |
| data = (192 - bytesInDouble) * "Q" | |
| data = struct.pack("d", time.time()) + data | |
| my_checksum = checksum(header + data) | |
| header = struct.pack( | |
| "bbHHh", ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), ID, 1 | |
| ) | |
| packet = header + data # data packet for sent | |
| my_socket.sendto(packet, (dest_addr, 1)) # Don't know about | |
| """ | |
| ----------------------------------------- | |
| receive_one_ping | |
| ----------------------------------------- | |
| """ | |
| def receive_one_ping(my_socket, ID, timeout): | |
| timeLeft = timeout | |
| while True: | |
| startedSelect = time.time() | |
| whatReady = select.select([my_socket], [], [], timeLeft) | |
| howLongInSelect = (time.time() - startedSelect) | |
| if whatReady[0] == []: #timeout | |
| return | |
| timeReceived = time.time() | |
| recPacket, addr = my_socket.recvfrom(1024) | |
| icmpHeader = recPacket[20:28] | |
| type, code, checksum, packetID, sequence = struct.unpack( # call checksum | |
| "bbHHh", icmpHeader | |
| ) | |
| if packetID == ID: | |
| bytesInDouble = struct.calcsize("d") | |
| timeSent = struct.unpack("d", recPacket[28:28 + bytesInDouble])[0] | |
| return timeReceived - timeSent | |
| timeLeft = timeLeft - howLongInSelect | |
| if timeLeft <= 0: | |
| return | |
| """ | |
| ----------------------------------------- | |
| checksum | |
| ----------------------------------------- | |
| """ | |
| def checksum(source_string): | |
| sum = 0 | |
| countTo = (len(source_string)/2)*2 | |
| count = 0 | |
| while count < countTo: | |
| thisVal = ord(source_string[count + 1])*256 + ord(source_string[count]) | |
| sum = sum + thisVal | |
| sum = sum & 0xffffffff # Necessary? | |
| count = count + 2 | |
| if countTo < len(source_string): | |
| sum = sum + ord(source_string[len(source_string)-1]) | |
| sum = sum & 0xffffffff # Necessary? | |
| sum = (sum >> 16) + (sum & 0xffff) | |
| sum = sum + (sum >> 16) | |
| answer = ~sum | |
| answer = answer & 0xffff | |
| answer = answer >> 8 | (answer << 8 & 0xff00) | |
| return answer | |
| """ | |
| ----------------------------------------- | |
| wait for delay (in seconds) or timeout | |
| ----------------------------------------- | |
| """ | |
| def send_signal(dest_addr, timeout): | |
| # get socket | |
| icmp = socket.getprotobyname("icmp") | |
| try: | |
| my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp) | |
| except socket.error, (errno, msg): | |
| if errno == 1: | |
| #operation not permitted | |
| msg = msg + ( | |
| " - Note that ICMP messages can only by sent from processes" | |
| " running as root." | |
| ) | |
| raise socket.error(msg) | |
| raise #raise the original error | |
| # send packet ping | |
| my_ID = os.getpid() & 0xFFFF | |
| send_one_ping(my_socket, dest_addr, my_ID) | |
| delay = receive_one_ping(my_socket, my_ID, timeout) | |
| my_socket.close() | |
| return delay | |
| def kping(dest_addr, timeout=2, count=4): | |
| # ping 4 time | |
| for i in xrange(count): | |
| print "ping %s ..." % dest_addr, | |
| try: | |
| # send message for wait response | |
| delay = send_signal(dest_addr, timeout) | |
| except socket.gaierror, e: | |
| print "failed. (socket error: '%s')" % e[1] | |
| break | |
| if delay == None: | |
| print "failed. (timeout within %ssec.)" %timeout | |
| else: | |
| delay = delay * 100 | |
| print "get ping in %0.4fms"%delay | |
| """ | |
| ----------------------------------------- | |
| Loop trace ip | |
| ----------------------------------------- | |
| """ | |
| def startTrace(start_ip, end_ip): | |
| print 'trace ping ip between ' +start_ip +' to '+ end_ip | |
| startip_check = '' | |
| endip_check = '' | |
| for num in start_ip.split('.'): | |
| h = str(hex(int(num)))[2:4] | |
| if len(h) == 1: | |
| h = '0'+h | |
| startip_check += h | |
| for num in end_ip.split('.'): | |
| h = str(hex(int(num)))[2:4] | |
| if len(h) == 1: | |
| h = '0'+h | |
| endip_check += h | |
| if int(startip_check, 16) < int(endip_check, 16): | |
| sip_h = int(startip_check, 16) | |
| eip_h = int(endip_check, 16) | |
| while True: | |
| ip_trace = hex(sip_h) | |
| ip_t = '' | |
| ip_trace = ip_trace[2:len(ip_trace)] # cut '0x' first text | |
| ip_trace = ip_trace.replace('L', '') # cut L last charecter | |
| for i in range(4, 0, -1): | |
| si = len(ip_trace)-(i*2) | |
| ei = si+2 | |
| if si < 0 | i == 4: | |
| n = str(int(ip_trace[0:ei], 16)) | |
| else: | |
| n = "."+ str(int(ip_trace[si:ei], 16)) | |
| ip_t +=n | |
| #pring process loop | |
| kping(ip_t, 2, 1) # ping trace | |
| if sip_h < eip_h: | |
| sip_h +=1 | |
| else: | |
| break | |
| else: | |
| print "set start ip and end ip not correct" | |
| """ | |
| ----------------------------------------- | |
| Main | |
| ----------------------------------------- | |
| """ | |
| if __name__ == '__main__': | |
| #kping('10.15.1.50') | |
| #start & end ip for ping | |
| if len(sys.argv) > 1: | |
| start_ip = sys.argv[1] | |
| if len(sys.argv) > 2: | |
| end_ip = sys.argv[2] | |
| startTrace(start_ip, end_ip) | |
| else: | |
| kping(start_ip) | |
| else: | |
| print "argument not correct. Ex: > prang.py 192.168.1.1 192.168.1.254" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment