Skip to content

Commit

Permalink
Merge pull request #490 from amgadhanafy/#fix-481
Browse files Browse the repository at this point in the history
Introduce 4 octet ASPathSegment, Extended NLRI Routes
  • Loading branch information
brifordwylie committed Sep 22, 2020
2 parents 2707678 + 3965d37 commit 93adab6
Showing 1 changed file with 143 additions and 2 deletions.
145 changes: 143 additions & 2 deletions dpkt/bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
# Cease Subcodes - RFC 4486
# NOPEER Community - RFC 3765
# Multiprotocol Extensions - 2858
# Advertisement of Multiple Paths in BGP - RFC 7911
# BGP Support for Four-Octet Autonomous System (AS) Number Spac - RFC 6793

# Message Types
OPEN = 1
Expand Down Expand Up @@ -252,7 +254,10 @@ def unpack(self, buf):
# Announced Routes
l = []
while self.data:
route = RouteIPV4(self.data)
if len(self.data) % 9 == 0:
route = ExtendedRouteIPV4(self.data)
else:
route = RouteIPV4(self.data)
self.data = self.data[len(route):]
l.append(route)
self.announced = l
Expand Down Expand Up @@ -371,8 +376,12 @@ class ASPath(dpkt.Packet):
def unpack(self, buf):
self.data = buf
l = []
as4 = len(self.data) == 6
while self.data:
seg = self.ASPathSegment(self.data)
if as4:
seg = self.ASPathSegment4(self.data)
else:
seg = self.ASPathSegment(self.data)
self.data = self.data[len(seg):]
l.append(seg)
self.data = self.segments = l
Expand Down Expand Up @@ -407,6 +416,31 @@ def __bytes__(self):
as_str += struct.pack('>H', AS)
return self.pack_hdr() + as_str

class ASPathSegment4(dpkt.Packet):
__hdr__ = (
('type', 'B', 0),
('len', 'B', 0)
)

def unpack(self, buf):
dpkt.Packet.unpack(self, buf)
l = []
for i in range(self.len):
if len(self.data) >= 4:
AS = struct.unpack('>I', self.data[:4])[0]
self.data = self.data[4:]
l.append(AS)
self.path = l

def __len__(self):
return self.__hdr_len__ + 4 * len(self.path)

def __bytes__(self):
as_str = b''
for AS in self.path:
as_str += struct.pack('>I', AS)
return self.pack_hdr() + as_str

