1## This file is part of Scapy 2## See http://www.secdev.org/projects/scapy for more informations 3## Copyright (C) Philippe Biondi <phil@secdev.org> 4## This program is published under a GPLv2 license 5 6""" 7Global variables and functions for handling external data sets. 8""" 9 10 11import os 12import re 13import sys 14import time 15 16 17from scapy.dadict import DADict 18from scapy.consts import DARWIN, FREEBSD, NETBSD, OPENBSD 19from scapy.error import log_loading 20from scapy.compat import * 21 22 23############ 24## Consts ## 25############ 26 27ETHER_ANY = b"\x00"*6 28ETHER_BROADCAST = b"\xff"*6 29 30ETH_P_ALL = 3 31ETH_P_IP = 0x800 32ETH_P_ARP = 0x806 33ETH_P_IPV6 = 0x86dd 34ETH_P_MACSEC = 0x88e5 35 36# From net/if_arp.h 37ARPHDR_ETHER = 1 38ARPHDR_METRICOM = 23 39ARPHDR_PPP = 512 40ARPHDR_LOOPBACK = 772 41ARPHDR_TUN = 65534 42 43# From pcap/dlt.h 44DLT_NULL = 0 45DLT_EN10MB = 1 46DLT_EN3MB = 2 47DLT_AX25 = 3 48DLT_PRONET = 4 49DLT_CHAOS = 5 50DLT_IEEE802 = 6 51DLT_ARCNET = 7 52DLT_SLIP = 8 53DLT_PPP = 9 54DLT_FDDI = 10 55if OPENBSD: 56 DLT_RAW = 14 57else: 58 DLT_RAW = 12 59DLT_RAW_ALT = 101 # At least in Argus 60if FREEBSD or NETBSD: 61 DLT_SLIP_BSDOS = 13 62 DLT_PPP_BSDOS = 14 63else: 64 DLT_SLIP_BSDOS = 15 65 DLT_PPP_BSDOS = 16 66if FREEBSD: 67 DLT_PFSYNC = 121 68else: 69 DLT_PFSYNC = 18 70 DLT_HHDLC = 121 71DLT_ATM_CLIP = 19 72DLT_PPP_SERIAL = 50 73DLT_PPP_ETHER = 51 74DLT_SYMANTEC_FIREWALL = 99 75DLT_C_HDLC = 104 76DLT_IEEE802_11 = 105 77if OPENBSD: 78 DLT_LOOP = 12 79 DLT_ENC = 13 80else: 81 DLT_LOOP = 108 82 DLT_ENC = 109 83DLT_LINUX_SLL = 113 84DLT_PFLOG = 117 85DLT_PRISM_HEADER = 119 86DLT_AIRONET_HEADER = 120 87DLT_IEEE802_11_RADIO = 127 88DLT_LINUX_IRDA = 144 89DLT_BLUETOOTH_HCI_H4 = 187 90DLT_PPI = 192 91DLT_CAN_SOCKETCAN = 227 92DLT_IPV4 = 228 93DLT_IPV6 = 229 94 95# From net/ipv6.h on Linux (+ Additions) 96IPV6_ADDR_UNICAST = 0x01 97IPV6_ADDR_MULTICAST = 0x02 98IPV6_ADDR_CAST_MASK = 0x0F 99IPV6_ADDR_LOOPBACK = 0x10 100IPV6_ADDR_GLOBAL = 0x00 101IPV6_ADDR_LINKLOCAL = 0x20 102IPV6_ADDR_SITELOCAL = 0x40 # deprecated since Sept. 2004 by RFC 3879 103IPV6_ADDR_SCOPE_MASK = 0xF0 104#IPV6_ADDR_COMPATv4 = 0x80 # deprecated; i.e. ::/96 105#IPV6_ADDR_MAPPED = 0x1000 # i.e.; ::ffff:0.0.0.0/96 106IPV6_ADDR_6TO4 = 0x0100 # Added to have more specific info (should be 0x0101 ?) 107IPV6_ADDR_UNSPECIFIED = 0x10000 108 109 110# On windows, epoch is 01/02/1970 at 00:00 111EPOCH = time.mktime((1970, 1, 2, 0, 0, 0, 3, 1, 0))-86400 112 113MTU = 0xffff # a.k.a give me all you have 114 115WINDOWS=sys.platform.startswith("win") 116 117 118# file parsing to get some values : 119 120def load_protocols(filename): 121 spaces = re.compile(b"[ \t]+|\n") 122 dct = DADict(_name=filename) 123 try: 124 for l in open(filename, "rb"): 125 try: 126 shrp = l.find(b"#") 127 if shrp >= 0: 128 l = l[:shrp] 129 l = l.strip() 130 if not l: 131 continue 132 lt = tuple(re.split(spaces, l)) 133 if len(lt) < 2 or not lt[0]: 134 continue 135 dct[lt[0]] = int(lt[1]) 136 except Exception as e: 137 log_loading.info("Couldn't parse file [%s]: line [%r] (%s)", filename, l, e) 138 except IOError: 139 log_loading.info("Can't open %s file", filename) 140 return dct 141 142def load_ethertypes(filename): 143 spaces = re.compile(b"[ \t]+|\n") 144 dct = DADict(_name=filename) 145 try: 146 f=open(filename, "rb") 147 for l in f: 148 try: 149 shrp = l.find(b"#") 150 if shrp >= 0: 151 l = l[:shrp] 152 l = l.strip() 153 if not l: 154 continue 155 lt = tuple(re.split(spaces, l)) 156 if len(lt) < 2 or not lt[0]: 157 continue 158 dct[lt[0]] = int(lt[1], 16) 159 except Exception as e: 160 log_loading.info("Couldn't parse file [%s]: line [%r] (%s)", filename, l, e) 161 f.close() 162 except IOError as msg: 163 pass 164 return dct 165 166def load_services(filename): 167 spaces = re.compile(b"[ \t]+|\n") 168 tdct=DADict(_name="%s-tcp"%filename) 169 udct=DADict(_name="%s-udp"%filename) 170 try: 171 f=open(filename, "rb") 172 for l in f: 173 try: 174 shrp = l.find(b"#") 175 if shrp >= 0: 176 l = l[:shrp] 177 l = l.strip() 178 if not l: 179 continue 180 lt = tuple(re.split(spaces, l)) 181 if len(lt) < 2 or not lt[0]: 182 continue 183 if lt[1].endswith(b"/tcp"): 184 tdct[lt[0]] = int(lt[1].split(b'/')[0]) 185 elif lt[1].endswith(b"/udp"): 186 udct[lt[0]] = int(lt[1].split(b'/')[0]) 187 except Exception as e: 188 log_loading.warning("Couldn't parse file [%s]: line [%r] (%s)", filename, l, e) 189 f.close() 190 except IOError: 191 log_loading.info("Can't open /etc/services file") 192 return tdct,udct 193 194 195class ManufDA(DADict): 196 def fixname(self, val): 197 return plain_str(val) 198 def _get_manuf_couple(self, mac): 199 oui = ":".join(mac.split(":")[:3]).upper() 200 return self.__dict__.get(oui,(mac,mac)) 201 def _get_manuf(self, mac): 202 return self._get_manuf_couple(mac)[1] 203 def _get_short_manuf(self, mac): 204 return self._get_manuf_couple(mac)[0] 205 def _resolve_MAC(self, mac): 206 oui = ":".join(mac.split(":")[:3]).upper() 207 if oui in self: 208 return ":".join([self[oui][0]]+ mac.split(":")[3:]) 209 return mac 210 def __repr__(self): 211 return "\n".join("<%s %s, %s>" % (i[0], i[1][0], i[1][1]) for i in self.__dict__.items()) 212 213 214 215def load_manuf(filename): 216 manufdb=ManufDA(_name=filename) 217 with open(filename, "rb") as fdesc: 218 for l in fdesc: 219 try: 220 l = l.strip() 221 if not l or l.startswith(b"#"): 222 continue 223 oui,shrt=l.split()[:2] 224 i = l.find(b"#") 225 if i < 0: 226 lng=shrt 227 else: 228 lng = l[i+2:] 229 manufdb[oui] = plain_str(shrt), plain_str(lng) 230 except Exception: 231 log_loading.warning("Couldn't parse one line from [%s] [%r]", 232 filename, l, exc_info=True) 233 return manufdb 234 235 236if WINDOWS: 237 ETHER_TYPES=load_ethertypes("ethertypes") 238 IP_PROTOS=load_protocols(os.environ["SystemRoot"]+"\system32\drivers\etc\protocol") 239 TCP_SERVICES,UDP_SERVICES=load_services(os.environ["SystemRoot"] + "\system32\drivers\etc\services") 240 # Default value, will be updated by arch.windows 241 try: 242 MANUFDB = load_manuf(os.environ["ProgramFiles"] + "\\wireshark\\manuf") 243 except IOError: 244 MANUFDB = None 245else: 246 IP_PROTOS=load_protocols("/etc/protocols") 247 ETHER_TYPES=load_ethertypes("/etc/ethertypes") 248 TCP_SERVICES,UDP_SERVICES=load_services("/etc/services") 249 MANUFDB = None 250 for prefix in ['/usr', '/usr/local', '/opt', '/opt/wireshark']: 251 try: 252 MANUFDB = load_manuf(os.path.join(prefix, "share", "wireshark", 253 "manuf")) 254 if MANUFDB: 255 break 256 except IOError: 257 pass 258 if not MANUFDB: 259 log_loading.warning("Cannot read wireshark manuf database") 260 261 262##################### 263## knowledge bases ## 264##################### 265 266class KnowledgeBase: 267 def __init__(self, filename): 268 self.filename = filename 269 self.base = None 270 271 def lazy_init(self): 272 self.base = "" 273 274 def reload(self, filename = None): 275 if filename is not None: 276 self.filename = filename 277 oldbase = self.base 278 self.base = None 279 self.lazy_init() 280 if self.base is None: 281 self.base = oldbase 282 283 def get_base(self): 284 if self.base is None: 285 self.lazy_init() 286 return self.base 287 288 289