Skip to content

Instantly share code, notes, and snippets.

@drdavella
Created September 25, 2018 21:05
Show Gist options
  • Save drdavella/3686138dd74b890ad670582fc2c8fe96 to your computer and use it in GitHub Desktop.
Save drdavella/3686138dd74b890ad670582fc2c8fe96 to your computer and use it in GitHub Desktop.
WIP implementation of ping in Python
#!/usr/bin/env python3
import struct
from argparse import ArgumentParser
from socket import socket, AF_INET, SOCK_DGRAM, IPPROTO_ICMP
ICMP_ECHO_REQUEST = 8
def ip_checksum(databuf, s=0):
def carry_around_add(a, b):
c = a + b
return (c & 0xffff) + (c >> 16)
for i in range(0, len(databuf), 2):
w = (databuf[i] << 8) + databuf[i + 1]
s = carry_around_add(s, w)
s = ~s & 0xffff
return s
def ping_once(sock):
checksum = 0
packet = bytearray(struct.pack('!bbHHh', ICMP_ECHO_REQUEST, 0, checksum, 1, 0))
packet += bytearray([x for x in range(ord('A'), ord('Z')+1)])
checksum = ip_checksum(packet)
packet[2:4] = checksum.to_bytes(2, 'big')
sock.send(packet)
result, sender = sock.recvfrom(1024)
result = bytearray(result)
checksum = ip_checksum(result[:2] + result[4:])
if checksum - len(result) != 0:
raise ValueError("Invalid checksum in ping reply")
return sender[0]
def do_ping(host, count, timeout):
with socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP) as sock:
sock.connect((host, IPPROTO_ICMP))
print(ping_once(sock)
def main():
p = ArgumentParser()
p.add_argument('host')
p.add_argument('-c', '--count', type=int, default=-1)
args = p.parse_args()
do_ping(args.host, args.count, 0)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment