Seite 1 von 2

Ping (ICMP)?

Verfasst: Freitag 21. Juli 2006, 08:24
von movies1978
Gibt es unter Python ein Möglichkeit, möglichst ohne externe Bibliotheken. Pings abzusenden? Oder ist die einzige Möglichkeit in dem Bereich Sockets? Könnte man mit Sockets denn überhaupt ICMP Pakete generieren?

Mfg
Mathias

Verfasst: Freitag 21. Juli 2006, 12:00
von Python 47
Ich weiß nicht ob du das suchst, aber:

Code: Alles auswählen

import os
os.system('ping 127.0.0.1')

Verfasst: Freitag 21. Juli 2006, 14:17
von rayo
Hi

Das kannst du mit Raw-Sockets machen, ist aber aufwendig. Musst halt das Packet selber generieren.

Hier siehst du wie:
ftp://ftp.visi.com/users/mdc/ping.py

Gruss

Verfasst: Freitag 21. Juli 2006, 14:42
von movies1978
Hi leider funktioniert keiner der beiden Lösungen auf meinem Symbian Smartphone. Dies hängt wahrscheinlich damit zusammen, dass die Implementation noch beta is und einige Funktionen nicht gar implementiert sind.
Mathias

Verfasst: Freitag 21. Juli 2006, 18:38
von Python 47
movies1978 hat geschrieben:Hi leider funktioniert keiner der beiden Lösungen auf meinem Symbian Smartphone. Dies hängt wahrscheinlich damit zusammen, dass die Implementation noch beta is und einige Funktionen nicht gar implementiert sind.
Mathias
Das hättest du auch mal sagen können, dass das für ein Smartphone gedacht ist. Mein Vorschlag ist natürlich für ein Windows System gedacht. :?

Verfasst: Freitag 21. Juli 2006, 22:08
von jAN
kann man auf dem smartphone irgendwie über eine console ienne ping befehl absenden?

Re: Ping (ICMP) ????

Verfasst: Freitag 21. Juli 2006, 22:56
von gerold
movies1978 hat geschrieben:Pings abzusenden?
Hi Mathias!

Ich habe das etwas mit Google gefunden. Vielleicht bringt es dich weiter:
http://www.thescripts.com/forum/thread21672.html
http://www.python.org/~jeremy/python.html

mfg
Gerold
:-)

Verfasst: Mittwoch 30. Mai 2007, 08:17
von jens
EDIT (jens): Sourcecode ist nun auch in meinem SVN: http://pylucid.net:8080/pylucid/browser ... ts/ping.py
Ich hab den sourcecode mal umgeschrieben:

Code: Alles auswählen

#!/usr/bin/env python

#
# 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
#

# 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.

# Note that ICMP messages can only be sent from processes running
# as root.

# 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.
#

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")
    my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
    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
    print


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")
Beispiel Ausgabe:

Code: Alles auswählen

ping heise.de... get ping in 14.6611ms
ping heise.de... get ping in 14.3045ms
ping heise.de... get ping in 14.6112ms
ping heise.de... get ping in 14.0498ms

ping google.com... get ping in 115.8470ms
ping google.com... get ping in 115.5172ms
ping google.com... get ping in 115.3419ms
ping google.com... get ping in 115.0621ms

ping a-test-url-taht-is-not-available.com... failed. (socket error: 'getaddrinfo failed')

ping 192.168.1.1... failed. (timeout within 2sec.)
ping 192.168.1.1... failed. (timeout within 2sec.)
ping 192.168.1.1... failed. (timeout within 2sec.)
ping 192.168.1.1... failed. (timeout within 2sec.)
Ich weiß nicht was man noch verbessern könnte. In den ursprünglichen Kommentaren steht ja, das der Author auch nicht so ganz genau weiß, was er da gemacht hat ;)
Es funktioniert aber recht gut...

Alternativen findet man noch einige: http://www.google.de/search?q=ping.py

Verfasst: Mittwoch 30. Mai 2007, 13:41
von Y0Gi
Ich habe seinerzeit mal ein kleines Tool mit dem Aussehen eines Instant-Messengers gebastelt, das Hosts in Intervallen pingt. Dazu habe ich noch die Implementierungen folgender Personen/Projekte auf meiner Platte, die ich mir dazu angesehen habe: Jeremy Hylton, Lars Strand, Impacket, Scapy. Die eine oder andere mehr wird es wohl noch geben.

Über Raw-Sockets lässt sich das auch lösen (bzw. tun das wohl die meisten oder gar alle der Implementierungen auch), allerdings soll das wohl ab WinXP SP2 nicht mehr möglich sein, weil Raw-Sockets "verboten" wurden. Inwieweit das bei Symbian oder Series 60 aussieht, kann ich dir aber nicht sagen.

Verfasst: Mittwoch 30. Mai 2007, 14:03
von jens
Y0Gi hat geschrieben:allerdings soll das wohl ab WinXP SP2 nicht mehr möglich sein, weil Raw-Sockets "verboten" wurden.
Mein Skript läuft einwandfrei auf XP mit SP2... Ich kann mir vorstellen, das die Windows-Firewall evtl. dazwischen funkt. Die nutzte ich allerdings nicht ;)

