def __init__(self, device, snaplen, promisc, to_ms, monitor=None): device = network_name(device) self.errbuf = create_string_buffer(PCAP_ERRBUF_SIZE) self.iface = create_string_buffer(device.encode("utf8")) self.dtl = None if monitor: if WINDOWS and not conf.use_npcap: raise OSError("On Windows, this feature requires NPcap !") # Npcap-only functions from scapy.libs.winpcapy import pcap_create, \ pcap_set_snaplen, pcap_set_promisc, \ pcap_set_timeout, pcap_set_rfmon, pcap_activate self.pcap = pcap_create(self.iface, self.errbuf) pcap_set_snaplen(self.pcap, snaplen) pcap_set_promisc(self.pcap, promisc) pcap_set_timeout(self.pcap, to_ms) if pcap_set_rfmon(self.pcap, 1) != 0: log_runtime.error("Could not set monitor mode") if pcap_activate(self.pcap) != 0: raise OSError("Could not activate the pcap handler") else: self.pcap = pcap_open_live(self.iface, snaplen, promisc, to_ms, self.errbuf) error = bytes(bytearray(self.errbuf)).strip(b"\x00") if error: raise OSError(error) if WINDOWS: # Winpcap/Npcap exclusive: make every packet to be instantly # returned, and not buffered within Winpcap/Npcap pcap_setmintocopy(self.pcap, 0) self.header = POINTER(pcap_pkthdr)() self.pkt_data = POINTER(c_ubyte)() self.bpf_program = bpf_program()
def compile_filter(filter_exp, iface=None, linktype=None, promisc=False): """Asks libpcap to parse the filter, then build the matching BPF bytecode. :param iface: if provided, use the interface to compile :param linktype: if provided, use the linktype to compile """ try: from scapy.libs.winpcapy import (PCAP_ERRBUF_SIZE, pcap_open_live, pcap_compile, pcap_compile_nopcap, pcap_close) from scapy.libs.structures import bpf_program except ImportError: raise Scapy_Exception( "libpcap is not available. Cannot compile filter !") root = WINDOWS or (os.geteuid() == 0) from ctypes import create_string_buffer bpf = bpf_program() bpf_filter = create_string_buffer(filter_exp.encode("utf8")) if not linktype: # Try to guess linktype to avoid root if not iface: if not conf.iface: raise Scapy_Exception( "Please provide an interface or linktype!") if WINDOWS: iface = conf.iface.pcap_name else: iface = conf.iface # Try to guess linktype to avoid requiring root try: arphd = get_if_raw_hwaddr(iface)[0] linktype = ARPHRD_TO_DLT.get(arphd) except Exception: # Failed to use linktype: use the interface if not root: raise Scapy_Exception( "Please provide a valid interface or linktype!") if linktype is not None: ret = pcap_compile_nopcap(MTU, linktype, ctypes.byref(bpf), bpf_filter, 0, -1) elif iface: if not root: raise OSError("Compiling using an interface requires root.") err = create_string_buffer(PCAP_ERRBUF_SIZE) iface = create_string_buffer(iface.encode("utf8")) pcap = pcap_open_live(iface, MTU, promisc, 0, err) ret = pcap_compile(pcap, ctypes.byref(bpf), bpf_filter, 0, -1) pcap_close(pcap) if ret == -1: raise Scapy_Exception("Failed to compile filter expression %s (%s)" % (filter_exp, ret)) if conf.use_pypy and sys.pypy_version_info <= (7, 3, 0): # PyPy < 7.3.0 has a broken behavior # https://bitbucket.org/pypy/pypy/issues/3114 return struct.pack('HL', bpf.bf_len, ctypes.addressof(bpf.bf_insns.contents)) return bpf
def compile_filter( filter_exp, # type: str iface=None, # type: Optional[Union[str, 'scapy.interfaces.NetworkInterface']] # noqa: E501 linktype=None, # type: Optional[int] promisc=False # type: bool ): # type: (...) -> bpf_program """Asks libpcap to parse the filter, then build the matching BPF bytecode. :param iface: if provided, use the interface to compile :param linktype: if provided, use the linktype to compile """ try: from scapy.libs.winpcapy import (PCAP_ERRBUF_SIZE, pcap_open_live, pcap_compile, pcap_compile_nopcap, pcap_close) except OSError: raise ImportError("libpcap is not available. Cannot compile filter !") from ctypes import create_string_buffer bpf = bpf_program() bpf_filter = create_string_buffer(filter_exp.encode("utf8")) if not linktype: # Try to guess linktype to avoid root if not iface: if not conf.iface: raise Scapy_Exception( "Please provide an interface or linktype!") iface = conf.iface # Try to guess linktype to avoid requiring root try: arphd = get_if_raw_hwaddr(iface)[0] linktype = ARPHRD_TO_DLT.get(arphd) except Exception: # Failed to use linktype: use the interface pass if not linktype and conf.use_bpf: linktype = ARPHDR_ETHER if linktype is not None: ret = pcap_compile_nopcap(MTU, linktype, ctypes.byref(bpf), bpf_filter, 0, -1) elif iface: err = create_string_buffer(PCAP_ERRBUF_SIZE) iface_b = create_string_buffer(network_name(iface).encode("utf8")) pcap = pcap_open_live(iface_b, MTU, promisc, 0, err) error = bytes(bytearray(err)).strip(b"\x00") if error: raise OSError(error) ret = pcap_compile(pcap, ctypes.byref(bpf), bpf_filter, 0, -1) pcap_close(pcap) if ret == -1: raise Scapy_Exception("Failed to compile filter expression %s (%s)" % (filter_exp, ret)) return bpf