|
View:
New views
3 Messages
—
Rating Filter:
Alert me
|
|
|
Python ICMPI need to create a class that sends ICMP packets from either a Windows or Linux host. I found a few, but I like this one the best: #!/usr/bin/env python However, there is one small problem. It works on Windows, but not on Linux. When I run this on Linux, the host sends the requests but never gets a response. Not one. I've compared the output from both hosts in Wireshark and the only difference I see is the identification field in the IP header. Packets frmo Linux show 0 but packets from Windows have an incrementing number. I'd like to have this working on both. I prefer this code since it's pure Python, doesn't shell out (popen) and I can call/import it into another program. Any ideas? _______________________________________________ Tutor maillist - Tutor@... To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor |
|
|
Re: Python ICMPDo you testing it with root account ? Linux wants root permission to
receive and normally send to icmp packets. On Fri, 2009-11-06 at 14:37 -0500, chris hallman wrote: > > I need to create a class that sends ICMP packets from either a Windows > or Linux host. I found a few, but I like this one the best: > > > #!/usr/bin/env python > > > > """ > A pure python ping implementation using raw socket. > > > > Note that ICMP messages can only be sent from processes running as root. > > > Derived from ping.c distributed in Linux's netkit. That code is > copyright (c) 1989 by The Regents of the University of California. > > > > That code is in turn derived from code written by Mike Muuss of the > US Army Ballistic Research Laboratory in December, 1983 and > placed in the public domain. They have my thanks. > > Bugs are naturally mine. I'd be glad to hear about them. There are > > > > certainly word - size dependenceies here. > > Copyright (c) Matthew Dixon Cowles, <http://www.visi.com/~mdc/>. > Distributable under the terms of the GNU General Public License > > > > version 2. Provided with no warranties of any sort. > > Original Version from Matthew Dixon Cowles: > -> ftp://ftp.visi.com/users/mdc/ping.py > > > > > Rewrite by Jens Diemer: > -> http://www.python-forum.de/post-69122.html#69122 > > > Revision history > ~~~~~~~~~~~~~~~~ > > > > > May 30, 2007 > little rewrite by Jens Diemer: > - change socket asterisk import to a normal import > - replace time.time() with time.clock() > - delete "return None" (or change to "return" only) > > > > - in checksum() rename "str" to "source_string" > > November 22, 1997 > Initial hack. Doesn't do much, but rather than try to guess > what features I (or others) will want in the future, I've only > > > > put in what I need now. > > December 16, 1997 > For some reason, the checksum bytes are in the wrong order when > this is run under Solaris 2.X for SPARC but it works right under > Linux x86. Since I don't know just what's wrong, I'll swap the > > > > bytes always and then do an htons(). > > December 4, 2000 > Changed the struct.pack() calls to pack the checksum and ID as > unsigned. My thanks to Jerome Poincheval for the fix. > > > Last commit info: > > > > ~~~~~~~~~~~~~~~~~ > $LastChangedDate: $ > $Rev: $ > $Author: $ > """ > > > import os, sys, socket, struct, select, time > > > > > # From /usr/include/linux/icmp.h; your milage may vary. > ICMP_ECHO_REQUEST = 8 # Seems to be the same on Solaris. > > > > > > def checksum(source_string): > """ > > > > I'm not too confident that this is right but testing seems > to suggest that it gives the same answers as in_cksum in ping.c > """ > 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 > > # Swap bytes. Bugger me if I know why. > > > > answer = answer >> 8 | (answer << 8 & 0xff00) > > > > > return answer > > > def receive_one_ping(my_socket, ID, timeout): > > > > """ > receive the ping from the socket. > """ > timeLeft = timeout > while True: > > > > startedSelect = time.clock() > whatReady = select.select([my_socket], [], [], timeLeft) > > > > howLongInSelect = (time.clock() - startedSelect) > > > > if whatReady[0] == []: # Timeout > > > > return > > timeReceived = time.clock() > > > > recPacket, addr = my_socket.recvfrom(1024) > icmpHeader = recPacket[20:28] > > > > type, code, checksum, packetID, sequence = struct.unpack( > > > > "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 > > > def send_one_ping(my_socket, dest_addr, ID): > > > > """ > Send one ping to the given >dest_addr<. > """ > dest_addr = socket.gethostbyname(dest_addr) > > > > > # Header is type (8), code (8), checksum (16), id (16), sequence (16) > my_checksum = 0 > > > > > # Make a dummy heder with a 0 checksum. > 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.clock()) + data > > > > > # Calculate the checksum on the data and the dummy header. > my_checksum = checksum(header + data) > > > > > # Now that we have the right checksum, we put that in. It's just easier > # to make up a new header than to stuff it into the dummy. > > > > header = struct.pack( > "bbHHh", ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), ID, 1 > > > > ) > packet = header + data > my_socket.sendto(packet, (dest_addr, 1)) # Don't know about the 1 > > > > > > def do_one(dest_addr, timeout): > """ > > > > Returns either the delay (in seconds) or none on timeout. > """ > 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 be sent from processes" > " running as root." > > > > ) > raise socket.error(msg) > > > > raise # raise the original error > > 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 verbose_ping(dest_addr, timeout = 2, count = 4): > > > > """ > Send >count< ping to >dest_addr< with the given >timeout< and display > the result. > """ > for i in xrange(count): > > > > print "ping %s..." % dest_addr, > try: > > > > delay = do_one(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 * 1000 > print "get ping in %0.4fms" % delay > > > > > > if __name__ == '__main__': > > > > verbose_ping("heise.de") > verbose_ping("google.com") > > > > verbose_ping("a-test-url-taht-is-not-available.com") > > > > verbose_ping("192.168.1.1") > > However, there is one small problem. It works on Windows, but not on > Linux. When I run this on Linux, the host sends the requests but never > gets a response. Not one. I've compared the output from both hosts in > Wireshark and the only difference I see is the identification field in > the IP header. Packets frmo Linux show 0 but packets from Windows have > an incrementing number. > > I'd like to have this working on both. I prefer this code since it's > pure Python, doesn't shell out (popen) and I can call/import it into > another program. > > Any ideas? > > _______________________________________________ > Tutor maillist - Tutor@... > To unsubscribe or change subscription options: > http://mail.python.org/mailman/listinfo/tutor _______________________________________________ Tutor maillist - Tutor@... To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor |
|
|
Re: Python ICMP[snip]
... (code from OP) ... [/snip] > However, there is one small problem. It works on Windows, but not on Linux. > When I run this on Linux, the host sends the requests but never gets a > response. Not one. I've compared the output from both hosts in Wireshark and > the only difference I see is the identification field in the IP header. > Packets frmo Linux show 0 but packets from Windows have an incrementing > number. > > I'd like to have this working on both. I prefer this code since it's pure > Python, doesn't shell out (popen) and I can call/import it into another > program. > > Any ideas? I haven't read through the code, but something you might try if you haven't already just to rule out other potential problems: - Try to use the system command ping(8) from a command shell like bash or tcsh, as the the same userID as your program will be running at: (tcsh shell prompt)> ping -c 3 www.google.com If that doesn't get a response, you likely have a firewall issue. Just a thought. -Modulok- _______________________________________________ Tutor maillist - Tutor@... To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor |
| Free embeddable forum powered by Nabble | Forum Help |