Verfasst: Mittwoch 30. Mai 2007, 14:33
von Leonidas
jens hat geschrieben:
Y0Gi hat geschrieben:allerdings soll das wohl ab WinXP SP2 nicht mehr möglich sein, weil Raw-Sockets "verboten" wurden.
Mein Skript läuft einwandfrei auf XP mit SP2...
Nutzt du etwa Raw-Sockets?

Verfasst: Mittwoch 30. Mai 2007, 18:09
von lunar
Leonidas hat geschrieben:
jens hat geschrieben:
Y0Gi hat geschrieben:allerdings soll das wohl ab WinXP SP2 nicht mehr möglich sein, weil Raw-Sockets "verboten" wurden.
Mein Skript läuft einwandfrei auf XP mit SP2...
Nutzt du etwa Raw-Sockets?
Ja, eigentlich schon... socket.SOCK_RAW erzeugt Raw Sockets. Mein Linux zumindest verweigert die Ausführung ohne root-Rechte.

Verfasst: Mittwoch 30. Mai 2007, 18:36
von Grossmeister_C
"However, the ability to send traffic over raw sockets has been restricted in two ways:

* TCP data cannot be sent over raw sockets.
* UDP datagrams with invalid source addresses cannot be sent over raw sockets. The IP source address for any outgoing UDP datagram must exist on a network interface or the datagram is dropped. "


http://blogs.msdn.com/michael_howard/ar ... 13611.aspx

Verfasst: Mittwoch 30. Mai 2007, 21:05
von lunar
Grossmeister_C hat geschrieben:"However, the ability to send traffic over raw sockets has been restricted in two ways:

* TCP data cannot be sent over raw sockets.
* UDP datagrams with invalid source addresses cannot be sent over raw sockets. The IP source address for any outgoing UDP datagram must exist on a network interface or the datagram is dropped. "

http://blogs.msdn.com/michael_howard/ar ... 13611.aspx
Und was genau hat das mit Pings zu tun? ICMP setzt eine Ebene tiefer an als TCP oder UDP. Die Einschränkungen betreffen ICMP Pakete (also auch Pings) nicht.

Verfasst: Mittwoch 30. Mai 2007, 21:16
von Grossmeister_C
Ok da haste auch wieder Recht. Ich versuche nur gerade das gesamte Dokument zu finden von dem er da redet, dem "Changes in functionality...". Aber entweder bin ich blind oder das ist nicht mehr zu finden.

Verfasst: Mittwoch 30. Mai 2007, 23:16
von Leonidas
lunar hat geschrieben:Und was genau hat das mit Pings zu tun? ICMP setzt eine Ebene tiefer an als TCP oder UDP. Die Einschränkungen betreffen ICMP Pakete (also auch Pings) nicht.
Ergo das erklärt, warum das Programm auch mit SP2 funktioniert.

Wobei, ich finde die Idee Raw-Sockets zu beschneiden als Schutz gegen was auch immer ziemlich bescheuert. Würde mich interessieren, wie viel das gebracht hat.

Verfasst: Donnerstag 31. Mai 2007, 18:25
von Y0Gi
Irgendwer, ich glaube ein sogar recht bekannter und respektierter Autor, hat sich mal darüber ausgelassen, dass Windows überhaupt User-programmierbare Raw Sockets eingeführt hat. Grund war wohl, dass es Malware-Autoren und Spammern weitreichende Möglichkeiten an die Hand gibt, kompromittierte Zombie-Rechner noch umfassender und verdeckter zu missbrauchen.

Verfasst: Freitag 1. Juni 2007, 12:03
von Actimehl
Ja wegen der Misbrauchsmöglichkeiten haben die das gemacht, auch wenn es sinnlos ist. Die Leute die Schaden anrichten wollen, können das immer noch und die Leute die das eventuell brauchen sind gekniffen.

Hab von nem Programm gelesen, dass raw-Sockets brauchte und dann nicht mehr funktioniert hat, der Workaround unter Windows: das Programm sendet jetzt raw-Ethernetframes und kann dann wieder alles machen, ergo nur eine lästige Einschränkung aber keine wirksame.

Verfasst: Freitag 1. Juni 2007, 17:58
von lunar
Leonidas hat geschrieben:Wobei, ich finde die Idee Raw-Sockets zu beschneiden als Schutz gegen was auch immer ziemlich bescheuert. Würde mich interessieren, wie viel das gebracht hat.
Naja, irgendwas mussten sie ja tun ;)

Unter Linux sind Raw-Sockets ja auch eingeschränkt, indem sie dem root vorbehalten sind... dumm ist halt nur, dass unter Windows jeder als "root" unterwegs ist ;)

Verfasst: Mittwoch 7. November 2007, 16:57
von jens
Nur zur Info, ping.py ist nun auch in meinem SVN zu finden ;)

http://pylucid.net:8080/pylucid/browser ... ts/ping.py