Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/arch/common.py: 25%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# SPDX-License-Identifier: GPL-2.0-only
2# This file is part of Scapy
3# See https://scapy.net/ for more information
4# Copyright (C) Philippe Biondi <phil@secdev.org>
6"""
7Functions common to different architectures
8"""
10import re
11import socket
13from scapy.config import conf
14from scapy.data import MTU, ARPHRD_TO_DLT, DLT_RAW_ALT, DLT_RAW
15from scapy.error import Scapy_Exception, warning
16from scapy.interfaces import network_name, resolve_iface, NetworkInterface
17from scapy.pton_ntop import inet_pton
18from scapy.utils import decode_locale_str
20# Type imports
21import scapy
22from typing import (
23 List,
24 Optional,
25 TYPE_CHECKING,
26 Union,
27)
29if TYPE_CHECKING:
30 from scapy.libs.structures import bpf_program
32# From if.h
33_iff_flags = [
34 "UP",
35 "BROADCAST",
36 "DEBUG",
37 "LOOPBACK",
38 "POINTTOPOINT",
39 "NOTRAILERS",
40 "RUNNING",
41 "NOARP",
42 "PROMISC",
43 "ALLMULTI",
44 "MASTER",
45 "SLAVE",
46 "MULTICAST",
47 "PORTSEL",
48 "AUTOMEDIA",
49 "DYNAMIC",
50 "LOWER_UP",
51 "DORMANT",
52 "ECHO"
53]
56def get_if_raw_addr(iff):
57 # type: (Union[NetworkInterface, str]) -> bytes
58 """Return the raw IPv4 address of interface"""
59 iff = resolve_iface(iff)
60 if not iff.ip:
61 return b"\x00" * 4
62 return inet_pton(socket.AF_INET, iff.ip)
65# BPF HANDLERS
68def compile_filter(filter_exp, # type: str
69 iface=None, # type: Optional[Union[str, 'scapy.interfaces.NetworkInterface']] # noqa: E501
70 linktype=None, # type: Optional[int]
71 promisc=False # type: bool
72 ):
73 # type: (...) -> 'bpf_program'
74 """Asks libpcap to parse the filter, then build the matching
75 BPF bytecode.
77 :param iface: if provided, use the interface to compile
78 :param linktype: if provided, use the linktype to compile
79 """
80 try:
81 import ctypes
82 except OSError:
83 raise ImportError(
84 "ctypes is not available. Cannot compile filter !"
85 )
86 from scapy.libs.structures import bpf_program
87 try:
88 from scapy.libs.winpcapy import (
89 PCAP_ERRBUF_SIZE,
90 pcap_open_live,
91 pcap_open_dead,
92 pcap_compile,
93 pcap_geterr,
94 pcap_close
95 )
96 except OSError:
97 raise ImportError(
98 "libpcap is not available. Cannot compile filter !"
99 )
100 from ctypes import create_string_buffer
101 bpf = bpf_program()
102 bpf_filter = create_string_buffer(filter_exp.encode("utf8"))
103 if not linktype:
104 # Try to guess linktype to avoid root
105 if not iface:
106 if not conf.iface:
107 raise Scapy_Exception(
108 "Please provide an interface or linktype!"
109 )
110 iface = conf.iface
111 # Try to guess linktype to avoid requiring root
112 try:
113 arphd = resolve_iface(iface).type
114 linktype = ARPHRD_TO_DLT.get(arphd)
115 except Exception:
116 # Failed to use linktype: use the interface
117 pass
118 if linktype is not None:
119 # Some conversion aliases (e.g. linktype_to_dlt in libpcap)
120 if linktype == DLT_RAW_ALT:
121 linktype = DLT_RAW
122 # Use a "dead" capture handle (no interface / no root required) so that,
123 # on failure, the libpcap error message can be retrieved with pcap_geterr
124 pcap = pcap_open_dead(linktype, MTU)
125 elif iface:
126 err = create_string_buffer(PCAP_ERRBUF_SIZE)
127 iface_b = create_string_buffer(network_name(iface).encode("utf8"))
128 pcap = pcap_open_live(
129 iface_b, MTU, promisc, 0, err
130 )
131 error = decode_locale_str(bytearray(err).strip(b"\x00"))
132 if error:
133 raise OSError(error)
134 else:
135 raise Scapy_Exception("Please provide an interface or linktype!")
136 ret = pcap_compile(
137 pcap, ctypes.byref(bpf), bpf_filter, 1, -1
138 )
139 if ret == -1:
140 # Retrieve the underlying libpcap error message: it explains why the
141 # filter is invalid or incompatible with the link-layer type
142 errstr = decode_locale_str(
143 bytearray(pcap_geterr(pcap)).strip(b"\x00")
144 )
145 pcap_close(pcap)
146 raise Scapy_Exception(
147 "Failed to compile filter expression %r (%s)" % (filter_exp, errstr)
148 )
149 pcap_close(pcap)
150 return bpf
153def free_filter(bp: 'bpf_program') -> None:
154 """
155 Free a bpf_program created with compile_filter
156 """
157 try:
158 import ctypes
159 except OSError:
160 raise ImportError(
161 "ctypes is not available. Cannot free filter !"
162 )
163 try:
164 from scapy.libs.winpcapy import pcap_freecode
165 except OSError:
166 raise ImportError(
167 "libpcap is not available. Cannot free filter !"
168 )
169 pcap_freecode(ctypes.byref(bp))
172#######
173# DNS #
174#######
176def read_nameservers() -> List[str]:
177 """Return the nameservers configured by the OS
178 """
179 try:
180 with open('/etc/resolv.conf', 'r') as fd:
181 return re.findall(r"nameserver\s+([^\s]+)", fd.read())
182 except FileNotFoundError:
183 warning("Could not retrieve the OS's nameserver !")
184 return []