Created
February 5, 2018 07:15
-
-
Save onemouth/67cb276d15d3b064ee4cf5ce8b70663c to your computer and use it in GitHub Desktop.
Use ttl=1 Ping to find first router device's ip
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import socket | |
import struct | |
import sys | |
import select | |
class PingProtocolData(object): | |
def __init__(self): | |
self.seq_number = 0 | |
@property | |
def ICMP_ECHO(self): | |
return 8 | |
@property | |
def seq_number(self): | |
return self.__seq_number | |
@property | |
def identifier(self): | |
return 0 | |
@seq_number.setter | |
def seq_number(self, seq_number): | |
self.__seq_number = seq_number | |
def generate_ping_packet(self): | |
checksum = 0 | |
header = struct.pack("!BBHHH", self.ICMP_ECHO, 0, checksum, self.identifier, | |
self.seq_number) | |
padBytes = "abcdefghijk" | |
data = bytes(padBytes) | |
#print data | |
checksum = self.calculate_checksum(header+data) | |
header = struct.pack("!BBHHH", self.ICMP_ECHO, 0, checksum, self.identifier, | |
self.seq_number) | |
packet = header + data | |
print packet | |
return packet | |
def calculate_checksum(self, source_string): | |
""" | |
A port of the functionality of in_cksum() from ping.c | |
Ideally this would act on the string as a series of 16-bit ints (host | |
packed), but this works. | |
Network data is big-endian, hosts are typically little-endian | |
""" | |
countTo = (int(len(source_string) / 2)) * 2 | |
sum = 0 | |
count = 0 | |
# Handle bytes in pairs (decoding as short ints) | |
loByte = 0 | |
hiByte = 0 | |
while count < countTo: | |
if (sys.byteorder == "little"): | |
loByte = source_string[count] | |
hiByte = source_string[count + 1] | |
else: | |
loByte = source_string[count + 1] | |
hiByte = source_string[count] | |
loByte = ord(loByte) | |
hiByte = ord(hiByte) | |
sum = sum + (hiByte * 256 + loByte) | |
count += 2 | |
# Handle last byte if applicable (odd-number of bytes) | |
# Endianness should be irrelevant in this case | |
if countTo < len(source_string): # Check for odd length | |
loByte = source_string[len(source_string) - 1] | |
loByte = ord(loByte) | |
sum += loByte | |
sum &= 0xffffffff # Truncate sum to 32 bits (a variance from ping.c, which | |
# uses signed ints, but overflow is unlikely in ping) | |
sum = (sum >> 16) + (sum & 0xffff) # Add high 16 bits to low 16 bits | |
sum += (sum >> 16) # Add carry from above (if any) | |
answer = ~sum & 0xffff # Invert and truncate to 16 bits | |
answer = socket.htons(answer) | |
return answer | |
class Pinger(object): | |
def __init__(self, ppd): | |
self.ppd = ppd | |
def _send_ping(self, s, target): | |
ping_packet = self.ppd.generate_ping_packet() | |
s.sendto(ping_packet, (target, 1)) | |
def _receive_ping(self, s): | |
timeout = 2.5 | |
select.select([s], [], [], timeout) | |
packet_data, address = s.recvfrom(2048) | |
print packet_data, address | |
def do(self): | |
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.getprotobyname("icmp")) | |
s.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, 1) | |
self._send_ping(s, "8.8.8.8") | |
self._receive_ping(s) | |
s.close() | |
def main(): | |
pinger = Pinger(PingProtocolData()) | |
pinger.do() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment