1
2
3 """Border Gateway Protocol."""
4 from __future__ import print_function
5 from __future__ import absolute_import
6
7 import struct
8 import socket
9
10 from . import dpkt
11 from .decorators import deprecated
12
13
14
15
16
17
18
19
20
21
22
23
24
25 OPEN = 1
26 UPDATE = 2
27 NOTIFICATION = 3
28 KEEPALIVE = 4
29 ROUTE_REFRESH = 5
30
31
32 ORIGIN = 1
33 AS_PATH = 2
34 NEXT_HOP = 3
35 MULTI_EXIT_DISC = 4
36 LOCAL_PREF = 5
37 ATOMIC_AGGREGATE = 6
38 AGGREGATOR = 7
39 COMMUNITIES = 8
40 ORIGINATOR_ID = 9
41 CLUSTER_LIST = 10
42 MP_REACH_NLRI = 14
43 MP_UNREACH_NLRI = 15
44
45
46 ORIGIN_IGP = 0
47 ORIGIN_EGP = 1
48 INCOMPLETE = 2
49
50
51 AS_SET = 1
52 AS_SEQUENCE = 2
53 AS_CONFED_SEQUENCE = 3
54 AS_CONFED_SET = 4
55
56
57 NO_EXPORT = 0xffffff01
58 NO_ADVERTISE = 0xffffff02
59 NO_EXPORT_SUBCONFED = 0xffffff03
60 NO_PEER = 0xffffff04
61
62
63 AFI_IPV4 = 1
64 AFI_IPV6 = 2
65
66
67 SAFI_UNICAST = 1
68 SAFI_MULTICAST = 2
69 SAFI_UNICAST_MULTICAST = 3
70
71
72 AUTHENTICATION = 1
73 CAPABILITY = 2
74
75
76 CAP_MULTIPROTOCOL = 1
77 CAP_ROUTE_REFRESH = 2
78
79
80 MESSAGE_HEADER_ERROR = 1
81 OPEN_MESSAGE_ERROR = 2
82 UPDATE_MESSAGE_ERROR = 3
83 HOLD_TIMER_EXPIRED = 4
84 FSM_ERROR = 5
85 CEASE = 6
86
87
88 CONNECTION_NOT_SYNCHRONIZED = 1
89 BAD_MESSAGE_LENGTH = 2
90 BAD_MESSAGE_TYPE = 3
91
92
93 UNSUPPORTED_VERSION_NUMBER = 1
94 BAD_PEER_AS = 2
95 BAD_BGP_IDENTIFIER = 3
96 UNSUPPORTED_OPTIONAL_PARAMETER = 4
97 AUTHENTICATION_FAILURE = 5
98 UNACCEPTABLE_HOLD_TIME = 6
99 UNSUPPORTED_CAPABILITY = 7
100
101
102 MALFORMED_ATTRIBUTE_LIST = 1
103 UNRECOGNIZED_ATTRIBUTE = 2
104 MISSING_ATTRIBUTE = 3
105 ATTRIBUTE_FLAGS_ERROR = 4
106 ATTRIBUTE_LENGTH_ERROR = 5
107 INVALID_ORIGIN_ATTRIBUTE = 6
108 AS_ROUTING_LOOP = 7
109 INVALID_NEXT_HOP_ATTRIBUTE = 8
110 OPTIONAL_ATTRIBUTE_ERROR = 9
111 INVALID_NETWORK_FIELD = 10
112 MALFORMED_AS_PATH = 11
113
114
115 MAX_NUMBER_OF_PREFIXES_REACHED = 1
116 ADMINISTRATIVE_SHUTDOWN = 2
117 PEER_DECONFIGURED = 3
118 ADMINISTRATIVE_RESET = 4
119 CONNECTION_REJECTED = 5
120 OTHER_CONFIGURATION_CHANGE = 6
121 CONNECTION_COLLISION_RESOLUTION = 7
122 OUT_OF_RESOURCES = 8
123
124
125 -class BGP(dpkt.Packet):
126 """Border Gateway Protocol.
127
128 BGP is an inter-AS routing protocol.
129 See more about the BGP on \
130 https://en.wikipedia.org/wiki/Border_Gateway_Protocol
131
132 Attributes:
133 __hdr__: Header fields of BGP.
134 #TODO
135 """
136
137 __hdr__ = (
138 ('marker', '16s', '\xff' * 16),
139 ('len', 'H', 0),
140 ('type', 'B', OPEN)
141 )
142
156
157 - class Open(dpkt.Packet):
158 __hdr__ = (
159 ('v', 'B', 4),
160 ('asn', 'H', 0),
161 ('holdtime', 'H', 0),
162 ('identifier', 'I', 0),
163 ('param_len', 'B', 0)
164 )
165 __hdr_defaults__ = {
166 'parameters': []
167 }
168
179
182
187
189 __hdr__ = (
190 ('type', 'B', 0),
191 ('len', 'B', 0)
192 )
193
202
204 __hdr__ = (
205 ('code', 'B', 0),
206 )
207
209 __hdr__ = (
210 ('code', 'B', 0),
211 ('len', 'B', 0)
212 )
213
217
219 __hdr_defaults__ = {
220 'withdrawn': [],
221 'attributes': [],
222 'announced': []
223 }
224
226 self.data = buf
227
228
229 wlen = struct.unpack('>H', self.data[:2])[0]
230 self.data = self.data[2:]
231 l = []
232 while wlen > 0:
233 route = RouteIPV4(self.data)
234 self.data = self.data[len(route):]
235 wlen -= len(route)
236 l.append(route)
237 self.withdrawn = l
238
239
240 plen = struct.unpack('>H', self.data[:2])[0]
241 self.data = self.data[2:]
242 l = []
243 while plen > 0:
244 attr = self.Attribute(self.data)
245 self.data = self.data[len(attr):]
246 plen -= len(attr)
247 l.append(attr)
248 self.attributes = l
249
250
251 l = []
252 while self.data:
253 route = RouteIPV4(self.data)
254 self.data = self.data[len(route):]
255 l.append(route)
256 self.announced = l
257
259 return 2 + sum(map(len, self.withdrawn)) + \
260 2 + sum(map(len, self.attributes)) + \
261 sum(map(len, self.announced))
262
264 return struct.pack('>H', sum(map(len, self.withdrawn))) + \
265 b''.join(map(bytes, self.withdrawn)) + \
266 struct.pack('>H', sum(map(len, self.attributes))) + \
267 b''.join(map(bytes, self.attributes)) + \
268 b''.join(map(bytes, self.announced))
269
271 __hdr__ = (
272 ('flags', 'B', 0),
273 ('type', 'B', 0)
274 )
275
276 @property
278 return (self.flags >> 7) & 0x1
279
280 @optional.setter
282 self.flags = (self.flags & ~0x80) | ((o & 0x1) << 7)
283
284 @property
286 return (self.flags >> 6) & 0x1
287
288 @transitive.setter
290 self.flags = (self.flags & ~0x40) | ((t & 0x1) << 6)
291
292 @property
294 return (self.flags >> 5) & 0x1
295
296 @partial.setter
298 self.flags = (self.flags & ~0x20) | ((p & 0x1) << 5)
299
300 @property
302 return (self.flags >> 4) & 0x1
303
304 @extended_length.setter
306 self.flags = (self.flags & ~0x10) | ((e & 0x1) << 4)
307
344
351
358
363
365 __hdr_defaults__ = {
366 'segments': []
367 }
368
377
380
382 return b''.join(map(bytes, self.data))
383
385 __hdr__ = (
386 ('type', 'B', 0),
387 ('len', 'B', 0)
388 )
389
398
401
403 as_str = b''
404 for AS in self.path:
405 as_str += struct.pack('>H', AS)
406 return self.pack_hdr() + as_str
407
409 __hdr__ = (
410 ('ip', 'I', 0),
411 )
412
414 __hdr__ = (
415 ('value', 'I', 0),
416 )
417
419 __hdr__ = (
420 ('value', 'I', 0),
421 )
422
432
434 __hdr__ = (
435 ('asn', 'H', 0),
436 ('ip', 'I', 0)
437 )
438
440 __hdr_defaults__ = {
441 'list': []
442 }
443
456
459
461 return b''.join(map(bytes, self.data))
462
464 __hdr__ = (
465 ('asn', 'H', 0),
466 ('value', 'H', 0)
467 )
468
470 __hdr__ = (
471 ('value', 'I', 0),
472 )
473
475 __hdr__ = (
476 ('value', 'I', 0),
477 )
478
480 __hdr_defaults__ = {
481 'list': []
482 }
483
485 self.data = buf
486 l = []
487 while self.data:
488 id = struct.unpack('>I', self.data[:4])[0]
489 self.data = self.data[4:]
490 l.append(id)
491 self.data = self.list = l
492
494 return 4 * len(self.list)
495
497 cluster_str = b''
498 for val in self.list:
499 cluster_str += struct.pack('>I', val)
500 return cluster_str
501
503 __hdr__ = (
504 ('afi', 'H', AFI_IPV4),
505 ('safi', 'B', SAFI_UNICAST),
506 )
507
541
547
549 return self.pack_hdr() + \
550 struct.pack('B', len(self.next_hop)) + \
551 bytes(self.next_hop) + \
552 struct.pack('B', len(self.snpas)) + \
553 b''.join(map(bytes, self.snpas)) + \
554 b''.join(map(bytes, self.announced))
555
556 - class SNPA(object):
557 __hdr__ = (
558 ('len', 'B', 0),
559 )
560
564
594
596 __hdr__ = (
597 ('code', 'B', 0),
598 ('subcode', 'B', 0),
599 )
600
604
614
621
624 __hdr__ = (
625 ('len', 'B', 0),
626 )
627
631
634 __hdr__ = (
635 ('len', 'B', 0),
636 )
637
643
645 cidr = '%s/%d' % (socket.inet_ntoa(self.prefix), self.len)
646 return '%s(%s)' % (self.__class__.__name__, cidr)
647
650
653
656 __hdr__ = (
657 ('len', 'B', 0),
658 )
659
665
668
671
672
673 __bgp1 = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x13\x04'
674 __bgp2 = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x63\x02\x00\x00\x00\x48\x40\x01\x01\x00\x40\x02\x0a\x01\x02\x01\xf4\x01\xf4\x02\x01\xfe\xbb\x40\x03\x04\xc0\xa8\x00\x0f\x40\x05\x04\x00\x00\x00\x64\x40\x06\x00\xc0\x07\x06\xfe\xba\xc0\xa8\x00\x0a\xc0\x08\x0c\xfe\xbf\x00\x01\x03\x16\x00\x04\x01\x54\x00\xfa\x80\x09\x04\xc0\xa8\x00\x0f\x80\x0a\x04\xc0\xa8\x00\xfa\x16\xc0\xa8\x04'
675 __bgp3 = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x79\x02\x00\x00\x00\x62\x40\x01\x01\x00\x40\x02\x00\x40\x05\x04\x00\x00\x00\x64\xc0\x10\x08\x00\x02\x01\x2c\x00\x00\x01\x2c\xc0\x80\x24\x00\x00\xfd\xe9\x40\x01\x01\x00\x40\x02\x04\x02\x01\x15\xb3\x40\x05\x04\x00\x00\x00\x2c\x80\x09\x04\x16\x05\x05\x05\x80\x0a\x04\x16\x05\x05\x05\x90\x0e\x00\x1e\x00\x01\x80\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x04\x04\x04\x00\x60\x18\x77\x01\x00\x00\x01\xf4\x00\x00\x01\xf4\x85'
676 __bgp4 = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x2d\x01\x04\x00\xed\x00\x5a\xc6\x6e\x83\x7d\x10\x02\x06\x01\x04\x00\x01\x00\x01\x02\x02\x80\x00\x02\x02\x02\x00'
684
762
763
764 if __name__ == '__main__':
765 test_pack()
766 test_unpack()
767 print('Tests Successful...')
768