import ctypes as c ARP_REQUEST = "\x08\x06\x00\x01\x08\x00\x06\x04\x00\x01" ARP_REPLY = "\x08\x06\x00\x01\x08\x00\x06\x04\x00\x02" class SockAddr(c.Structure): _fields_ = [("sa_family", c.c_ushort), ("sa_data", c.c_char * 14)] class PcapAddr(c.Structure): pass PcapAddr._fields_ = [("next", c.POINTER(PcapAddr)), ("addr", c.POINTER(SockAddr)), ("netmask", c.POINTER(SockAddr)), ("sockaddr", c.POINTER(SockAddr)), ("dstaddr", c.POINTER(SockAddr))] class PcapIfT(c.Structure): pass PcapIfT._fields_ = [("next", c.POINTER(PcapIfT)), ("name", c.c_char_p), ("description", c.c_char_p), ("addresses", c.POINTER(PcapAddr)), ("flags", c.c_uint)] class BpfInsn(c.Structure): _fields_ = [("code", c.c_ushort), ("jt", c.c_char), ("jf", c.c_char), ("k", c.c_uint32)] class BpfProgram(c.Structure): _fields_ = [("bf_len", c.c_uint), ("bpf_insn", c.POINTER(BpfInsn))] class Timeval(c.Structure): _fields_ = [("tv_sec", c.c_long), ("tv_usec", c.c_long)] class PcapPktHdr(c.Structure): _fields_ = [("ts", Timeval), ("caplen", c.c_uint32), ("len", c.c_uint32)] PcapCallback = c.CFUNCTYPE(c.py_object, c.POINTER(PcapPktHdr), c.POINTER(c.c_byte)) PCAP_IF_LOOPBACK = 1 LINKTYPE_ETHERNET = 1 PCAP_NETMASK_UNKNOWN = 0xffffffff NULL = 0 CAPTURE_LIMIT = 2048 #MAC_ADDR_LEN = 6 #class EthernetHeader(c.Structure): # _fields_ = [("dst", c.c_ubyte * MAC_ADDR_LEN), # ("src", c.c_ubyte * MAC_ADDR_LEN), # ("type", c.c_ushort)] MAC_ADDR_LEN = 100 class EthernetHeader(c.Structure): _fields_ = [("foo", c.c_uint32 * MAC_ADDR_LEN)] # pcap.pcap_lookupdev # pcap.pcap_sendpacket class Interface: def __init__(self, name, pcap, handle): self._name = name self.pcap = pcap self.handle = handle def __del__(self): self.pcap.close_device(self.handle) @property def name(self): return self._name.decode("utf-8", "ignore") def collect_address(self): self.pcap.set_filter(self.handle, "(ip or ip6) and not net 127.0.0.0/8 and not net fe80::/64") i = 0 self.pcap.capture_packets(self.handle) #for packet in self.pcap.capture_packets(handle): # if i > 10: # break # i += 1 # print(packet) def buf_to_str(buf): return "".join([s for s in buf]) class Pcap(): def __init__(self, lib): self._devs_p = c.POINTER(PcapIfT) self.lib = lib def assert_pcap(self, return_code, handle): if return_code < 0: error = self.lib.pcap_geterr(handle) raise OSError(c.c_char_p(error).value.decode("utf-8", "ignore")) def find_devices(self): err = c.create_string_buffer(255) devs = self._devs_p() result = self.lib.pcap_findalldevs(c.byref(devs), err) if result < 0: raise OSError(buf_to_str(error_buf)) if not devs: return [] found_devs = [] this_dev = devs while True: dev = this_dev.contents if not (dev.flags & PCAP_IF_LOOPBACK): handle = self.open_live(dev.name) if handle != NULL: if self.lib.pcap_datalink(handle) == LINKTYPE_ETHERNET: interface = Interface(dev.name, self, handle) found_devs.append(interface) else: self.close_device(handle) if not dev.next: self.lib.pcap_freealldevs(devs) return found_devs this_dev = dev.next def close_device(self, device): self.lib.pcap_close(device) def open_live(self, name): err = c.create_string_buffer(255) return self.lib.pcap_open_live(name, CAPTURE_LIMIT, 1, 1000, err) def format_mac(self, dst): return "%x:%x:%x:%x:%x:%x" % \ (c.c_ubyte(dst[0]).value,c.c_ubyte(dst[1]).value,c.c_ubyte(dst[2]).value,c.c_ubyte(dst[3]).value,c.c_ubyte(dst[4]).value,c.c_ubyte(dst[5]).value) def handle_package(self, header, package): caplen = header.contents.caplen header_len = header.contents.len #assert caplen <= header_len #assert caplen >= c.sizeof(EthernetHeader) ethernet_header = c.cast(package, c.POINTER(EthernetHeader)).contents import pry; pry() def capture_packets(self, handle): cb = PcapCallback(self.handle_package) self.lib.pcap_loop(handle, 3, cb, c.py_object(self)) def set_filter(self, handle, filter): bpf_filter = BpfProgram() filter_string = c.create_string_buffer(filter.encode("utf-8")) status = self.lib.pcap_compile(handle, c.byref(bpf_filter), filter_string, 1, PCAP_NETMASK_UNKNOWN) self.assert_pcap(status, handle) status = self.lib.pcap_setfilter(handle, c.byref(bpf_filter)) self.assert_pcap(status, handle) #static u_int16_t ether_packet(u_char *args, const struct pcap_pkthdr *pkthdr, co nst u_char *p) { # struct ether_header *eptr = (struct ether_header*)p; # assert(pkthdr->caplen <= pkthdr->len); # assert(pkthdr->caplen >= sizeof(struct ether_header)); # return eptr->ether_type; # }