# SPDX-License-Identifier: GPL-2.0-only # This file is part of Scapy # See https://scapy.net/ for more information # Copyright (C) Philippe Biondi """ Functions common to different architectures """ import ctypes import re import socket from scapy.config import conf from scapy.data import MTU, ARPHRD_TO_DLT, DLT_RAW_ALT, DLT_RAW from scapy.error import Scapy_Exception, warning from scapy.interfaces import network_name, resolve_iface, NetworkInterface from scapy.libs.structures import bpf_program from scapy.pton_ntop import inet_pton from scapy.utils import decode_locale_str # Type imports import scapy from typing import ( List, Optional, Union, ) # From if.h _iff_flags = [ "UP", "BROADCAST", "DEBUG", "LOOPBACK", "POINTTOPOINT", "NOTRAILERS", "RUNNING", "NOARP", "PROMISC", "ALLMULTI", "MASTER", "SLAVE", "MULTICAST", "PORTSEL", "AUTOMEDIA", "DYNAMIC", "LOWER_UP", "DORMANT", "ECHO" ] def get_if_raw_addr(iff): # type: (Union[NetworkInterface, str]) -> bytes """Return the raw IPv4 address of interface""" iff = resolve_iface(iff) if not iff.ip: return b"\x00" * 4 return inet_pton(socket.AF_INET, iff.ip) # BPF HANDLERS 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 = resolve_iface(iface).type linktype = ARPHRD_TO_DLT.get(arphd) except Exception: # Failed to use linktype: use the interface pass if linktype is not None: # Some conversion aliases (e.g. linktype_to_dlt in libpcap) if linktype == DLT_RAW_ALT: linktype = DLT_RAW ret = pcap_compile_nopcap( MTU, linktype, ctypes.byref(bpf), bpf_filter, 1, -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 = decode_locale_str(bytearray(err).strip(b"\x00")) if error: raise OSError(error) ret = pcap_compile( pcap, ctypes.byref(bpf), bpf_filter, 1, -1 ) pcap_close(pcap) if ret == -1: raise Scapy_Exception( "Failed to compile filter expression %s (%s)" % (filter_exp, ret) ) return bpf def free_filter(bp: bpf_program) -> None: """ Free a bpf_program created with compile_filter """ from scapy.libs.winpcapy import pcap_freecode pcap_freecode(ctypes.byref(bp)) ####### # DNS # ####### def read_nameservers() -> List[str]: """Return the nameservers configured by the OS """ try: with open('/etc/resolv.conf', 'r') as fd: return re.findall(r"nameserver\s+([^\s]+)", fd.read()) except FileNotFoundError: warning("Could not retrieve the OS's nameserver !") return []