Jamesla
Jamesla

Reputation: 1418

ICMP traceroute in Python

I am trying to implement an ICMP based Traceroute in Python.

I found a very helpful guide ( https://blogs.oracle.com/ksplice/entry/learning_by_doing_writing_your ) that has allowed me to create a UDP based Traceroute (code below) so just needs modification. I have tried changing the send socket to ICMP however I can't get anything to run without exceptions.

Note - The below code works however this is a UDP traceroute (sends a UDP packet and receives an ICMP one) and I need my program to send an ICMP packet and receive an ICMP packet. Essentially the UDP socket needs to be changed for an ICMP one.

I guess this isn't the most common thing to try and achieve and am having trouble researching on the net on how to do this. If anybody can provide some insight it would be REALLY appreciated :-)

#!/usr/bin/python

    import socket

    def main(dest_name):
        dest_addr = socket.gethostbyname(dest_name)
        port = 33434
        max_hops = 30
        icmp = socket.getprotobyname('icmp')
        udp = socket.getprotobyname('udp')
        ttl = 1
        while True:
            recv_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
            send_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, udp)
            send_socket.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
            recv_socket.bind(("", port))
            send_socket.sendto("", (dest_name, port))
            curr_addr = None
            curr_name = None
            try:
                _, curr_addr = recv_socket.recvfrom(512)
                curr_addr = curr_addr[0]
                try:
                    curr_name = socket.gethostbyaddr(curr_addr)[0]
                except socket.error:
                    curr_name = curr_addr
            except socket.error:
                pass
            finally:
                send_socket.close()
                recv_socket.close()

            if curr_addr is not None:
                curr_host = "%s (%s)" % (curr_name, curr_addr)
            else:
                curr_host = "*"
            print "%d\t%s" % (ttl, curr_host)

            ttl += 1
            if curr_addr == dest_addr or ttl > max_hops:
                break

    if __name__ == "__main__":
        main('google.com')

Upvotes: 0

Views: 3507

Answers (1)

user590028
user590028

Reputation: 11738

I think udp is your best approach

Due to RFC 791, traceroute was ineffective while sending icmp packets, causing the original author Van Jacobson to reimplement using udp. Checkout the footnote on this page for further clarification http://www.inetdaemon.com/tutorials/troubleshooting/tools/traceroute/definition.shtml

If you still insist on sending icmp, try this library

http://code.activestate.com/recipes/409689-icmplib-library-for-creating-and-reading-icmp-pack/

Upvotes: 4

Related Questions