1
2
3 """Border Gateway Protocol."""
4
5 import dpkt
6 import struct
7
8
9
10
11
12
13
14
15
16
17
18
19 OPEN = 1
20 UPDATE = 2
21 NOTIFICATION = 3
22 KEEPALIVE = 4
23 ROUTE_REFRESH = 5
24
25
26 ORIGIN = 1
27 AS_PATH = 2
28 NEXT_HOP = 3
29 MULTI_EXIT_DISC = 4
30 LOCAL_PREF = 5
31 ATOMIC_AGGREGATE = 6
32 AGGREGATOR = 7
33 COMMUNITIES = 8
34 ORIGINATOR_ID = 9
35 CLUSTER_LIST = 10
36 MP_REACH_NLRI = 14
37 MP_UNREACH_NLRI = 15
38
39
40 ORIGIN_IGP = 0
41 ORIGIN_EGP = 1
42 INCOMPLETE = 2
43
44
45 AS_SET = 1
46 AS_SEQUENCE = 2
47 AS_CONFED_SEQUENCE = 3
48 AS_CONFED_SET = 4
49
50
51 NO_EXPORT = 0xffffff01L
52 NO_ADVERTISE = 0xffffff02L
53 NO_EXPORT_SUBCONFED = 0xffffff03L
54 NO_PEER = 0xffffff04L
55
56
57 AFI_IPV4 = 1
58 AFI_IPV6 = 2
59
60
61 SAFI_UNICAST = 1
62 SAFI_MULTICAST = 2
63 SAFI_UNICAST_MULTICAST = 3
64
65
66 AUTHENTICATION = 1
67 CAPABILITY = 2
68
69
70 CAP_MULTIPROTOCOL = 1
71 CAP_ROUTE_REFRESH = 2
72
73
74 MESSAGE_HEADER_ERROR = 1
75 OPEN_MESSAGE_ERROR = 2
76 UPDATE_MESSAGE_ERROR = 3
77 HOLD_TIMER_EXPIRED = 4
78 FSM_ERROR = 5
79 CEASE = 6
80
81
82 CONNECTION_NOT_SYNCHRONIZED = 1
83 BAD_MESSAGE_LENGTH = 2
84 BAD_MESSAGE_TYPE = 3
85
86
87 UNSUPPORTED_VERSION_NUMBER = 1
88 BAD_PEER_AS = 2
89 BAD_BGP_IDENTIFIER = 3
90 UNSUPPORTED_OPTIONAL_PARAMETER = 4
91 AUTHENTICATION_FAILURE = 5
92 UNACCEPTABLE_HOLD_TIME = 6
93 UNSUPPORTED_CAPABILITY = 7
94
95
96 MALFORMED_ATTRIBUTE_LIST = 1
97 UNRECOGNIZED_ATTRIBUTE = 2
98 MISSING_ATTRIBUTE = 3
99 ATTRIBUTE_FLAGS_ERROR = 4
100 ATTRIBUTE_LENGTH_ERROR = 5
101 INVALID_ORIGIN_ATTRIBUTE = 6
102 AS_ROUTING_LOOP = 7
103 INVALID_NEXT_HOP_ATTRIBUTE = 8
104 OPTIONAL_ATTRIBUTE_ERROR = 9
105 INVALID_NETWORK_FIELD = 10
106 MALFORMED_AS_PATH = 11
107
108
109 MAX_NUMBER_OF_PREFIXES_REACHED = 1
110 ADMINISTRATIVE_SHUTDOWN = 2
111 PEER_DECONFIGURED = 3
112 ADMINISTRATIVE_RESET = 4
113 CONNECTION_REJECTED = 5
114 OTHER_CONFIGURATION_CHANGE = 6
115 CONNECTION_COLLISION_RESOLUTION = 7
116 OUT_OF_RESOURCES = 8
117
118
119 -class BGP(dpkt.Packet):
120 __hdr__ = (
121 ('marker', '16s', '\x01' * 16),
122 ('len', 'H', 0),
123 ('type', 'B', OPEN)
124 )
125
139
140 - class Open(dpkt.Packet):
141 __hdr__ = (
142 ('v', 'B', 4),
143 ('as', 'H', 0),
144 ('holdtime', 'H', 0),
145 ('identifier', 'I', 0),
146 ('param_len', 'B', 0)
147 )
148
150 dpkt.Packet.unpack(self, buf)
151 l = []
152 plen = self.param_len
153 while plen > 0:
154 param = self.Parameter(self.data)
155 self.data = self.data[len(param):]
156 plen -= len(param)
157 l.append(param)
158 self.data = self.parameters = l
159
161 return self.__hdr_len__ + \
162 sum(map(len, self.parameters))
163
165 return self.pack_hdr() + \
166 ''.join(map(str, self.parameters))
167
169 __hdr__ = (
170 ('type', 'B', 0),
171 ('len', 'B', 0)
172 )
173
182
184 __hdr__ = (
185 ('code', 'B', 0),
186 )
187
189 __hdr__ = (
190 ('code', 'B', 0),
191 ('len', 'B', 0)
192 )
193
197
198
201 self.data = buf
202
203
204 wlen = struct.unpack('>H', self.data[:2])[0]
205 self.data = self.data[2:]
206 l = []
207 while wlen > 0:
208 route = RouteIPV4(self.data)
209 self.data = self.data[len(route):]
210 wlen -= len(route)
211 l.append(route)
212 self.withdrawn = l
213
214
215 plen = struct.unpack('>H', self.data[:2])[0]
216 self.data = self.data[2:]
217 l = []
218 while plen > 0:
219 attr = self.Attribute(self.data)
220 self.data = self.data[len(attr):]
221 plen -= len(attr)
222 l.append(attr)
223 self.attributes = l
224
225
226 l = []
227 while self.data:
228 route = RouteIPV4(self.data)
229 self.data = self.data[len(route):]
230 l.append(route)
231 self.announced = l
232
234 return 2 + sum(map(len, self.withdrawn)) + \
235 2 + sum(map(len, self.attributes)) + \
236 sum(map(len, self.announced))
237
239 return struct.pack('>H', sum(map(len, self.withdrawn))) + \
240 ''.join(map(str, self.withdrawn)) + \
241 struct.pack('>H', sum(map(len, self.attributes))) + \
242 ''.join(map(str, self.attributes)) + \
243 ''.join(map(str, self.announced))
244
246 __hdr__ = (
247 ('flags', 'B', 0),
248 ('type', 'B', 0)
249 )
250
252 return (self.flags >> 7) & 0x1
254 self.flags = (self.flags & ~0x80) | ((o & 0x1) << 7)
255 optional = property(_get_o, _set_o)
256
258 return (self.flags >> 6) & 0x1
260 self.flags = (self.flags & ~0x40) | ((t & 0x1) << 6)
261 transitive = property(_get_t, _set_t)
262
264 return (self.flags >> 5) & 0x1
266 self.flags = (self.flags & ~0x20) | ((p & 0x1) << 5)
267 partial = property(_get_p, _set_p)
268
270 return (self.flags >> 4) & 0x1
272 self.flags = (self.flags & ~0x10) | ((e & 0x1) << 4)
273 extended_length = property(_get_e, _set_e)
274
311
313 if self.extended_length:
314 attr_len = 2
315 else:
316 attr_len = 1
317 return self.__hdr_len__ + \
318 attr_len + \
319 len(self.data)
320
322 if self.extended_length:
323 attr_len_str = struct.pack('>H', self.len)
324 else:
325 attr_len_str = struct.pack('B', self.len)
326 return self.pack_hdr() + \
327 attr_len_str + \
328 str(self.data)
329
334
337 self.data = buf
338 l = []
339 while self.data:
340 seg = self.ASPathSegment(self.data)
341 self.data = self.data[len(seg):]
342 l.append(seg)
343 self.data = self.segments = l
344
346 return sum(map(len, self.data))
347
349 return ''.join(map(str, self.data))
350
352 __hdr__ = (
353 ('type', 'B', 0),
354 ('len', 'B', 0)
355 )
356
358 dpkt.Packet.unpack(self, buf)
359 l = []
360 for i in range(self.len):
361 AS = struct.unpack('>H', self.data[:2])[0]
362 self.data = self.data[2:]
363 l.append(AS)
364 self.data = self.path = l
365
369
371 as_str = ''
372 for AS in self.path:
373 as_str += struct.pack('>H', AS)
374 return self.pack_hdr() + \
375 as_str
376
378 __hdr__ = (
379 ('ip', 'I', 0),
380 )
381
383 __hdr__ = (
384 ('value', 'I', 0),
385 )
386
388 __hdr__ = (
389 ('value', 'I', 0),
390 )
391
401
403 __hdr__ = (
404 ('as', 'H', 0),
405 ('ip', 'I', 0)
406 )
407
410 self.data = buf
411 l = []
412 while self.data:
413 val = struct.unpack('>I', self.data[:4])[0]
414 if (val >= 0x00000000L and val <= 0x0000ffffL) or \
415 (val >= 0xffff0000L and val <= 0xffffffffL):
416 comm = self.ReservedCommunity(self.data[:4])
417 else:
418 comm = self.Community(self.data[:4])
419 self.data = self.data[len(comm):]
420 l.append(comm)
421 self.data = self.list = l
422
424 return sum(map(len, self.data))
425
427 return ''.join(map(str, self.data))
428
430 __hdr__ = (
431 ('as', 'H', 0),
432 ('value', 'H', 0)
433 )
434
436 __hdr__ = (
437 ('value', 'I', 0),
438 )
439
441 __hdr__ = (
442 ('value', 'I', 0),
443 )
444
447 self.data = buf
448 l = []
449 while self.data:
450 id = struct.unpack('>I', self.data[:4])[0]
451 self.data = self.data[4:]
452 l.append(id)
453 self.data = self.list = l
454
456 return 4 * len(self.list)
457
459 cluster_str = ''
460 for val in self.list:
461 cluster_str += struct.pack('>I', val)
462 return cluster_str
463
465 __hdr__ = (
466 ('afi', 'H', AFI_IPV4),
467 ('safi', 'B', SAFI_UNICAST),
468 )
469
471 dpkt.Packet.unpack(self, buf)
472
473
474 nlen = struct.unpack('B', self.data[:1])[0]
475 self.data = self.data[1:]
476 self.next_hop = self.data[:nlen]
477 self.data = self.data[nlen:]
478
479
480 l = []
481 num_snpas = struct.unpack('B', self.data[:1])[0]
482 self.data = self.data[1:]
483 for i in range(num_snpas):
484 snpa = self.SNPA(self.data)
485 self.data = self.data[len(snpa):]
486 l.append(snpa)
487 self.snpas = l
488
489 if self.afi == AFI_IPV4:
490 Route = RouteIPV4
491 elif self.afi == AFI_IPV6:
492 Route = RouteIPV6
493 else:
494 Route = RouteGeneric
495
496
497 l = []
498 while self.data:
499 route = Route(self.data)
500 self.data = self.data[len(route):]
501 l.append(route)
502 self.data = self.announced = l
503
505 return self.__hdr_len__ + \
506 1 + len(self.next_hop) + \
507 1 + sum(map(len, self.snpas)) + \
508 sum(map(len, self.announced))
509
511 return self.pack_hdr() + \
512 struct.pack('B', len(self.next_hop)) + \
513 str(self.next_hop) + \
514 struct.pack('B', len(self.snpas)) + \
515 ''.join(map(str, self.snpas)) + \
516 ''.join(map(str, self.announced))
517
519 __hdr__ = (
520 ('len', 'B', 0),
521 )
522
524 dpkt.Packet.unpack(self, buf)
525 self.data = self.data[:(self.len + 1) / 2]
526
528 __hdr__ = (
529 ('afi', 'H', AFI_IPV4),
530 ('safi', 'B', SAFI_UNICAST),
531 )
532
534 dpkt.Packet.unpack(self, buf)
535
536 if self.afi == AFI_IPV4:
537 Route = RouteIPV4
538 elif self.afi == AFI_IPV6:
539 Route = RouteIPV6
540 else:
541 Route = RouteGeneric
542
543
544 l = []
545 while self.data:
546 route = Route(self.data)
547 self.data = self.data[len(route):]
548 l.append(route)
549 self.data = self.withdrawn = l
550
552 return self.__hdr_len__ + \
553 sum(map(len, self.data))
554
556 return self.pack_hdr() + \
557 ''.join(map(str, self.data))
558
559
561 __hdr__ = (
562 ('code', 'B', 0),
563 ('subcode', 'B', 0),
564 )
565
569
570
580
581
588
589
591 __hdr__ = (
592 ('len', 'B', 0),
593 )
594
596 dpkt.Packet.unpack(self, buf)
597 self.data = self.prefix = self.data[:(self.len + 7) / 8]
598
600 __hdr__ = (
601 ('len', 'B', 0),
602 )
603
605 dpkt.Packet.unpack(self, buf)
606 tmp = self.data[:(self.len + 7) / 8]
607 tmp += (4 - len(tmp)) * '\x00'
608 self.data = self.prefix = tmp
609
613
615 return self.pack_hdr() + \
616 self.data[:(self.len + 7) / 8]
617
619 __hdr__ = (
620 ('len', 'B', 0),
621 )
622
624 dpkt.Packet.unpack(self, buf)
625 tmp = self.data[:(self.len + 7) / 8]
626 tmp += (16 - len(tmp)) * '\x00'
627 self.data = self.prefix = tmp
628
632
634 return self.pack_hdr() + \
635 self.data[:(self.len + 7) / 8]
636
637
638 if __name__ == '__main__':
639 import unittest
640
643 b1 = BGP(self.bgp1)
644 self.failUnless(self.bgp1 == str(b1))
645 b2 = BGP(self.bgp2)
646 self.failUnless(self.bgp2 == str(b2))
647 b3 = BGP(self.bgp3)
648 self.failUnless(self.bgp3 == str(b3))
649 b4 = BGP(self.bgp4)
650 self.failUnless(self.bgp4 == str(b4))
651
653 b1 = BGP(self.bgp1)
654 self.failUnless(b1.len == 19)
655 self.failUnless(b1.type == KEEPALIVE)
656 self.failUnless(b1.keepalive is not None)
657
658 b2 = BGP(self.bgp2)
659 self.failUnless(b2.type == UPDATE)
660 self.failUnless(len(b2.update.withdrawn) == 0)
661 self.failUnless(len(b2.update.announced) == 1)
662 self.failUnless(len(b2.update.attributes) == 9)
663 a = b2.update.attributes[1]
664 self.failUnless(a.type == AS_PATH)
665 self.failUnless(a.len == 10)
666 self.failUnless(len(a.as_path.segments) == 2)
667 s = a.as_path.segments[0]
668 self.failUnless(s.type == AS_SET)
669 self.failUnless(s.len == 2)
670 self.failUnless(len(s.path) == 2)
671 self.failUnless(s.path[0] == 500)
672
673 a = b2.update.attributes[6]
674 self.failUnless(a.type == COMMUNITIES)
675 self.failUnless(a.len == 12)
676 self.failUnless(len(a.communities.list) == 3)
677 c = a.communities.list[0]
678 self.failUnless(c.as == 65215)
679 self.failUnless(c.value == 1)
680 r = b2.update.announced[0]
681 self.failUnless(r.len == 22)
682 self.failUnless(r.prefix == '\xc0\xa8\x04\x00')
683
684 b3 = BGP(self.bgp3)
685 self.failUnless(b3.type == UPDATE)
686 self.failUnless(len(b3.update.withdrawn) == 0)
687 self.failUnless(len(b3.update.announced) == 0)
688 self.failUnless(len(b3.update.attributes) == 6)
689 a = b3.update.attributes[0]
690 self.failUnless(a.optional == False)
691 self.failUnless(a.transitive == True)
692 self.failUnless(a.partial == False)
693 self.failUnless(a.extended_length == False)
694 self.failUnless(a.type == ORIGIN)
695 self.failUnless(a.len == 1)
696 o = a.origin
697 self.failUnless(o.type == ORIGIN_IGP)
698 a = b3.update.attributes[5]
699 self.failUnless(a.optional == True)
700 self.failUnless(a.transitive == False)
701 self.failUnless(a.partial == False)
702 self.failUnless(a.extended_length == True)
703 self.failUnless(a.type == MP_REACH_NLRI)
704 self.failUnless(a.len == 30)
705 m = a.mp_reach_nlri
706 self.failUnless(m.afi == AFI_IPV4)
707 self.failUnless(len(m.snpas) == 0)
708 self.failUnless(len(m.announced) == 1)
709 p = m.announced[0]
710 self.failUnless(p.len == 96)
711
712 b4 = BGP(self.bgp4)
713 self.failUnless(b4.len == 45)
714 self.failUnless(b4.type == OPEN)
715 self.failUnless(b4.open.as == 237)
716 self.failUnless(b4.open.param_len == 16)
717 self.failUnless(len(b4.open.parameters) == 3)
718 p = b4.open.parameters[0]
719 self.failUnless(p.type == CAPABILITY)
720 self.failUnless(p.len == 6)
721 c = p.capability
722 self.failUnless(c.code == CAP_MULTIPROTOCOL)
723 self.failUnless(c.len == 4)
724 self.failUnless(c.data == '\x00\x01\x00\x01')
725 c = b4.open.parameters[2].capability
726 self.failUnless(c.code == CAP_ROUTE_REFRESH)
727 self.failUnless(c.len == 0)
728
729 bgp1 = '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x13\x04'
730 bgp2 = '\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'
731 bgp3 = '\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'
732 bgp4 = '\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'
733
734 unittest.main()
735