Skip to content
Open
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
49 changes: 26 additions & 23 deletions scapy/contrib/rpl_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import struct
from scapy.packet import Packet
from scapy.fields import ByteEnumField, ByteField, ShortField, BitField, \
BitEnumField, FieldLenField, StrLenField, IntField, PacketListField
BitEnumField, StrLenField, IntField, PacketListField
from scapy.layers.inet6 import _PhantomAutoPadField
from scapy.contrib.rpl import RPLOPTSSTR, RPLOPTS, _RPLGuessOption

Expand All @@ -48,28 +48,6 @@ def post_build(self, pkt, pay):
8: "Link Color"}


class DAGMCObjUnknown(Packet):
"""
Dummy unknown metric/constraint
"""
name = 'Unknown DAGMC Object Option'
fields_desc = [ByteEnumField("otype", 3, DAGMC_OBJTYPE),
FieldLenField("olen", None, length_of="odata", fmt="B"),
StrLenField("odata", "",
length_from=lambda pkt: pkt.olen)]

@classmethod
def dispatch_hook(cls, _pkt=None, *_, **kargs):
"""
Dispatch hook for DAGMC sub-fields
"""
if _pkt:
opt_type = _pkt[0] # Option type
if opt_type in DAGMC_CLS:
return DAGMC_CLS[opt_type]
return cls


AGG_RTMETRIC = {0: "additive",
1: "maximum",
2: "minimum",
Expand Down Expand Up @@ -107,6 +85,31 @@ def extract_padding(self, s):
return s[:tmp_len], s[tmp_len:]


class DAGMCObjUnknown(DAGMCObj):
"""
Metric/constraint object of a type without its own class: the
common header of RFC 6551 - 2.1, then Length octets of body
"""
name = 'Unknown DAGMC Object Option'
deprecated_fields = {
"olen": ("len", "2.8.1"),
}
fields_desc = DAGMCObj.fields_desc + [
StrLenField("odata", "", length_from=lambda pkt: pkt.len)
]

@classmethod
def dispatch_hook(cls, _pkt=None, *_, **kargs):
"""
Dispatch hook for DAGMC sub-fields
"""
if _pkt:
opt_type = _pkt[0] # Option type
if opt_type in DAGMC_CLS:
return DAGMC_CLS[opt_type]
return cls


class RPLDAGMCNSA(DAGMCObj):
"""
DAG Metric: Node State and Attributes
Expand Down
26 changes: 26 additions & 0 deletions test/contrib/rpl.uts
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,29 @@ assert raw(p.options[0].payload) == bytes.fromhex("0241")
assert p.options[1].HopCount == 4
p.clear_cache()
assert raw(p) == raw_mc

= RPL DAG Metric Container with an object of an unassigned type
# An unknown object has the same 4-octet header as the others (RFC 6551, 2.1)

# Type 9 with a 2-octet body, then Hop Count
raw_mc = bytes.fromhex("020c09000002abcd" + "030000020003")
p = RPLOptDAGMC(raw_mc)
assert [type(o) for o in p.options] == [DAGMCObjUnknown, RPLDAGMCHopCount]
assert p.options[0].otype == 9
assert p.options[0].len == 2
assert p.options[0].odata == b"\xab\xcd"
assert p.options[0].olen == 2 # deprecated name of len
assert p.options[1].HopCount == 3
p.clear_cache()
assert raw(p) == raw_mc

# Type 9 with an empty body between Hop Count and Link ETX
raw_mc = bytes.fromhex("0210030000020003" + "09000000" + "070000020100")
p = RPLOptDAGMC(raw_mc)
assert [type(o) for o in p.options] == [RPLDAGMCHopCount, DAGMCObjUnknown, RPLDAGMCLinkETX]
assert p.options[2].ETX == 256

# Building fills in the Length of the body
assert raw(DAGMCObjUnknown(otype=9, P=1, odata=b"\xab\xcd")) == bytes.fromhex("09040002abcd")
mc = RPLOptDAGMC(options=[DAGMCObjUnknown(otype=9, odata=b"\xab\xcd"), RPLDAGMCHopCount(HopCount=3)])
assert raw(mc) == bytes.fromhex("020c09000002abcd030000020003")
Loading