Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/arch/common.py: 31%

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

67 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 ctypes 

11import re 

12import socket 

13 

14from scapy.config import conf 

15from scapy.data import MTU, ARPHRD_TO_DLT, DLT_RAW_ALT, DLT_RAW 

16from scapy.error import Scapy_Exception, warning 

17from scapy.interfaces import network_name, resolve_iface, NetworkInterface 

18from scapy.libs.structures import bpf_program 

19from scapy.pton_ntop import inet_pton 

20from scapy.utils import decode_locale_str 

21 

22# Type imports 

23import scapy 

24from typing import ( 

25 List, 

26 Optional, 

27 Union, 

28) 

29 

30# From if.h 

31_iff_flags = [ 

32 "UP", 

33 "BROADCAST", 

34 "DEBUG", 

35 "LOOPBACK", 

36 "POINTTOPOINT", 

37 "NOTRAILERS", 

38 "RUNNING", 

39 "NOARP", 

40 "PROMISC", 

41 "ALLMULTI", 

42 "MASTER", 

43 "SLAVE", 

44 "MULTICAST", 

45 "PORTSEL", 

46 "AUTOMEDIA", 

47 "DYNAMIC", 

48 "LOWER_UP", 

49 "DORMANT", 

50 "ECHO" 

51] 

52 

53 

54def get_if_raw_addr(iff): 

55 # type: (Union[NetworkInterface, str]) -> bytes 

56 """Return the raw IPv4 address of interface""" 

57 iff = resolve_iface(iff) 

58 if not iff.ip: 

59 return b"\x00" * 4 

60 return inet_pton(socket.AF_INET, iff.ip) 

61 

62 

63# BPF HANDLERS 

64 

65 

66def compile_filter(filter_exp, # type: str 

67 iface=None, # type: Optional[Union[str, 'scapy.interfaces.NetworkInterface']] # noqa: E501 

68 linktype=None, # type: Optional[int] 

69 promisc=False # type: bool 

70 ): 

71 # type: (...) -> bpf_program 

72 """Asks libpcap to parse the filter, then build the matching 

73 BPF bytecode. 

74 

75 :param iface: if provided, use the interface to compile 

76 :param linktype: if provided, use the linktype to compile 

77 """ 

78 try: 

79 from scapy.libs.winpcapy import ( 

80 PCAP_ERRBUF_SIZE, 

81 pcap_open_live, 

82 pcap_open_dead, 

83 pcap_compile, 

84 pcap_geterr, 

85 pcap_close 

86 ) 

87 except OSError: 

88 raise ImportError( 

89 "libpcap is not available. Cannot compile filter !" 

90 ) 

91 from ctypes import create_string_buffer 

92 bpf = bpf_program() 

93 bpf_filter = create_string_buffer(filter_exp.encode("utf8")) 

94 if not linktype: 

95 # Try to guess linktype to avoid root 

96 if not iface: 

97 if not conf.iface: 

98 raise Scapy_Exception( 

99 "Please provide an interface or linktype!" 

100 ) 

101 iface = conf.iface 

102 # Try to guess linktype to avoid requiring root 

103 try: 

104 arphd = resolve_iface(iface).type 

105 linktype = ARPHRD_TO_DLT.get(arphd) 

106 except Exception: 

107 # Failed to use linktype: use the interface 

108 pass 

109 if linktype is not None: 

110 # Some conversion aliases (e.g. linktype_to_dlt in libpcap) 

111 if linktype == DLT_RAW_ALT: 

112 linktype = DLT_RAW 

113 # Use a "dead" capture handle (no interface / no root required) so that, 

114 # on failure, the libpcap error message can be retrieved with pcap_geterr 

115 pcap = pcap_open_dead(linktype, MTU) 

116 elif iface: 

117 err = create_string_buffer(PCAP_ERRBUF_SIZE) 

118 iface_b = create_string_buffer(network_name(iface).encode("utf8")) 

119 pcap = pcap_open_live( 

120 iface_b, MTU, promisc, 0, err 

121 ) 

122 error = decode_locale_str(bytearray(err).strip(b"\x00")) 

123 if error: 

124 raise OSError(error) 

125 else: 

126 raise Scapy_Exception("Please provide an interface or linktype!") 

127 ret = pcap_compile( 

128 pcap, ctypes.byref(bpf), bpf_filter, 1, -1 

129 ) 

130 if ret == -1: 

131 # Retrieve the underlying libpcap error message: it explains why the 

132 # filter is invalid or incompatible with the link-layer type 

133 errstr = decode_locale_str( 

134 bytearray(pcap_geterr(pcap)).strip(b"\x00") 

135 ) 

136 pcap_close(pcap) 

137 raise Scapy_Exception( 

138 "Failed to compile filter expression %r (%s)" % (filter_exp, errstr) 

139 ) 

140 pcap_close(pcap) 

141 return bpf 

142 

143 

144def free_filter(bp: bpf_program) -> None: 

145 """ 

146 Free a bpf_program created with compile_filter 

147 """ 

148 from scapy.libs.winpcapy import pcap_freecode 

149 pcap_freecode(ctypes.byref(bp)) 

150 

151 

152####### 

153# DNS # 

154####### 

155 

156def read_nameservers() -> List[str]: 

157 """Return the nameservers configured by the OS 

158 """ 

159 try: 

160 with open('/etc/resolv.conf', 'r') as fd: 

161 return re.findall(r"nameserver\s+([^\s]+)", fd.read()) 

162 except FileNotFoundError: 

163 warning("Could not retrieve the OS's nameserver !") 

164 return []