Advertisement
rfmonk

ping_remote_host.py

Jun 25th, 2014
242
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.58 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3.  
  4. import os
  5. import argparse
  6. import socket
  7. import struct
  8. import select
  9. import time
  10.  
  11. ICMP_ECHO_REQUEST = 8  # platform specific
  12. DEFAULT_TIMEOUT = 2
  13. DEFAULT_COUNT = 4
  14.  
  15.  
  16. class Pinger(object):
  17.     """ Ping a host the Python way"""
  18.     def __init__(self, target_host, count=DEFAULT_COUNT, timeout=DEFAULT_TIMEOUT):
  19.         self.target_host = target_host
  20.         self.count = count
  21.         self.timeout = timeout
  22.  
  23.     def do_checksum(self, source_string):
  24.         """ Verify packet integrity """
  25.         sum = 0
  26.         max_count = (len(source_string)/2) *2
  27.         count = 0
  28.         while count < max_count:
  29.             val = ord(source_string[count + 1])*256 + ord(source_string[count])
  30.             sum = sum + val
  31.             sum = sum & 0xffffffff
  32.             count = count + 2
  33.         if max_count<len(source_string):
  34.             sum = sum + ord(source_string[len(source_string) - 1])
  35.             sum = sum & 0xffffffff
  36.         sum = (sum >> 16) + (sum & 0xffff)
  37.         sum = sum + (sum >> 16)
  38.         answer = ~sum
  39.         answer = answer & 0xffff
  40.         answer = answer >> 8 | (answer << 8 & 0xff00)
  41.         return answer
  42.  
  43.     def receive_pong(self, sock, ID, timeout):
  44.         """ Receive ping from socket """
  45.         time_remaining = timeout
  46.         while True:
  47.             start_time = time.time()
  48.             readable = select.select([sock], [], [], time_remaining)
  49.             time_spent = (time.time() - start_time)
  50.             if readable[0] == []:  # timeout
  51.                 return
  52.  
  53.             time_received = time.time()
  54.             recv_packet, addr = sock.recvfrom(1024)
  55.             icmp_header = recv_packet[20:28]
  56.             type, code, checksum, packet_ID, sequence = struct.unpack(
  57.                 "bbHHh", icmp_header
  58.                 )
  59.             if packet_ID == ID:
  60.                 bytes_In_double = struct.calcsize("d")
  61.                 time_sent = struct.unpack("d", recv_packet[28:28 + bytes_In_double]) [0]
  62.                 return time_received - time_sent
  63.                 time_remaining = time_remaining - time_spent
  64.                 if time_remaining <= 0:
  65.                     return
  66.  
  67.     def send_ping(self, sock, ID):
  68.         """ Ping the target """
  69.         target_addr = socket.gethostbyname(self.target_host)
  70.         my_checksum = 0
  71.         # create a dummy header with a 0 checksum.
  72.         header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, my_checksum, ID, 1)
  73.         bytes_In_double = struct.calcsize("d")
  74.         data = (192 - bytes_In_double) * "Q"
  75.         data = struct.pack("d", time.time()) + data
  76.         # get the checksum on the data and the dummy header.
  77.         my_checksum = self.do_checksum(header + data)
  78.         header = struct.pack(
  79.             "bbHHh", ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), ID, 1
  80.             )
  81.         packet = header + data
  82.         sock.sendto(packet, (target_addr, 1))
  83.  
  84.     def ping_once(self):
  85.         """ returns delay in seconds or none on timeout. """
  86.         icmp = socket.getprotobyname("icmp")
  87.         try:
  88.             sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
  89.         except socket.error, (errno, msg):
  90.             if errno == 1:
  91.                 # need root privs
  92.                 msg += " need root privs to send icmp"
  93.                 raise socket.error(msg)
  94.         except Exception, e:
  95.             print "Exception: %s" %(e)
  96.             my_ID = os.getpid() & 0xFFFF
  97.             self.send_ping(sock, my_ID)
  98.             delay = self.receive_pong(sock, my_ID, self.timeout)
  99.             sock.close()
  100.             return delay
  101.  
  102.     def ping(self):
  103.         """ run ping """
  104.         for i in xrange(self.count):
  105.             print "Ping to %s..." % self.target_host,
  106.             try:
  107.                 delay = self.ping_once()
  108.             except socket.gaierror, e:
  109.                 print "Ping failed. (socket error: '%s')" % e[1]
  110.                 break
  111.             if delay == None:
  112.                 print "Ping failed. (timeout within %ssec.)" % \
  113.                             self.timeout
  114.             else:
  115.                 delay = delay * 1000
  116.                 print "Get pong in %0.4fms" % delay
  117.  
  118. if __name__ == '__main__':
  119.     parser = argparse.ArgumentParser(description='Python ping')
  120.     parser.add_argument('--target-host', action="store", dest="target_host", required=True)
  121.     given_args = parser.parse_args()
  122.     target_host = given_args.target_host
  123.     pinger = Pinger(target_host=target_host)
  124.     pinger.ping()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement