Example #1
0
    def recvPackets(self,pingJob):
        """receive a packet and decode its header"""
        while time.time() - pingJob.start<self.timeout:
            rl,wl,el = select.select([self.pingsocket],[],[],0)
            if self.pingsocket in rl:
                try:
                    data, (host, port) = self.pingsocket.recvfrom(1024)
                    if not data: return
                    ipreply = ip.disassemble(data)
                    try:
                        icmppkt = icmp.disassemble(ipreply.data)
                    except ValueError:
                        print ("checksum failure on packet %r", ipreply.data)
                        try:
                            icmppkt = icmp.disassemble(ipreply.data, 0)
                        except ValueError:
                            continue            # probably Unknown type
                    except Exception, ex:
                        print ("Unable to decode reply packet payload %s", ex)
                        continue
                    sip =  ipreply.src
                    if (icmppkt.get_type() == icmp.ICMP_ECHOREPLY and
                        icmppkt.get_id() == self.procId and
                        sip == pingJob.ipaddr):
                        pingJob.rrt = (time.time()-pingJob.start)*1000
                        if pingJob.rrt  < 1:
                            time_print = "time<1ms"
                        else:
                            time_print = "time=%dms"%(pingJob.rrt)
                        print "Reply from %s: bytes=%s %s TTL=%d"%(sip,ipreply.len,time_print,ipreply.ttl)
                        pingJob.pingSuc()
                    elif icmppkt.get_type() == icmp.ICMP_UNREACH:
                        try:
                            origpkt = icmppkt.get_embedded_ip()
                            dip = origpkt.dst
                            if (origpkt.data.find(self.pktdata) > -1
                                and dip == pingJob.ipaddr):
                                print ("pj fail for %s", pingJob.ipaddr)

                        except ValueError, ex:
                            print ("failed to parse host unreachable packet")
                    else:
                        pingJob.message = "unexpected pkt %s %s"% (sip, icmppkt)
                        continue
                    break
                except (SystemExit, KeyboardInterrupt): raise
                except socket.error, err:
                    errnum, errmsg = err.args
                    if errnum == errno.EAGAIN:
                        return
                    raise err
Example #2
0
	def wait(self):
		start = time.time()
		timeout = 0.05
		while 1:
			rd, wt, er = select.select([self.sock.socket], [], [], timeout)
			if rd:
				# okay to use time here, because select has told us
				# there is data and we don't care to measure the time
				# it takes the system to give us the packet.
				arrival = time.time()
				try:
					pkt, who = self.sock.recvfrom(4096)
				except socket.error:
					continue
				# could also use the ip module to get the payload
				repip = ip.disassemble(pkt)
				try:
					reply = icmp.disassemble(repip.data)
				except ValueError:
					continue
				try:
					if reply.get_id() == self.ping_ident:
						self.recv_packet(reply, arrival)
						self.last_arrival = arrival
				except AttributeError, e:
					if reply.get_embedded_ip().dst == self.addr:
						raise exceptions.DoesntExistException('host %s '
							'unreachable (%s)' % (self.addr, e))
					# else we are receiving a hostunreach for another host,
					# just ignore it and continue waiting.
			timeout = (start + 0.05) - time.time()
			if timeout < 0:
				break
Example #3
0
 def wait(self):
     start = time.time()
     timeout = 1.0
     while 1:
         rd, wt, er = select.select([self.sock.socket], [], [], timeout)
         if rd:
             # okay to use time here, because select has told us
             # there is data and we don't care to measure the time
             # it takes the system to give us the packet.
             arrival = time.time()
             try:
                 pkt, who = self.sock.recvfrom(4096)
             except socket.error:
                 continue
             # could also use the ip module to get the payload
             repip = ip.disassemble(pkt)
             try:
                 reply = icmp.disassemble(repip.data)
             except ValueError:
                 continue
             if reply.get_id() == self.pid:
                 self.recv_packet(reply, arrival)
                 self.last_arrival = arrival
         timeout = (start + 1.0) - time.time()
         if timeout < 0:
             break
Example #4
0
 def wait(self):
     start = time.time()
     timeout = 1.0
     while 1:
         rd, wt, er = select.select([self.sock.socket], [], [], timeout)
         if rd:
             # okay to use time here, because select has told us
             # there is data and we don't care to measure the time
             # it takes the system to give us the packet.
             arrival = time.time()
             try:
                 pkt, who = self.sock.recvfrom(4096)
             except socket.error:
                 continue
             # could also use the ip module to get the payload
             repip = ip.disassemble(pkt)
             try:
                 reply = icmp.disassemble(repip.data)
             except ValueError:
                 continue
             if reply.get_id() == self.pid:
                 self.recv_packet(reply, arrival)
                 self.last_arrival = arrival
         timeout = (start + 1.0) - time.time()
         if timeout < 0:
             break
Example #5
0
    def testUdpPortWronlyParsed(self):
        ip_reply = ip.disassemble(self.pkt)
        icmp_reply = icmp.disassemble(ip_reply.data)                #ICMP is payload of IP
        inner_ip = icmp_reply.get_embedded_ip()

        self.assertEqual('10.249.64.152', inner_ip.src)
        self.assertEqual('207.68.173.76', inner_ip.dst)
        
        udp_in_icmp = udp.disassemble(inner_ip.data, 0)
        self.assertEqual(40164, udp_in_icmp.sport)
        self.assertEqual(33435, udp_in_icmp.dport)
Example #6
0
    def testUdpPortWronlyParsed(self):
        ip_reply = ip.disassemble(self.pkt)
        icmp_reply = icmp.disassemble(ip_reply.data)  #ICMP is payload of IP
        inner_ip = icmp_reply.get_embedded_ip()

        self.assertEqual('10.249.64.152', inner_ip.src)
        self.assertEqual('207.68.173.76', inner_ip.dst)

        udp_in_icmp = udp.disassemble(inner_ip.data, 0)
        self.assertEqual(40164, udp_in_icmp.sport)
        self.assertEqual(33435, udp_in_icmp.dport)
Example #7
0
def loop(hosts, callback, sleep_interval = 1, timeout_interval = 1):
    sendq = []
    recvq = {}

    jitter = 0
    vario = 0.1
    for host in hosts:
        heappush(sendq, (time.time()+sleep_interval+jitter, host))
        jitter += vario

    psocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname('icmp'))
    psocket.setblocking(0)
    poller = select.poll()
    poller.register(psocket.fileno(), select.POLLOUT | select.POLLIN)

    my_id = os.getpid()
    seq = 0

    while True:
        events = poller.poll(1)
        current_time = time.time()
        for fileno, event in events:
            if event & select.POLLIN:
                #curent_time = time.time()
                (data, addr) = psocket.recvfrom(2048)
                (r_id, r_seq, time_sent) = icmp.disassemble(data)
                if r_id:
                    rtt = (current_time - time_sent) * 1000
                    if  r_id == my_id:
                        callback(addr[0], rtt)
                        heappush(sendq, (time.time() + sleep_interval, addr[0]))
                        if addr[0] in recvq:
                            del recvq[addr[0]]
            if event & select.POLLOUT:
                if sendq:
                    (time_to_send, ip) = heappop(sendq)
                    if time_to_send < current_time:
                        icmp_packet = icmp.assemble(ip, my_id, seq, current_time)
                        seq += 1
                        psocket.sendto(icmp_packet, (ip,0))
                        recvq[ip] = current_time + timeout_interval
                    else:
                        heappush(sendq, (time_to_send, ip))

        #TODO optimize here
        for ip in [ host for (host, timeout) in recvq.items() if timeout < current_time ]:
            callback(ip, None)
            heappush(sendq, (current_time + sleep_interval, ip))
            del recvq[ip]

        if seq > 10000:
            seq=0
Example #8
0
 def received(self, pkt, gateway):
     """ Upon received an incoming ICMP, determine if the packet is of our interest
          If it is, populate related fields, and return 1
          otherwise return 0
     """
     
     ip_reply = ip.disassemble(pkt)
     if icmp.HDR_SIZE_IN_BYTES > len(ip_reply.data):
         return 0                #IP payload is not long enough to hold ICMP
  
     try:
         icmp_reply = icmp.disassemble(ip_reply.data)                #ICMP is payload of IP
     except ValueError, msg:
         if DEBUG:
             stdout.write("Bad Packet received!")
         return 0
Example #9
0
    def received(self, pkt, gateway):
        """ Upon received an incoming ICMP, determine if the packet is of our interest
             If it is, populate related fields, and return 1
             otherwise return 0
        """

        ip_reply = ip.disassemble(pkt)
        if icmp.HDR_SIZE_IN_BYTES > len(ip_reply.data):
            return 0  #IP payload is not long enough to hold ICMP

        try:
            icmp_reply = icmp.disassemble(
                ip_reply.data)  #ICMP is payload of IP
        except ValueError, msg:
            if DEBUG:
                stdout.write("Bad Packet received!")
            return 0
Example #10
0
    def received(self, pkt, gateway):
        """ Upon received an incoming ICMP, determine if the packet is of our interest
             If it is, populate related fields, and return 1
             otherwise return 0
        """

        ip_reply = ip.disassemble(pkt)
        if icmp.HDR_SIZE_IN_BYTES > len(ip_reply.data):
            return 0  #IP payload is not long enough to hold ICMP

        icmp_reply = icmp.disassemble(ip_reply.data)  #ICMP is payload of IP

        if DEBUG:
            stdout.write(
                "recvfrom %s: ICMP_type: %d ICMP_code: %d" %
                (gateway, icmp_reply.get_type(), icmp_reply.get_code()))

        # 2 conditions interest us:
        #   1. ICMP_TIMEEXCEED, probe packet dropped by gateway in the middle,
        #      which then send ICMP_TIMEEXCEED back to us
        #   2. ICMP_ECHOREPLY, probe packet reach destination host,
        if (icmp_reply.get_type() == icmp.ICMP_TIMXCEED \
                    and icmp_reply.get_code() == icmp.ICMP_TIMXCEED_INTRANS) \
                    or icmp_reply.get_type() == icmp.ICMP_ECHOREPLY:
            if ip.MIN_HDR_SIZE_IN_BYTES > len(icmp_reply.data):
                return 0  #ICMP payload is not long enough for inner IP

            inner_ip = ip.disassemble(icmp_reply.data)

            if inner_ip.src != self.src_addr or inner_ip.dst != self.dst_addr:
                return 0

            self.gateway = gateway
            self.timestamp_received = time.time()
            if icmp_reply.get_type() == icmp.ICMP_ECHOREPLY:
                self.dst_reached = 1
            return 1

        if self.verbose:  # In verbose mode, ICMP packets other than IME_EXCEEDED and UNREACHABLE are listed
            stdout.write(
                "recvfrom %s: ICMP_type: %d ICMP_code: %d" %
                (gateway, icmp_reply.get_type(), icmp_reply.get_code()))

        return 0
Example #11
0
 def received(self, pkt, gateway):
     """ Upon received an incoming ICMP, determine if the packet is of our interest
          If it is, populate related fields, and return 1
          otherwise return 0
     """
      
     ip_reply = ip.disassemble(pkt)
     if icmp.HDR_SIZE_IN_BYTES > len(ip_reply.data):
         return 0                #IP payload is not long enough to hold ICMP
      
     icmp_reply = icmp.disassemble(ip_reply.data)                #ICMP is payload of IP
      
     if DEBUG:
         stdout.write("recvfrom %s: ICMP_type: %d ICMP_code: %d" % (gateway, icmp_reply.get_type(), icmp_reply.get_code()))
     
     # 2 conditions interest us:
     #   1. ICMP_TIMEEXCEED, probe packet dropped by gateway in the middle,
     #      which then send ICMP_TIMEEXCEED back to us
     #   2. ICMP_ECHOREPLY, probe packet reach destination host, 
     if (icmp_reply.get_type() == icmp.ICMP_TIMXCEED \
                 and icmp_reply.get_code() == icmp.ICMP_TIMXCEED_INTRANS) \
                 or icmp_reply.get_type() == icmp.ICMP_ECHOREPLY:
         if ip.MIN_HDR_SIZE_IN_BYTES > len(icmp_reply.data):
             return 0        #ICMP payload is not long enough for inner IP
                 
         inner_ip = ip.disassemble(icmp_reply.data)
          
         if inner_ip.src != self.src_addr or inner_ip.dst != self.dst_addr:
             return 0
          
         self.gateway = gateway
         self.timestamp_received = time.time()
         if icmp_reply.get_type() == icmp.ICMP_ECHOREPLY:
             self.dst_reached = 1
         return 1
      
     if self.verbose:                # In verbose mode, ICMP packets other than IME_EXCEEDED and UNREACHABLE are listed
         stdout.write("recvfrom %s: ICMP_type: %d ICMP_code: %d" % (gateway, icmp_reply.get_type(), icmp_reply.get_code()))
          
     return 0             
