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

79 statements  

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> 

5 

6""" 

7Functions common to different architectures 

8""" 

9 

10import re 

11import socket 

12 

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 

19 

20# Type imports 

21import scapy 

22from typing import ( 

23 List, 

24 Optional, 

25 TYPE_CHECKING, 

26 Union, 

27) 

28 

29if TYPE_CHECKING: 

30 from scapy.libs.structures import bpf_program 

31 

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] 

54 

55 

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) 

63 

64 

65# BPF HANDLERS 

66 

67 

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. 

76 

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 

151 

152 

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)) 

170 

171 

172####### 

173# DNS # 

174####### 

175 

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 []