How to fix SOCK_RAW not reading, writes fine, but will not read

0

Trying to make an ICMP request on windows 10 pro, SOCK_RAW will not read, but writes fine. How can I fix this so it reads and writes?

Ran using admin privileges, and I've tried running without firewall on with no avail

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

ICMP_ECHO_REQUEST = 8

def checksum(string):
    csum = 0
    countTo = (len(string) // 2) * 2
    count = 0

    while count < countTo:
        thisVal = ord(string[count+1]) * 256 + ord(string[count])
        csum = csum + thisVal
        csum = csum & 0xffffffff
        count = count + 2

    if countTo < len(string):
        csum = csum + ord(string[len(string) - 1])
        csum = csum & 0xffffffff
    csum = (csum >> 16) + (csum & 0xffff)
    csum = csum + (csum >> 16)
    answer = ~csum
    answer = answer & 0xffff
    answer = answer >> 8 | (answer << 8 & 0xff00)

    return answer

def receiveOnePing(mySocket, ID, timeout, destAddr):
    timeLeft = timeout
    while 1:
        startedSelect = time.time()
        whatReady = select.select([mySocket], [], [], timeLeft)
        howLongInSelect = (time.time() - startedSelect)
        print(whatReady)
        if whatReady[0] == []: # Timeout
            return "Request timed out."

        timeReceived = time.time()
        recPacket, addr = mySocket.recvfrom(1024)

        #Fill in start
        rtype, code, checksum, recID, sequence = struct.unpack("bbHHh", recPacket[20:28])
        if recID != ID or code != 0 or type !=0:
            return "there was an error"
        origin = struct.unpack('b', recPacket[28:])
        rtt = timeReceived - origin
        return ('rtt {} ms', rtt)
        #Fetch the ICMP header from the IP packet

        #Fill in end
        timeLeft = timeLeft - howLongInSelect

        if timeLeft <= 0:
            return "Request timed out."

def sendOnePing(mySocket, destAddr, ID):
    # Header is type (8), code (8), checksum (16), id (16), sequence (16)

    myChecksum = 0

    # Make a dummy header with a 0 checksum
    # struct -- Interpret strings as packed binary data
    header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
    data = struct.pack("d", time.time())
    # Calculate the checksum on the data and the dummy header.
    myChecksum = checksum(str(header + data))

    # Get the right checksum, and put in the header
    if sys.platform == 'darwin':
        # Convert 16-bit integers from host to network byte order
        myChecksum = socket.htons(myChecksum) & 0xffff
    else:
        myChecksum = socket.htons(myChecksum)

    header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
    packet = header + data

    mySocket.sendto(packet, (destAddr, 1)) # AF_INET address must be tuple, not str
    # Both LISTS and TUPLES consist of a number of objects
    # which can be referenced by their position number within the object.

def doOnePing(destAddr, timeout):
    icmp = socket.getprotobyname("icmp")

    # SOCK_RAW is a powerful socket type. For more details: http://sockraw.org/papers/sock_raw
    try:
        mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
    except socket.error as e:
        if e.errno == 1:
            e.msg += "ICMP messages con only be sent from root user processes"
            raise socket.error(e.msg)
    except Exception as e:
        print ("Exception %s" %(e))
    myID = os.getpid() & 0xFFFF # Return the current process i

    sendOnePing(mySocket, destAddr, myID)

    delay = receiveOnePing(mySocket, myID, timeout, destAddr)

    mySocket.close()

    return delay

def ping(host, timeout=1):
    # timeout=1 means: If one second goes by without a reply from the server,
    # the client assumes that either the client's ping or the server's pong is lost
    dest = socket.gethostbyname(host)

    print("Pinging " + dest + " using Python:")
    print("")

    # Send ping requests to a server separated by approximately one second
    while 1 :
        delay = doOnePing(dest, timeout)
        print(delay)
        time.sleep(1)# one second
    return delay

ping('127.0.0.1', 32)

My expected results are that I am able to read on the socket, but select.select says that I can't read on the socket.

python-3.x
sockets
raw-sockets
asked on Stack Overflow Apr 12, 2019 by Matt Deleeuw

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0