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
34 changes: 30 additions & 4 deletions scapy/layers/inet.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,21 +251,47 @@ class IPOption_Traceroute(IPOption):
IPField("originator_ip", "0.0.0.0")]


class IPOption_Timestamp_Pair(Packet):
"""An internet address / timestamp pair of an IP timestamp option.

Used when the option's flg field asks for addresses next to the
timestamps, i.e. flg 1 (timestamp_and_ip_addr) and 3
(prespecified_ip_addr).
"""
name = "IP Option Timestamp Pair"
fields_desc = [IPField("internet_address", "0.0.0.0"),
IntField("timestamp", 0)]

def extract_padding(self, s):
return b"", s


class IPOption_Timestamp(IPOption):
name = "IP Option Timestamp"
optclass = 2
option = 4
# RFC 791 requires the originating host to compose the option with a data
# area large enough to hold every timestamp it expects back, so the
# timestamps (and their addresses, depending on flg) form a list rather
# than a single entry.
fields_desc = [_IPOption_HDR,
ByteField("length", None),
ByteField("pointer", 9),
ByteField("pointer", 5),
BitField("oflw", 0, 4),
BitEnumField("flg", 1, 4,
{0: "timestamp_only",
1: "timestamp_and_ip_addr",
3: "prespecified_ip_addr"}),
ConditionalField(IPField("internet_address", "0.0.0.0"),
lambda pkt: pkt.flg != 0),
IntField('timestamp', 0)]
ConditionalField(
FieldListField(
"timestamps", [], IntField("", 0),
length_from=lambda pkt: max(0, (pkt.length or 4) - 4)), # noqa: E501
lambda pkt: pkt.flg == 0),
ConditionalField(
PacketListField(
"pairs", [], IPOption_Timestamp_Pair,
length_from=lambda pkt: max(0, (pkt.length or 4) - 4)), # noqa: E501
lambda pkt: pkt.flg != 0)]

def post_build(self, p, pay):
if self.length is None:
Expand Down
18 changes: 15 additions & 3 deletions test/scapy/layers/inet.uts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,24 @@ assert r == b'\x00'
r = raw(IPOption_LSRR(routers=["1.2.3.4","5.6.7.8"]))
r
assert r == b'\x83\x0b\x04\x01\x02\x03\x04\x05\x06\x07\x08'
r = raw(IPOption_Timestamp(internet_address='192.168.15.7', timestamp=11223344))
r = raw(IPOption_Timestamp(pointer=9, pairs=[IPOption_Timestamp_Pair(internet_address='192.168.15.7', timestamp=11223344)]))
r
assert r == b'D\x0c\t\x01\xc0\xa8\x0f\x07\x00\xabA0'
r = raw(IPOption_Timestamp(flg=0, length=8))
r = raw(IPOption_Timestamp(flg=0, pointer=9, timestamps=[0]))
r
assert r == b'D\x08\t\x00\x00\x00\x00\x00'
# RFC 791: the data area holds as many entries as the sender reserves room for
r = raw(IPOption_Timestamp(pairs=[IPOption_Timestamp_Pair(internet_address='192.168.15.7', timestamp=1), IPOption_Timestamp_Pair(internet_address='10.0.0.1', timestamp=2)]))
r
assert r == b'D\x14\x05\x01\xc0\xa8\x0f\x07\x00\x00\x00\x01\n\x00\x00\x01\x00\x00\x00\x02'
r = raw(IPOption_Timestamp(flg=0, timestamps=[1, 2, 3]))
r
assert r == b'D\x10\x05\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03'
# and they are dissected back into the list
p = IPOption_Timestamp(b'D\x14\x05\x01\xc0\xa8\x0f\x07\x00\x00\x00\x01\n\x00\x00\x01\x00\x00\x00\x02')
assert [(e.internet_address, e.timestamp) for e in p.pairs] == [('192.168.15.7', 1), ('10.0.0.1', 2)]
p = IPOption_Timestamp(b'D\x10\x05\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03')
assert p.timestamps == [1, 2, 3]

= IP options individual dissection
~ IP options
Expand Down Expand Up @@ -476,7 +488,7 @@ pkt = IP(len=54, ihl=6, options=[IPOption_RR()]) / TCP() / ("A" * 10)
bpkt = IP(raw(pkt))
assert bpkt.chksum == 0x70bc and bpkt.payload.chksum == 0x4b2c

pkt = IP(options=[IPOption_Timestamp()]) / TCP() / ("A" * 10)
pkt = IP(options=[IPOption_Timestamp(pointer=9, pairs=[IPOption_Timestamp_Pair()])]) / TCP() / ("A" * 10)
bpkt = IP(raw(pkt))
assert bpkt.chksum == 0x2caa and bpkt.payload.chksum == 0x4b2c

Expand Down
Loading