class NextHop(dpkt.Packet):
__hdr__ = (
('ip', 'I', 0),
Expand Down Expand Up @@ -667,6 +701,16 @@ def __len__(self):
def __bytes__(self):
return self.pack_hdr() + self.prefix[:(self.len + 7) // 8]

class ExtendedRouteIPV4(RouteIPV4):
__hdr__ = (
('path_id', 'I', 0),
('len', 'B', 0),
)

def __repr__(self):
cidr = '%s/%d PathId %d' % (socket.inet_ntoa(self.prefix), self.len, self.path_id)
return '%s(%s)' % (self.__class__.__name__, cidr)


class RouteIPV6(dpkt.Packet):
__hdr__ = (
Expand Down Expand Up @@ -1018,9 +1062,106 @@ def test_bgp_mp_nlri_20_1_mp_reach_nlri_next_hop():
assert (socket.inet_ntop(socket.AF_INET6, mp_reach_nlri.next_hops[1]) == 'fe80::c001:bff:fe7e:0')
assert (mp_reach_nlri.next_hop == b''.join(mp_reach_nlri.next_hops))

def test_bgp_add_path_6_1_as_path():
# test for https://github.com/kbandla/dpkt/issues/481
# Error processing BGP data: packet 6 : message 1 of bgp-add-path.cap https://packetlife.net/media/captures/bgp-add-path.cap
__bgp = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x59\x02\x00\x00\x00\x30\x40\x01\x01\x00\x40\x02\x06\x02\x01\x00\x00\xfb\xff\x40\x03\x04\x0a\x00\x0e\x01\x80\x04\x04\x00\x00\x00\x00\x40\x05\x04\x00\x00\x00\x64\x80\x0a\x04\x0a\x00\x22\x04\x80\x09\x04\x0a\x00\x0f\x01\x00\x00\x00\x01\x20\x05\x05\x05\x05\x00\x00\x00\x01\x20\xc0\xa8\x01\x05'
bgp = BGP(__bgp)
assert (__bgp == bytes(bgp))
assert (len(bgp) == 89)
assert (bgp.type == UPDATE)
assert (len(bgp.update.withdrawn) == 0)
announced = bgp.update.announced
assert (len(announced) == 2)
assert (announced[0].len == 32)
assert (announced[0].path_id == 1)
assert (socket.inet_ntop(socket.AF_INET, bytes(announced[0].prefix)) == '5.5.5.5')
assert (announced[1].len == 32)
assert (announced[1].path_id == 1)
assert (socket.inet_ntop(socket.AF_INET, bytes(announced[1].prefix)) == '192.168.1.5')

assert (len(bgp.update.attributes) == 7)

attribute = bgp.update.attributes[0]
assert (attribute.type == ORIGIN)
assert (attribute.optional == False)
assert (attribute.transitive == True)
assert (attribute.partial == False)
assert (attribute.extended_length == False)
assert (attribute.flags == 0x40)
assert (attribute.len == 1)
assert (attribute.origin.type == ORIGIN_IGP)

attribute = bgp.update.attributes[1]
assert (attribute.type == AS_PATH)
assert (attribute.optional == False)
assert (attribute.transitive == True)
assert (attribute.partial == False)
assert (attribute.extended_length == False)
assert (attribute.flags == 0x40)
assert (attribute.len == 6)
assert (len(attribute.as_path.segments) == 1)
segment = attribute.as_path.segments[0]
assert (segment.type == AS_SEQUENCE)
assert (segment.len == 1)
assert (len(segment.path) == 1)
assert (segment.path[0] == 64511)

attribute = bgp.update.attributes[2]
assert (attribute.type == NEXT_HOP)
assert (attribute.optional == False)
assert (attribute.transitive == True)
assert (attribute.partial == False)
assert (attribute.extended_length == False)
assert (attribute.flags == 0x40)
assert (attribute.len == 4)
assert (socket.inet_ntop(socket.AF_INET, bytes(attribute.next_hop)) == '10.0.14.1')

attribute = bgp.update.attributes[3]
assert (attribute.type == MULTI_EXIT_DISC)
assert (attribute.optional == True)
assert (attribute.transitive == False)
assert (attribute.partial == False)
assert (attribute.extended_length == False)
assert (attribute.flags == 0x80)
assert (attribute.len == 4)
assert (attribute.multi_exit_disc.value == 0)

attribute = bgp.update.attributes[4]
assert (attribute.type == LOCAL_PREF)
assert (attribute.optional == False)
assert (attribute.transitive == True)
assert (attribute.partial == False)
assert (attribute.extended_length == False)
assert (attribute.flags == 0x40)
assert (attribute.len == 4)
assert (attribute.local_pref.value == 100)

attribute = bgp.update.attributes[5]
assert (attribute.type == CLUSTER_LIST)
assert (attribute.optional == True)
assert (attribute.transitive == False)
assert (attribute.partial == False)
assert (attribute.extended_length == False)
assert (attribute.flags == 0x80)
assert (attribute.len == 4)
assert (socket.inet_ntop(socket.AF_INET, bytes(attribute.cluster_list)) == '10.0.34.4')

attribute = bgp.update.attributes[6]
assert (attribute.type == ORIGINATOR_ID)
assert (attribute.optional == True)
assert (attribute.transitive == False)
assert (attribute.partial == False)
assert (attribute.extended_length == False)
assert (attribute.flags == 0x80)
assert (attribute.len == 4)
assert (socket.inet_ntop(socket.AF_INET, bytes(attribute.originator_id)) == '10.0.15.1')


if __name__ == '__main__':
test_pack()
test_unpack()
test_bgp_mp_nlri_20_1_mp_reach_nlri_next_hop()
test_bgp_add_path_6_1_as_path()
print('Tests Successful...')

0 comments on commit 93adab6

Please sign in to comment.