Example #12
0
    def ping(self, packets=1):
        """
        Send ping messages, as many as given with packets parameter.

        Returns a dictionary of results, may raise PingError.
        """

        try:
            packets = int(packets)
            if packets < 0 or packets > MAX_PACKETS:
                raise ValueError
        except ValueError:
            raise PingError('Invalid number of packets: %s' % packets)

        interval = float(self.interval)/1000
        timeout = float(self.timeout)/1000
        last_sent = 0
        while 1:
            now = time.time()
            if self.sent < packets and (last_sent+interval)<now:
                self.__send_packet()
                last_sent = now

            if len(self.times) == packets:
                if filter(lambda t: t+timeout>now, self.times.values())==[]:
                    break

            (rd, wt, er) = select.select([self.socket.socket], [], [], timeout)
            if not rd:
                continue
            arrival = time.time()
            try:
                (pkt, who) = self.socket.recvfrom(4096)
            except socket.error:
                continue

            reply_address = ip.disassemble(pkt)
            try:
                reply = icmp.disassemble(reply_address.data)
            except ValueError:
                print 'Invalid ICMP reply packet received'
                continue

            if reply.get_id() != self.pid:
                print 'PID in response does not match'
                continue
            self.__recv_packet(reply, arrival, timeout)

            if self.sent < packets:
                continue

            if len(self.deltas)+len(self.timed_out) == packets:
                break

        received = len(self.deltas)
        loss = (float(packets-received)/float(packets))*100

        if len(self.deltas) == 0:
            summary = {
                'min': None,
                'max': None,
                'average': None,
                'sent': packets,
                'received': len(self.deltas) + len(self.timed_out),
                'packetloss': loss
            }

        else:
            summary = {
                'min': min(self.deltas),
                'max': max(self.deltas),
                'average': reduce(lambda x, y: x+y, self.deltas) / len(self.deltas),
                'sent': packets,
                'received': received,
                'packetloss': loss
            }

        self.__reset_counters()
        return summary
Example #13
0
 def testTimeExceeded(self):
     buf = icmp.assemble(self.time_exceeded, cksum=1)
     new = icmp.disassemble(buf, cksum=1)
     self.assertEqual(self.time_exceeded, new)
Example #14
0
 def testUnreachableNotCksum(self):
     buf = icmp.assemble(self.unreachable, cksum=0)
     new = icmp.disassemble(buf, cksum=0)
     self.assertEqual(self.unreachable, new)
Example #15
0
 def testEchoReplyNotCksum(self):
     buf = icmp.assemble(self.echo_reply, cksum=0)
     new = icmp.disassemble(buf, cksum=0)
     self.assertEqual(self.echo_reply, new)
Example #16
0
 def testEcho(self):
     buf = icmp.assemble(self.echo, cksum=1)
     new = icmp.disassemble(buf, cksum=1)
     self.assertEqual(self.echo, new)
Example #17
0
    def ping(self, packets=1):
        """
        Send ping messages, as many as given with packets parameter.

        Returns a dictionary of results, may raise PingError.
        """

        try:
            packets = int(packets)
            if packets < 0 or packets > MAX_PACKETS:
                raise ValueError
        except ValueError:
            raise PingError('Invalid number of packets: %s' % packets)

        interval = float(self.interval) / 1000
        timeout = float(self.timeout) / 1000
        last_sent = 0
        while 1:
            now = time.time()
            if self.sent < packets and (last_sent + interval) < now:
                self.__send_packet()
                last_sent = now

            if len(self.times) == packets:
                if filter(lambda t: t + timeout > now,
                          self.times.values()) == []:
                    break

            (rd, wt, er) = select.select([self.socket.socket], [], [], timeout)
            if not rd:
                continue
            arrival = time.time()
            try:
                (pkt, who) = self.socket.recvfrom(4096)
            except socket.error:
                continue

            reply_address = ip.disassemble(pkt)
            try:
                reply = icmp.disassemble(reply_address.data)
            except ValueError:
                print 'Invalid ICMP reply packet received'
                continue

            if reply.get_id() != self.pid:
                print 'PID in response does not match'
                continue
            self.__recv_packet(reply, arrival, timeout)

            if self.sent < packets:
                continue

            if len(self.deltas) + len(self.timed_out) == packets:
                break

        received = len(self.deltas)
        loss = (float(packets - received) / float(packets)) * 100

        if len(self.deltas) == 0:
            summary = {
                'min': None,
                'max': None,
                'average': None,
                'sent': packets,
                'received': len(self.deltas) + len(self.timed_out),
                'packetloss': loss
            }

        else:
            summary = {
                'min':
                min(self.deltas),
                'max':
                max(self.deltas),
                'average':
                reduce(lambda x, y: x + y, self.deltas) / len(self.deltas),
                'sent':
                packets,
                'received':
                received,
                'packetloss':
                loss
            }

        self.__reset_counters()
        return summary