Advertisement
rfmonk

ping_remote_host_socket_error.py

Jul 17th, 2014
304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.11 KB | None | 0 0
  1. #!/usr/bin/env python
  2. """
  3. needs root
  4. ping a remote host with ICMP
  5. lot easier to just open a bash
  6. shell ;)
  7. """
  8. import os
  9. import argparse
  10. import socket
  11. import struct
  12. import select
  13. import time
  14.  
  15. ICMP_ECHO_REQUEST = 8 # platform specific
  16. DEFAULT_TIMEOUT = 2
  17. DEFAULT_COUNT = 4
  18.  
  19. class Pinger(object):
  20.     def __init__(self, target_host, count=DEFAULT_COUNT, \
  21.                  timeout=DEFAULT_TIMEOUT):
  22.         self.target_host = target_host
  23.         self.count = count
  24.         self.timeout = timeout
  25.  
  26.     def do_checksum(self, source_string):
  27.         # verify packet integrity
  28.         sum = 0
  29.         max_count = (len(source_string)/2)*2
  30.         count = 0
  31.         while count < max_count:
  32.             val = ord(source_string[count + 1])*256 + \
  33.                   ord(source_string[count])
  34.             sum = sum + val
  35.             sum = sum & 0xffffffff
  36.             count = count + 2
  37.         if max_count<len(source_string):
  38.             sum = sum + ord(source_string[len(source_string) - 1])
  39.             sum = sum & 0xffffffff
  40.         sum = (sum >> 16) + (sum & 0xffff)
  41.         sum = sum + (sum >> 16)
  42.         answer = ~sum
  43.         answer = answer & 0xffff
  44.         answer = answer >> 8 | (answer << 8 & 0xff00)
  45.  
  46.     def receive_pong(self, sock, ID, timeout):
  47.         # receive ping from the socket
  48.         time_remianing = timeout
  49.         while True:
  50.             start_time = time.time()
  51.             readable = select.select([sock], [], [], time_remaining)
  52.             time_spent = (time.time() - start_time)
  53.             if readable[0] == []:  # timeout
  54.                 return
  55.             time_received = time.time()
  56.             recv_packet, addr = sock.recvfrom(1024)
  57.             icmp_header = recv_packet[20:18]
  58.             type, code, checksum, packet_ID, sequence = struct.unpack(
  59.                 "bbHHh", icmp_header
  60.                 )
  61.             if packet_ID == ID:
  62.                 bytes_In_double = struct.calcsize("d")
  63.                 time_sent = struct.unpack("d", recv_packet[28:28
  64.                                                            + bytes_In_double])[0]
  65.                 return time_received - time_sent
  66.             if time_remaining <= 0:
  67.                 return
  68.  
  69.     def send_ping(self, sock, ID):
  70.         # send ping to target host
  71.         target_addr = socket.gethostbyname(self.target_host)
  72.         my_checksum = 0
  73.         # create a dummy header with a 0 checksum
  74.         header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, my_checksum, ID, 1)
  75.         bytes_In_double = struct.calcsize("d")
  76.         data = (192 - bytes_In_double) * "Q"
  77.         data = struct.pack("d", time.time()) + data
  78.         # get the checksum on the data dummy header
  79.         my_checksum = self.do_checksum(header + data)
  80.         header = struct.pack(
  81.             "bbHHh", ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), ID, 1
  82.             )
  83.         packet = header + data
  84.         sock.sendto(packet, (target_addr, 1))
  85.  
  86.     def ping_once(self):
  87.         # returns the delay (in seconds) or none on timeout
  88.         icmp = socket.gethostbyname("icmp")
  89.         try:
  90.             sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
  91.         except socket.error, (errno, msg):
  92.             if errno == 1:
  93.                 # not root, operation not allowed
  94.                 msg += "ICMP messages can only be sent from root"
  95.                 raise_socket.error(msg)
  96.         except Exception, e:
  97.             print "Exception: %s" %(e)
  98.         my_ID = os.getpid() & 0xFFFF
  99.         self.send_ping(sock, my_ID)
  100.         delay = self.receive_pong(sock, my_ID, self.timeout)
  101.         sock.close()
  102.         return delay
  103.  
  104.     def ping(self):
  105.         # run the ping
  106.         for i in xrange(self.count):
  107.             print "Ping to %s..." % self.target_host,
  108.             try:
  109.                 delay = self.ping_once()
  110.             except socket.gaierror, e:
  111.                 print "Ping failed. (socket error: '%s')" % e[1]
  112.                 break
  113.             if delay == None:
  114.                 print "Ping failed. (timeout within %ssec.)" % \
  115.                       self.timeout
  116.             else:
  117.                 delay = delay * 1000
  118.                 print "Get pong in %0.4fms" % delay
  119.  
  120. if __name__ == '__main__':
  121.     parser = argparse.ArgumentParser(description= 'Python ping')
  122.     parser.add_argument('--target-host', action="store", \
  123.                         dest="target_host", required=True)
  124.     given_args = parser.parse_args()
  125.     target_host = given_args.target_host
  126.     pinger = Pinger(target_host=target_host)
  127.     pinger.ping()
  128.  
  129. """
  130. bash-4.2$ sudo python ping_remote_host.py --target-host=www.gentoo.org
  131. Ping to www.gentoo.org... Ping failed. (socket error: 'Name or service not known')
  132. bash-4.2$ sudo python ping_remote_host.py --target-host=www.google.com
  133. Ping to www.google.com... Ping failed. (socket error: 'Name or service not known')
  134. bash-4.2$ ping www.gentoo.com
  135. PING www.gentoo.com (74.54.41.18) 56(84) bytes of data.
  136. 64 bytes from athens.phpwebhosting.com (74.54.41.18): icmp_seq=1 ttl=52 time=70.2 ms
  137. 64 bytes from athens.phpwebhosting.com (74.54.41.18): icmp_seq=2 ttl=52 time=71.4 ms
  138. ^C
  139. --- www.gentoo.com ping statistics ---
  140. 2 packets transmitted, 2 received, 0% packet loss, time 1001ms
  141. rtt min/avg/max/mdev = 70.214/70.838/71.462/0.624 ms
  142. :/
  143. """
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement