1
2
3 """Border Gateway Protocol."""
4
5 import dpkt
6 import struct, socket
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 ('asn', 'H', 0),
144 ('holdtime', 'H', 0),
145 ('identifier', 'I', 0),
146 ('param_len', 'B', 0)
147 )
148 __hdr_defaults__ = {
149 'parameters': []
150 }
151
162
166
168 params = ''.join(map(str, self.parameters))
169 self.param_len = len(params)
170 return self.pack_hdr() + params
171
173 __hdr__ = (
174 ('type', 'B', 0),
175 ('len', 'B', 0)
176 )
177
186
188 __hdr__ = (
189 ('code', 'B', 0),
190 )
191
193 __hdr__ = (
194 ('code', 'B', 0),
195 ('len', 'B', 0)
196 )
197
201
202
204 __hdr_defaults__ = {
205 'withdrawn': [],
206 'attributes': [],
207 'announced': []
208 }
209
211 self.data = buf
212
213
214 wlen = struct.unpack('>H', self.data[:2])[0]
215 self.data = self.data[2:]
216 l = []
217 while wlen > 0:
218 route = RouteIPV4(self.data)
219 self.data = self.data[len(route):]
220 wlen -= len(route)
221 l.append(route)
222 self.withdrawn = l
223
224
225 plen = struct.unpack('>H', self.data[:2])[0]
226 self.data = self.data[2:]
227 l = []
228 while plen > 0:
229 attr = self.Attribute(self.data)
230 self.data = self.data[len(attr):]
231 plen -= len(attr)
232 l.append(attr)
233 self.attributes = l
234
235
236 l = []
237 while self.data:
238 route = RouteIPV4(self.data)
239 self.data = self.data[len(route):]
240 l.append(route)
241 self.announced = l
242
244 return 2 + sum(map(len, self.withdrawn)) + \
245 2 + sum(map(len, self.attributes)) + \
246 sum(map(len, self.announced))
247
249 return struct.pack('>H', sum(map(len, self.withdrawn))) + \
250 ''.join(map(str, self.withdrawn)) + \
251 struct.pack('>H', sum(map(len, self.attributes))) + \
252 ''.join(map(str, self.attributes)) + \
253 ''.join(map(str, self.announced))
254
256 __hdr__ = (
257 ('flags', 'B', 0),
258 ('type', 'B', 0)
259 )
260
262 return (self.flags >> 7) & 0x1
264 self.flags = (self.flags & ~0x80) | ((o & 0x1) << 7)
265 optional = property(_get_o, _set_o)
266
268 return (self.flags >> 6) & 0x1
270 self.flags = (self.flags & ~0x40) | ((t & 0x1) << 6)
271 transitive = property(_get_t, _set_t)
272
274 return (self.flags >> 5) & 0x1
276 self.flags = (self.flags & ~0x20) | ((p & 0x1) << 5)
277 partial = property(_get_p, _set_p)
278
280 return (self.flags >> 4) & 0x1
282 self.flags = (self.flags & ~0x10) | ((e & 0x1) << 4)
283 extended_length = property(_get_e, _set_e)
284
321
330
339
344
346 __hdr_defaults__ = {
347 'segments': []
348 }
349
358
361
363 return ''.join(map(str, self.data))
364
366 __hdr__ = (
367 ('type', 'B', 0),
368 ('len', 'B', 0)
369 )
370
379
383
385 as_str = ''
386 for AS in self.path:
387 as_str += struct.pack('>H', AS)
388 return self.pack_hdr() + \
389 as_str
390
392 __hdr__ = (
393 ('ip', 'I', 0),
394 )
395
397 __hdr__ = (
398 ('value', 'I', 0),
399 )
400
402 __hdr__ = (
403 ('value', 'I', 0),
404 )
405
415
417 __hdr__ = (
418 ('asn', 'H', 0),
419 ('ip', 'I', 0)
420 )
421
423 __hdr_defaults__ = {
424 'list': []
425 }
426
440
443
445 return ''.join(map(str, self.data))
446
448 __hdr__ = (
449 ('asn', 'H', 0),
450 ('value', 'H', 0)
451 )
452
454 __hdr__ = (
455 ('value', 'I', 0),
456 )
457
459 __hdr__ = (
460 ('value', 'I', 0),
461 )
462
464 __hdr_defaults__ = {
465 'list': []
466 }
467
469 self.data = buf
470 l = []
471 while self.data:
472 id = struct.unpack('>I', self.data[:4])[0]
473 self.data = self.data[4:]
474 l.append(id)
475 self.data = self.list = l
476
478 return 4 * len(self.list)
479
481 cluster_str = ''
482 for val in self.list:
483 cluster_str += struct.pack('>I', val)
484 return cluster_str
485
487 __hdr__ = (
488 ('afi', 'H', AFI_IPV4),
489 ('safi', 'B', SAFI_UNICAST),
490 )
491
525
531
533 return self.pack_hdr() + \
534 struct.pack('B', len(self.next_hop)) + \
535 str(self.next_hop) + \
536 struct.pack('B', len(self.snpas)) + \
537 ''.join(map(str, self.snpas)) + \
538 ''.join(map(str, self.announced))
539
541 __hdr__ = (
542 ('len', 'B', 0),
543 )
544
548
580
581
583 __hdr__ = (
584 ('code', 'B', 0),
585 ('subcode', 'B', 0),
586 )
587
591
592
602
603
610
611
613 __hdr__ = (
614 ('len', 'B', 0),
615 )
616
620
622 __hdr__ = (
623 ('len', 'B', 0),
624 )
625
631
633 cidr = '%s/%d' % (socket.inet_ntoa(self.prefix), self.len)
634 return '%s(%s)' % (self.__class__.__name__, cidr)
635
639
643
645 __hdr__ = (
646 ('len', 'B', 0),
647 )
648
654
658
662
663
664 if __name__ == '__main__':
665 import unittest
666
669 b1 = BGP(self.bgp1)
670 self.failUnless(self.bgp1 == str(b1))
671 b2 = BGP(self.bgp2)
672 self.failUnless(self.bgp2 == str(b2))
673 b3 = BGP(self.bgp3)
674 self.failUnless(self.bgp3 == str(b3))
675 b4 = BGP(self.bgp4)
676 self.failUnless(self.bgp4 == str(b4))
677
679 b1 = BGP(self.bgp1)
680 self.failUnless(b1.len == 19)
681 self.failUnless(b1.type == KEEPALIVE)
682 self.failUnless(b1.keepalive is not None)
683
684 b2 = BGP(self.bgp2)
685 self.failUnless(b2.type == UPDATE)
686 self.failUnless(len(b2.update.withdrawn) == 0)
687 self.failUnless(len(b2.update.announced) == 1)
688 self.failUnless(len(b2.update.attributes) == 9)
689 a = b2.update.attributes[1]
690 self.failUnless(a.type == AS_PATH)
691 self.failUnless(a.len == 10)
692 self.failUnless(len(a.as_path.segments) == 2)
693 s = a.as_path.segments[0]
694 self.failUnless(s.type == AS_SET)
695 self.failUnless(s.len == 2)
696 self.failUnless(len(s.path) == 2)
697 self.failUnless(s.path[0] == 500)
698
699 a = b2.update.attributes[6]
700 self.failUnless(a.type == COMMUNITIES)
701 self.failUnless(a.len == 12)
702 self.failUnless(len(a.communities.list) == 3)
703 c = a.communities.list[0]
704 self.failUnless(c.asn == 65215)
705 self.failUnless(c.value == 1)
706 r = b2.update.announced[0]
707 self.failUnless(r.len == 22)
708 self.failUnless(r.prefix == '\xc0\xa8\x04\x00')
709
710 b3 = BGP(self.bgp3)
711 self.failUnless(b3.type == UPDATE)
712 self.failUnless(len(b3.update.withdrawn) == 0)
713 self.failUnless(len(b3.update.announced) == 0)
714 self.failUnless(len(b3.update.attributes) == 6)
715 a = b3.update.attributes[0]
716 self.failUnless(a.optional == False)
717 self.failUnless(a.transitive == True)
718 self.failUnless(a.partial == False)
719 self.failUnless(a.extended_length == False)
720 self.failUnless(a.type == ORIGIN)
721 self.failUnless(a.len == 1)
722 o = a.origin
723 self.failUnless(o.type == ORIGIN_IGP)
724 a = b3.update.attributes[5]
725 self.failUnless(a.optional == True)
726 self.failUnless(a.transitive == False)
727 self.failUnless(a.partial == False)
728 self.failUnless(a.extended_length == True)
729 self.failUnless(a.type == MP_REACH_NLRI)
730 self.failUnless(a.len == 30)
731 m = a.mp_reach_nlri
732 self.failUnless(m.afi == AFI_IPV4)
733 self.failUnless(len(m.snpas) == 0)
734 self.failUnless(len(m.announced) == 1)
735 p = m.announced[0]
736 self.failUnless(p.len == 96)
737
738 b4 = BGP(self.bgp4)
739 self.failUnless(b4.len == 45)
740 self.failUnless(b4.type == OPEN)
741 self.failUnless(b4.open.asn == 237)
742 self.failUnless(b4.open.param_len == 16)
743 self.failUnless(len(b4.open.parameters) == 3)
744 p = b4.open.parameters[0]
745 self.failUnless(p.type == CAPABILITY)
746 self.failUnless(p.len == 6)
747 c = p.capability
748 self.failUnless(c.code == CAP_MULTIPROTOCOL)
749 self.failUnless(c.len == 4)
750 self.failUnless(c.data == '\x00\x01\x00\x01')
751 c = b4.open.parameters[2].capability
752 self.failUnless(c.code == CAP_ROUTE_REFRESH)
753 self.failUnless(c.len == 0)
754
755 bgp1 = '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x13\x04'
756 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'
757 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'
758 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'
759
760 unittest.main()
761