Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion doc/scapy/build_dissect.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1071,7 +1071,6 @@ TCP/IP
MACField
DestMACField(MACField)
SourceMACField(MACField)
ARPSourceMACField(MACField)

ICMPTimeStampField

Expand Down
2 changes: 2 additions & 0 deletions scapy/arch/windows/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,8 @@ def reload(self):
from scapy.arch.pcapdnet import load_winpcapy
load_winpcapy()
self.load()
# Reload conf.iface
conf.iface = get_working_if()

def show(self, resolve_mac=True, print_result=True):
"""Print list of available network interfaces in human readable form"""
Expand Down
59 changes: 38 additions & 21 deletions scapy/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,31 +275,41 @@ def __init__(self, flds, dflt):
self.dflt = dflt
self.name = self.dflt.name

def _iterate_fields_cond(self, pkt, val, use_val):
"""Internal function used by _find_fld_pkt & _find_fld_pkt_val"""
# Iterate through the fields
for fld, cond in self.flds:
if isinstance(cond, tuple):
if use_val:
if cond[1](pkt, val):
return fld
continue
else:
cond = cond[0]
if cond(pkt):
return fld
return self.dflt

def _find_fld_pkt(self, pkt):
"""Given a Packet instance `pkt`, returns the Field subclass to be
used. If you know the value to be set (e.g., in .addfield()), use
._find_fld_pkt_val() instead.

"""
for fld, cond in self.flds:
if isinstance(cond, tuple):
cond = cond[0]
if cond(pkt):
return fld
return self.dflt
return self._iterate_fields_cond(pkt, None, False)

def _find_fld_pkt_val(self, pkt, val):
"""Given a Packet instance `pkt` and the value `val` to be set,
returns the Field subclass to be used.
returns the Field subclass to be used, and the updated `val` if necessary.

"""
for fld, cond in self.flds:
if isinstance(cond, tuple):
if cond[1](pkt, val):
return fld
elif cond(pkt):
return fld
return self.dflt
fld = self._iterate_fields_cond(pkt, val, True)
# Default ? (in this case, let's make sure it's up-do-date)
dflts_pkt = pkt.default_fields
if val == dflts_pkt[self.name] and self.name not in pkt.fields:
dflts_pkt[self.name] = fld.default
val = fld.default
return fld, val

def _find_fld(self):
"""Returns the Field subclass to be used, depending on the Packet
Expand Down Expand Up @@ -331,25 +341,32 @@ def getfield(self, pkt, s):
return self._find_fld_pkt(pkt).getfield(pkt, s)

def addfield(self, pkt, s, val):
return self._find_fld_pkt_val(pkt, val).addfield(pkt, s, val)
fld, val = self._find_fld_pkt_val(pkt, val)
return fld.addfield(pkt, s, val)

def any2i(self, pkt, val):
return self._find_fld_pkt_val(pkt, val).any2i(pkt, val)
fld, val = self._find_fld_pkt_val(pkt, val)
return fld.any2i(pkt, val)

def h2i(self, pkt, val):
return self._find_fld_pkt_val(pkt, val).h2i(pkt, val)
fld, val = self._find_fld_pkt_val(pkt, val)
return fld.h2i(pkt, val)

def i2h(self, pkt, val):
return self._find_fld_pkt_val(pkt, val).i2h(pkt, val)
fld, val = self._find_fld_pkt_val(pkt, val)
return fld.i2h(pkt, val)

def i2m(self, pkt, val):
return self._find_fld_pkt_val(pkt, val).i2m(pkt, val)
fld, val = self._find_fld_pkt_val(pkt, val)
return fld.i2m(pkt, val)

def i2len(self, pkt, val):
return self._find_fld_pkt_val(pkt, val).i2len(pkt, val)
fld, val = self._find_fld_pkt_val(pkt, val)
return fld.i2len(pkt, val)

def i2repr(self, pkt, val):
return self._find_fld_pkt_val(pkt, val).i2repr(pkt, val)
fld, val = self._find_fld_pkt_val(pkt, val)
return fld.i2repr(pkt, val)

def register_owner(self, cls):
for fld, _ in self.flds:
Expand Down
17 changes: 9 additions & 8 deletions scapy/layers/l2.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,6 @@ def i2m(self, pkt, x):
return MACField.i2m(self, pkt, self.i2h(pkt, x))


class ARPSourceMACField(SourceMACField):
def __init__(self, name):
super(ARPSourceMACField, self).__init__(name)


# Layers

ETHER_TYPES['802_AD'] = 0x88a8
Expand Down Expand Up @@ -326,7 +321,7 @@ class ARP(Packet):
}),
MultipleTypeField(
[
(ARPSourceMACField("hwsrc"),
(SourceMACField("hwsrc"),
(lambda pkt: pkt.hwtype == 1 and pkt.hwlen == 6,
lambda pkt, val: pkt.hwtype == 1 and (
pkt.hwlen == 6 or (pkt.hwlen is None and
Expand Down Expand Up @@ -400,10 +395,16 @@ def answers(self, other):
return self_psrc[:len(other_pdst)] == other_pdst[:len(self_psrc)]

def route(self):
dst = self.pdst
fld, dst = self.getfield_and_val("pdst")
fld, dst = fld._find_fld_pkt_val(self, dst)
if isinstance(dst, Gen):
dst = next(iter(dst))
return conf.route.route(dst)
if isinstance(fld, IP6Field):
return conf.route6.route(dst)
elif isinstance(fld, IPField):
return conf.route.route(dst)
else:
return None

def extract_padding(self, s):
return "", s
Expand Down
31 changes: 30 additions & 1 deletion test/fields.uts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ r = m.addfield(None, b"FOO", "c0:01:be:ef:ba:be")
r
assert(r == b"FOO\xc0\x01\xbe\xef\xba\xbe" )

= SourceMACField, ARPSourceMACField
= SourceMACField, SourceMACField
conf.route.add(net="1.2.3.4/32", dev=conf.iface)
p = Ether() / ARP(pdst="1.2.3.4")
assert p.src == p.hwsrc == p[ARP].hwsrc == get_if_hwaddr(conf.iface)
Expand Down Expand Up @@ -1283,6 +1283,35 @@ a = DebugPacket(addr="scapy.net", atyp=0x3)
a = DebugPacket(raw(a))
assert a.addr == b"scapy.net."

= Test default values auto-update

class SweetPacket(Packet):
name = 'Sweet Celestian Packet'
fields_desc = [
IntField('switch', 0),
MultipleTypeField([
(XShortField('subfield', 0xDEAD), lambda pkt: pkt.switch == 1),
(XIntField('subfield', 0xBEEFBEEF), lambda pkt: pkt.switch == 2)],
XByteField('subfield', 0x88)
)
]

o = SweetPacket()
assert o.subfield == 0x88

o = SweetPacket(switch=1)
assert o.subfield == 0xDEAD

o = SweetPacket(switch=2)
assert o.subfield == 0xBEEFBEEF

o = SweetPacket()
assert o.subfield == 0x88
o.switch = 1
assert o.subfield == 0xDEAD
o.switch = 2
assert o.subfield == 0xBEEFBEEF

########
########
+ FlagsField
Expand Down