Skip to content

Commit 6c658dd

Browse files
authored
BGP: support tcp_reassemble (#4756)
1 parent 0224542 commit 6c658dd

4 files changed

Lines changed: 31 additions & 4 deletions

File tree

doc/scapy/usage.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,8 @@ The ``data`` argument is bytes and the ``metadata`` argument is a dictionary whi
847847
- ``metadata.get("tcp_psh", False)``: will be present if the PUSH flag is set
848848
- ``metadata.get("tcp_end", False)``: will be present if the END or RESET flag is set
849849

850+
If ``tcp_reassemble`` **returns any padding**, it will be kept for the next payload.
851+
850852
Filters
851853
-------
852854

scapy/contrib/bgp.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,17 @@ def dispatch_hook(cls, _pkt=None, *args, **kargs):
461461

462462
return _bgp_dispatcher(_pkt)
463463

464+
@classmethod
465+
def tcp_reassemble(cls, data, *args, **kwargs):
466+
if len(data) < 18:
467+
return None
468+
if data[:16] == _BGP_HEADER_MARKER:
469+
length = struct.unpack("!H", data[16:18])[0]
470+
if len(data) >= length:
471+
return cls(data[:length]) / conf.padding_layer(data[length:])
472+
else:
473+
return cls(data)
474+
464475
def post_build(self, p, pay):
465476
if self.len is None:
466477
length = len(p)
@@ -520,6 +531,8 @@ def dispatch_hook(cls, _pkt=None, *args, **kargs):
520531

521532
return _bgp_dispatcher(_pkt)
522533

534+
tcp_reassemble = BGPHeader.tcp_reassemble
535+
523536
def guess_payload_class(self, p):
524537
cls = None
525538
if len(p) > 15 and p[:16] == _BGP_HEADER_MARKER:
@@ -755,7 +768,8 @@ class ORFTuple(Packet):
755768
"entries",
756769
[],
757770
ORFTuple,
758-
count_from=lambda p: p.orf_number
771+
count_from=lambda p: p.orf_number,
772+
max_count=20000,
759773
)
760774
]
761775

@@ -811,7 +825,8 @@ class BGPCapORF(BGPCapability):
811825
"orf",
812826
[],
813827
BGPCapORFBlock,
814-
length_from=lambda p: p.length
828+
length_from=lambda p: p.length,
829+
max_count=20000,
815830
)
816831
]
817832

@@ -1910,7 +1925,8 @@ class BGPPAMPReachNLRI(Packet):
19101925
ConditionalField(IP6Field("nh_v6_link_local", "::"),
19111926
lambda x: x.afi == 2 and x.nh_addr_len == 32),
19121927
ByteField("reserved", 0),
1913-
MPReachNLRIPacketListField("nlri", [], BGPNLRI_IPv6)]
1928+
MPReachNLRIPacketListField("nlri", [], BGPNLRI_IPv6,
1929+
max_count=20000)]
19141930

19151931
def post_build(self, p, pay):
19161932
if self.nlri is None:
@@ -2216,7 +2232,8 @@ class BGPUpdate(BGP):
22162232
BGPPathAttr,
22172233
length_from=lambda p: p.path_attr_len
22182234
),
2219-
BGPNLRIPacketListField("nlri", [], "IPv4")
2235+
BGPNLRIPacketListField("nlri", [], "IPv4",
2236+
max_count=20000)
22202237
]
22212238

22222239
def post_build(self, p, pay):
@@ -2574,6 +2591,7 @@ class BGPORF(Packet):
25742591
[],
25752592
Packet,
25762593
length_from=lambda p: p.orf_len,
2594+
max_count=20000,
25772595
)
25782596
]
25792597

test/contrib/bgp.uts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ h = BGP(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x
8787
assert h.type == BGP.OPEN_TYPE
8888
assert h.len == 19
8989

90+
= BGP - Test TCP reassembly
91+
pkts = sniff(offline=scapy_path("/test/pcaps/bgp_fragmented.pcap.gz"), session=TCPSession)
92+
assert len(pkts) == 1
93+
assert BGPUpdate in pkts[0]
94+
assert len(pkts[0].nlri) == 512
95+
assert pkts[0].nlri[511].prefix == '91.0.177.0/24'
96+
9097
############################### BGPKeepAlive #################################
9198
+ BGPKeepAlive class tests
9299

test/pcaps/bgp_fragmented.pcap.gz

1.15 KB
Binary file not shown.

0 commit comments

Comments
 (0)