Skip to content

Commit 3f1628e

Browse files
committed
Improve path detection & Add backup ethertypes
1 parent 22f32cc commit 3f1628e

File tree

8 files changed

+250
-42
lines changed

8 files changed

+250
-42
lines changed

.coveragerc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ omit =
1414
# Libraries
1515
*/scapy/modules/six.py
1616
*/scapy/modules/winpcapy.py
17+
*/scapy/modules/ethertypes.py

.coveragerc.tox

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ omit =
77
# Scapy external modules
88
scapy/modules/six.py
99
scapy/modules/winpcapy.py
10+
scapy/modules/ethertypes.py
1011
# .tox specific path
1112
.tox/*
1213
# OS specific paths

scapy/data.py

Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -154,39 +154,49 @@
154154
MTU = 0xffff # a.k.a give me all you have
155155

156156

157-
def load_protocols(filename, _integer_base=10):
157+
def load_protocols(filename, _fallback=None, _integer_base=10):
158158
""""Parse /etc/protocols and return values as a dictionary."""
159159
spaces = re.compile(b"[ \t]+|\n")
160160
dct = DADict(_name=filename)
161+
162+
def _process_data(fdesc):
163+
for line in fdesc:
164+
try:
165+
shrp = line.find(b"#")
166+
if shrp >= 0:
167+
line = line[:shrp]
168+
line = line.strip()
169+
if not line:
170+
continue
171+
lt = tuple(re.split(spaces, line))
172+
if len(lt) < 2 or not lt[0]:
173+
continue
174+
dct[lt[0]] = int(lt[1], _integer_base)
175+
except Exception as e:
176+
log_loading.info(
177+
"Couldn't parse file [%s]: line [%r] (%s)",
178+
filename,
179+
line,
180+
e,
181+
)
161182
try:
183+
if not filename:
184+
raise IOError
162185
with open(filename, "rb") as fdesc:
163-
for line in fdesc:
164-
try:
165-
shrp = line.find(b"#")
166-
if shrp >= 0:
167-
line = line[:shrp]
168-
line = line.strip()
169-
if not line:
170-
continue
171-
lt = tuple(re.split(spaces, line))
172-
if len(lt) < 2 or not lt[0]:
173-
continue
174-
dct[lt[0]] = int(lt[1], _integer_base)
175-
except Exception as e:
176-
log_loading.info(
177-
"Couldn't parse file [%s]: line [%r] (%s)",
178-
filename,
179-
line,
180-
e,
181-
)
186+
_process_data(fdesc)
182187
except IOError:
183-
log_loading.info("Can't open %s file", filename)
188+
if _fallback:
189+
_process_data(_fallback.split(b"\n"))
190+
else:
191+
log_loading.info("Can't open %s file", filename)
184192
return dct
185193

186194

187195
def load_ethertypes(filename):
188-
""""Parse /etc/ethertypes and return values as a dictionary."""
189-
return load_protocols(filename, _integer_base=16)
196+
""""Parse /etc/ethertypes and return values as a dictionary.
197+
If unavailable, use the copy bundled with Scapy."""
198+
from scapy.modules.ethertypes import DATA
199+
return load_protocols(filename, _fallback=DATA, _integer_base=16)
190200

191201

192202
def load_services(filename):
@@ -288,28 +298,35 @@ def load_manuf(filename):
288298
return manufdb
289299

290300

301+
def select_path(directories, filename):
302+
"""Find filename among several directories"""
303+
for directory in directories:
304+
path = os.path.join(directory, filename)
305+
if os.path.exists(path):
306+
return path
307+
308+
291309
if WINDOWS:
292310
IP_PROTOS = load_protocols(os.environ["SystemRoot"] + "\\system32\\drivers\\etc\\protocol") # noqa: E501
293311
TCP_SERVICES, UDP_SERVICES = load_services(os.environ["SystemRoot"] + "\\system32\\drivers\\etc\\services") # noqa: E501
294312
# Default values, will be updated by arch.windows
295-
ETHER_TYPES = DADict()
313+
ETHER_TYPES = load_ethertypes(None)
296314
MANUFDB = ManufDA()
297315
else:
298316
IP_PROTOS = load_protocols("/etc/protocols")
299317
ETHER_TYPES = load_ethertypes("/etc/ethertypes")
300318
TCP_SERVICES, UDP_SERVICES = load_services("/etc/services")
301319
MANUFDB = None
302-
for prefix in ['/usr', '/usr/local', '/opt', '/opt/wireshark',
303-
'/Applications/Wireshark.app/Contents/Resources']:
320+
manuf_path = select_path(
321+
['/usr', '/usr/local', '/opt', '/opt/wireshark',
322+
'/Applications/Wireshark.app/Contents/Resources'],
323+
"share/wireshark/manuf"
324+
)
325+
if manuf_path:
304326
try:
305-
MANUFDB = load_manuf(os.path.join(prefix, "share", "wireshark",
306-
"manuf"))
307-
if MANUFDB:
308-
break
309-
except (IOError, OSError): # Same as above
310-
pass
311-
if not MANUFDB:
312-
log_loading.warning("Cannot read wireshark manuf database")
327+
MANUFDB = load_manuf(manuf_path)
328+
except (IOError, OSError):
329+
log_loading.warning("Cannot read wireshark manuf database")
313330

314331

315332
#####################

scapy/modules/ethertypes.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# This file is part of Scapy
2+
# See http://www.secdev.org/projects/scapy for more information
3+
4+
"""
5+
/*
6+
* Copyright (c) 1982, 1986, 1993
7+
* The Regents of the University of California. All rights reserved.
8+
*
9+
* Redistribution and use in source and binary forms, with or without
10+
* modification, are permitted provided that the following conditions
11+
* are met:
12+
* 1. Redistributions of source code must retain the above copyright
13+
* notice, this list of conditions and the following disclaimer.
14+
* 2. Redistributions in binary form must reproduce the above copyright
15+
* notice, this list of conditions and the following disclaimer in the
16+
* documentation and/or other materials provided with the distribution.
17+
* 3. Neither the name of the University nor the names of its contributors
18+
* may be used to endorse or promote products derived from this software
19+
* without specific prior written permission.
20+
*
21+
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24+
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31+
* SUCH DAMAGE.
32+
*
33+
* @(#)if_ether.h 8.1 (Berkeley) 6/10/93
34+
*/
35+
"""
36+
37+
# This file contains data automatically generated using
38+
# scapy/tools/generate_ethertypes.py
39+
# based on OpenBSD public source.
40+
41+
DATA = b"""
42+
#
43+
# Ethernet frame types
44+
# This file describes some of the various Ethernet
45+
# protocol types that are used on Ethernet networks.
46+
#
47+
# This list could be found on:
48+
# http://www.iana.org/assignments/ethernet-numbers
49+
# http://www.iana.org/assignments/ieee-802-numbers
50+
#
51+
# <name> <hexnumber> <alias1>...<alias35> #Comment
52+
#
53+
8023 0004 # IEEE 802.3 packet
54+
PUP 0200 # Xerox PUP protocol - see 0A00
55+
PUPAT 0200 # PUP Address Translation - see 0A01
56+
NS 0600 # XNS
57+
NSAT 0601 # XNS Address Translation (3Mb only)
58+
DLOG1 0660 # DLOG (?)
59+
DLOG2 0661 # DLOG (?)
60+
IPv4 0800 # IP protocol
61+
X75 0801 # X.75 Internet
62+
NBS 0802 # NBS Internet
63+
ECMA 0803 # ECMA Internet
64+
CHAOS 0804 # CHAOSnet
65+
X25 0805 # X.25 Level 3
66+
ARP 0806 # Address resolution protocol
67+
FRARP 0808 # Frame Relay ARP (RFC1701)
68+
VINES 0BAD # Banyan VINES
69+
TRAIL 1000 # Trailer packet
70+
DCA 1234 # DCA - Multicast
71+
VALID 1600 # VALID system protocol
72+
RCL 1995 # Datapoint Corporation (RCL lan protocol)
73+
NBPCC 3C04 # 3Com NBP Connect complete not registered
74+
NBPDG 3C07 # 3Com NBP Datagram (like XNS IDP) not registered
75+
PCS 4242 # PCS Basic Block Protocol
76+
IMLBL 4C42 # Information Modes Little Big LAN
77+
MOPDL 6001 # DEC MOP dump/load
78+
MOPRC 6002 # DEC MOP remote console
79+
LAT 6004 # DEC LAT
80+
SCA 6007 # DEC LAVC, SCA
81+
AMBER 6008 # DEC AMBER
82+
RAWFR 6559 # Raw Frame Relay (RFC1701)
83+
UBDL 7000 # Ungermann-Bass download
84+
UBNIU 7001 # Ungermann-Bass NIUs
85+
UBNMC 7003 # Ungermann-Bass ??? (NMC to/from UB Bridge)
86+
UBBST 7005 # Ungermann-Bass Bridge Spanning Tree
87+
OS9 7007 # OS/9 Microware
88+
RACAL 7030 # Racal-Interlan
89+
HP 8005 # HP Probe
90+
TIGAN 802F # Tigan, Inc.
91+
DECAM 8048 # DEC Availability Manager for Distributed Systems DECamds (but someone at DEC says not)
92+
VEXP 805B # Stanford V Kernel exp.
93+
VPROD 805C # Stanford V Kernel prod.
94+
ES 805D # Evans & Sutherland
95+
VEECO 8067 # Veeco Integrated Auto.
96+
ATT 8069 # AT&T
97+
MATRA 807A # Matra
98+
DDE 807B # Dansk Data Elektronik
99+
MERIT 807C # Merit Internodal (or Univ of Michigan?)
100+
ATALK 809B # AppleTalk
101+
PACER 80C6 # Pacer Software
102+
SNA 80D5 # IBM SNA Services over Ethernet
103+
RETIX 80F2 # Retix
104+
AARP 80F3 # AppleTalk AARP
105+
VLAN 8100 # IEEE 802.1Q VLAN tagging (XXX conflicts)
106+
BOFL 8102 # Wellfleet; BOFL (Breath OF Life) pkts [every 5-10 secs.]
107+
HAYES 8130 # Hayes Microcomputers (XXX which?)
108+
VGLAB 8131 # VG Laboratory Systems
109+
IPX 8137 # Novell (old) NetWare IPX (ECONFIG E option)
110+
MUMPS 813F # M/MUMPS data sharing
111+
FLIP 8146 # Vrije Universiteit (NL) FLIP (Fast Local Internet Protocol)
112+
NCD 8149 # Network Computing Devices
113+
ALPHA 814A # Alpha Micro
114+
SNMP 814C # SNMP over Ethernet (see RFC1089)
115+
XTP 817D # Protocol Engines XTP
116+
SGITW 817E # SGI/Time Warner prop.
117+
STP 8181 # Scheduled Transfer STP, HIPPI-ST
118+
IPv6 86DD # IP protocol version 6
119+
RDP 8739 # Control Technology Inc. RDP Without IP
120+
MICP 873A # Control Technology Inc. Mcast Industrial Ctrl Proto.
121+
IPAS 876C # IP Autonomous Systems (RFC1701)
122+
SLOW 8809 # 803.3ad slow protocols (LACP/Marker)
123+
PPP 880B # PPP (obsolete by PPPOE)
124+
MPLS 8847 # MPLS Unicast
125+
AXIS 8856 # Axis Communications AB proprietary bootstrap/config
126+
PPPOE 8864 # PPP Over Ethernet Session Stage
127+
PAE 888E # 802.1X Port Access Entity
128+
AOE 88A2 # ATA over Ethernet
129+
QINQ 88A8 # 802.1ad VLAN stacking
130+
LLDP 88CC # Link Layer Discovery Protocol
131+
PBB 88E7 # 802.1Q Provider Backbone Bridging
132+
XNSSM 9001 # 3Com (Formerly Bridge Communications), XNS Systems Management
133+
TCPSM 9002 # 3Com (Formerly Bridge Communications), TCP/IP Systems Management
134+
DEBNI AAAA # DECNET? Used by VAX 6220 DEBNI
135+
SONIX FAF5 # Sonix Arpeggio
136+
VITAL FF00 # BBN VITAL-LanBridge cache wakeups
137+
MAX FFFF # Maximum valid ethernet type, reserved
138+
"""

scapy/modules/p0f.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import socket
1616
import random
1717

18-
from scapy.data import KnowledgeBase
18+
from scapy.data import KnowledgeBase, select_path
1919
from scapy.config import conf
2020
from scapy.compat import raw
2121
from scapy.layers.inet import IP, TCP, TCPOptions
@@ -29,10 +29,12 @@
2929
# unused import, only to initialize conf.route
3030
import scapy.route # noqa: F401
3131

32-
conf.p0f_base = "/etc/p0f/p0f.fp"
33-
conf.p0fa_base = "/etc/p0f/p0fa.fp"
34-
conf.p0fr_base = "/etc/p0f/p0fr.fp"
35-
conf.p0fo_base = "/etc/p0f/p0fo.fp"
32+
_p0fpaths = ["/etc/p0f", "/usr/share/p0f", "/opt/local"]
33+
34+
conf.p0f_base = select_path(_p0fpaths, "p0f.fp")
35+
conf.p0fa_base = select_path(_p0fpaths, "p0fa.fp")
36+
conf.p0fr_base = select_path(_p0fpaths, "p0fr.fp")
37+
conf.p0fo_base = select_path(_p0fpaths, "p0fo.fp")
3638

3739

3840
###############

scapy/modules/winpcapy.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
#------------------------------------------------------------------------------- # noqa: E501
1111
# Modified for scapy's usage - Mainly to support Npcap/Monitor mode
1212

13-
## This file is part of Scapy
14-
## See http://www.secdev.org/projects/scapy for more information
15-
## This program is published under a GPLv2 license
13+
# This file is part of Scapy
14+
# See http://www.secdev.org/projects/scapy for more information
15+
# This program is published under a GPLv2 license
1616

1717
from ctypes import *
1818
from ctypes.util import find_library

scapy/tools/generate_ethertypes.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# This file is part of Scapy
2+
# See http://www.secdev.org/projects/scapy for more information
3+
# Copyright (C) Philippe Biondi <[email protected]>
4+
# Copyright (C) Gabriel Potter <[email protected]>
5+
# This program is published under a GPLv2 license
6+
7+
"""Generate the ethertypes file (/etc/ethertypes)
8+
based on the OpenBSD source.
9+
10+
It allows to have a file with the format of
11+
http://git.netfilter.org/ebtables/plain/ethertypes
12+
but up-to-date.
13+
"""
14+
15+
import re
16+
import urllib.request
17+
18+
URL = "https://github.com/raw/openbsd/src/master/sys/net/ethertypes.h" # noqa: E501
19+
20+
with urllib.request.urlopen(URL) as stream:
21+
DATA = stream.read()
22+
23+
reg = rb".*ETHERTYPE_([^\s]+)\s.0x([0-9A-Fa-f]+).*\/\*(.*)\*\/"
24+
COMPILED = b"""#
25+
# Ethernet frame types
26+
# This file describes some of the various Ethernet
27+
# protocol types that are used on Ethernet networks.
28+
#
29+
# This list could be found on:
30+
# http://www.iana.org/assignments/ethernet-numbers
31+
# http://www.iana.org/assignments/ieee-802-numbers
32+
#
33+
# <name> <hexnumber> <alias1>...<alias35> #Comment
34+
#
35+
"""
36+
for line in DATA.split(b"\n"):
37+
match = re.match(reg, line)
38+
if match:
39+
name = match.group(1).ljust(16)
40+
number = match.group(2).upper()
41+
comment = match.group(3).strip()
42+
compiled_line = (b"%b%b" + b" " * 25 + b"# %b\n") % (
43+
name, number, comment
44+
)
45+
COMPILED += compiled_line
46+
47+
with open("ethertypes", "wb") as output:
48+
print("Written: %s" % output.write(COMPILED))

tox.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,4 @@ commands = flake8 scapy/
125125
ignore = E731, W504
126126
exclude = scapy/modules/six.py,
127127
scapy/modules/winpcapy.py
128+
scapy/modules/ethertypes.py

0 commit comments

Comments
 (0)