Sending ECHO_REQUEST (pinging) with python

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Thomas Dybdahl Ahle

    #1

    Sending ECHO_REQUEST (pinging) with python

    Hi, I've writing a python application in which I'd like to have a small
    "ping label", to always tell the current ping time to the server.

    It seems however that I have to be root to send those imcp packages, but
    I guess there must be a workaround since I can easily use the "ping"
    command as ordinary user.

    Do anybody know how to do this in python?
  • Michael Bentley

    #2
    Re: Sending ECHO_REQUEST (pinging) with python

    On Mar 26, 2007, at 1:30 AM, Thomas Dybdahl Ahle wrote:
    Hi, I've writing a python application in which I'd like to have a
    small
    "ping label", to always tell the current ping time to the server.
    >
    It seems however that I have to be root to send those imcp
    packages, but
    I guess there must be a workaround since I can easily use the "ping"
    command as ordinary user.
    >
    Do anybody know how to do this in python?
    >
    This won't solve your privileges issue, but this seems to get the
    ping time to server:

    import socket
    import os
    import sys
    import struct
    import time
    import select

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

    # From /usr/include/linux/icmp.h; your milage may vary.
    ICMP_ECHO_REQUE ST = 8 # Seems to be the same on Solaris.

    # 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
    def checksum(str):
    csum = 0
    countTo = (len(str) / 2) * 2
    count = 0
    while count < countTo:
    thisVal = ord(str[count+1]) * 256 + ord(str[count])
    csum = csum + thisVal
    csum = csum & 0xffffffffL # Necessary?
    count = count + 2

    if countTo < len(str):
    csum = csum + ord(str[len(str) - 1])
    csum = csum & 0xffffffffL # Necessary?

    csum = (csum >16) + (csum & 0xffff)
    csum = csum + (csum >16)
    answer = ~csum
    answer = answer & 0xffff

    # Swap bytes. Bugger me if I know why.
    answer = answer >8 | (answer << 8 & 0xff00)

    return answer

    def receiveOnePing( mySocket, ID, timeout):
    timeLeft = timeout

    while 1:
    startedSelect = time.time()
    whatReady = select.select([mySocket], [], [], timeLeft)
    howLongInSelect = (time.time() - startedSelect)

    if whatReady[0] == []: # Timeout
    return -1

    timeReceived = time.time()
    recPacket, addr = mySocket.recvfr om(1024)
    icmpHeader = recPacket[20:28]
    typ, 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 -1

    def sendOnePing(myS ocket, destAddr, ID):
    # Header is type (8), code (8), checksum (16), id (16), sequence
    (16)
    myChecksum = 0

    # Make a dummy heder with a 0 checksum.
    header = struct.pack("bb HHh", ICMP_ECHO_REQUE ST, 0, myChecksum,
    ID, 1)
    bytesInDouble = struct.calcsize ("d")
    data = (192 - bytesInDouble) * "Q"
    data = struct.pack("d" , time.time()) + data

    # Calculate the checksum on the data and the dummy header.
    myChecksum = 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.
    if sys.platform == 'darwin':
    myChecksum = socket.htons(my Checksum) & 0xffff
    else:
    myChecksum = socket.htons(my Checksum)

    header = struct.pack("bb HHh", ICMP_ECHO_REQUE ST, 0,
    myChecksum, ID, 1)

    packet = header + data
    mySocket.sendto (packet, (destAddr, 1)) # Don't know about the 1

    def doOne(destAddr, timeout=10):
    # Returns either the delay (in seconds) or none on timeout.
    icmp = socket.getproto byname("icmp")
    mySocket = socket.socket(s ocket.AF_INET,s ocket.SOCK_RAW, icmp)
    myID = os.getpid() & 0xFFFF
    sendOnePing(myS ocket, destAddr, myID)
    delay = receiveOnePing( mySocket, myID, timeout)
    mySocket.close( )

    return delay


    def ping(host, timeout=1):
    dest = socket.gethostb yname(host)
    delay = doOne(dest, timeout)
    return delay


    Hope this helps,
    Michael

    ---
    The Rules of Optimization are simple.
    Rule 1: Don't do it.
    Rule 2 (for experts only): Don't do it yet.
    -- Michael A. Jackson , "Principles of
    Program Design", 1975.


    Comment

    • Michael Bentley

      #3
      Re: Sending ECHO_REQUEST (pinging) with python


      On Mar 26, 2007, at 1:30 AM, Thomas Dybdahl Ahle wrote:
      >
      It seems however that I have to be root to send those imcp
      packages, but
      I guess there must be a workaround since I can easily use the "ping"
      command as ordinary user.
      >
      The workaround your ping command is using btw, is probably running
      suid root.

      hth,
      Michael

      ---
      Simplicity is the ultimate sophistication.
      -Leonardo da Vinci



      Comment

      • Michal 'vorner' Vaner

        #4
        Re: Sending ECHO_REQUEST (pinging) with python

        On Mon, Mar 26, 2007 at 08:30:16AM +0200, Thomas Dybdahl Ahle wrote:
        Hi, I've writing a python application in which I'd like to have a small
        "ping label", to always tell the current ping time to the server.

        It seems however that I have to be root to send those imcp packages, but
        I guess there must be a workaround since I can easily use the "ping"
        command as ordinary user.

        Do anybody know how to do this in python?
        You need root for that and the ping command is allowed to have them by
        suid bit. You can execute ping from inside python and use ping as is, if
        you need.

        --
        This is a terroristic email. It will explode in 10 minutes,
        if you do not close it in the meantime.

        Michal "vorner" Vaner

        -----BEGIN PGP SIGNATURE-----
        Version: GnuPG v2.0.3 (GNU/Linux)

        iD8DBQBGB5FS7/oWwynB3bIRAoqwA J43yY0CqUfwivEG QHItkpVLPvpYygC fUZ6W
        haX6LC/gBtEUnS7Hc3CGUN k=
        =jRXs
        -----END PGP SIGNATURE-----

        Comment

        • Nick Craig-Wood

          #5
          Re: Sending ECHO_REQUEST (pinging) with python

          Michael Bentley <michael@jedimi ndworks.comwrot e:
          On Mar 26, 2007, at 1:30 AM, Thomas Dybdahl Ahle wrote:
          It seems however that I have to be root to send those imcp
          packages, but I guess there must be a workaround since I can
          easily use the "ping" command as ordinary user.
          >
          The workaround your ping command is using btw, is probably running
          suid root.
          Under linux the only priviledge you need is CAP_NET_RAW. It is
          possible to give this to a process - a bit of searching with google
          will show you how!

          --
          Nick Craig-Wood <nick@craig-wood.com-- http://www.craig-wood.com/nick

          Comment

          • Thomas Dybdahl Ahle

            #6
            Re: Sending ECHO_REQUEST (pinging) with python

            Den Mon, 26 Mar 2007 11:24:34 +0200 skrev Michal 'vorner' Vaner:
            On Mon, Mar 26, 2007 at 08:30:16AM +0200, Thomas Dybdahl Ahle wrote:
            >Do anybody know how to do this in python?
            You need root for that and the ping command is allowed to have them by
            suid bit. You can execute ping from inside python and use ping as is, if
            you need.
            Yeah, I could execute ping, but it would lock me harder to the platform.

            Comment

            • Thomas Dybdahl Ahle

              #7
              Re: Sending ECHO_REQUEST (pinging) with python

              Den Mon, 26 Mar 2007 06:30:04 -0500 skrev Nick Craig-Wood:
              Michael Bentley <michael@jedimi ndworks.comwrot e:
              > On Mar 26, 2007, at 1:30 AM, Thomas Dybdahl Ahle wrote:
              It seems however that I have to be root to send those imcp packages,
              but I guess there must be a workaround since I can easily use the
              "ping" command as ordinary user.
              >>
              > The workaround your ping command is using btw, is probably running
              > suid root.
              >
              Under linux the only priviledge you need is CAP_NET_RAW. It is possible
              to give this to a process - a bit of searching with google will show you
              how!
              How, I did google, but I wasn't able to find any way to do this in
              python..

              Comment

              • Nick Craig-Wood

                #8
                Re: Sending ECHO_REQUEST (pinging) with python

                Jean-Paul Calderone <exarkun@divmod .comwrote:
                On Mon, 26 Mar 2007 16:50:33 +0200, Thomas Dybdahl Ahle <lobais@gmail.c omwrote:
                Den Mon, 26 Mar 2007 06:30:04 -0500 skrev Nick Craig-Wood:
                Under linux the only priviledge you need is CAP_NET_RAW. It is possible
                to give this to a process - a bit of searching with google will show you
                how!
                How, I did google, but I wasn't able to find any way to do this in
                python..
                >
                You need a sendmsg wrapper (there are several, none in the stdlib), then
                you need a privileged process which is willing to give you the privilege.
                >
                It's pretty inconvenient.
                You start a user process with an extra capability using want using
                libcap and the execcap and sucap tools.

                --
                Nick Craig-Wood <nick@craig-wood.com-- http://www.craig-wood.com/nick

                Comment

                • Jorgen Grahn

                  #9
                  Re: Sending ECHO_REQUEST (pinging) with python

                  On Mon, 26 Mar 2007 16:50:09 +0200, Thomas Dybdahl Ahle <lobais@gmail.c omwrote:
                  Den Mon, 26 Mar 2007 11:24:34 +0200 skrev Michal 'vorner' Vaner:
                  >On Mon, Mar 26, 2007 at 08:30:16AM +0200, Thomas Dybdahl Ahle wrote:
                  >
                  >>Do anybody know how to do this in python?
                  >
                  >You need root for that and the ping command is allowed to have them by
                  >suid bit. You can execute ping from inside python and use ping as is, if
                  >you need.
                  >
                  Yeah, I could execute ping, but it would lock me harder to the platform.
                  True; Linux ping and Solaris ping have incompatible flags and output.
                  I even believe several implementations are in use on Linux. Then add
                  Windows to the mix ...

                  -Jorgen

                  --
                  // Jorgen Grahn <grahn@ Ph'nglui mglw'nafh Cthulhu
                  \X/ snipabacken.dyn dns.org R'lyeh wgah'nagl fhtagn!

                  Comment

                  Working...