bgp4r 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/COPYING +674 -0
  2. data/LICENSE.txt +53 -0
  3. data/README.rdoc +259 -0
  4. data/bgp/aggregator.rb +104 -0
  5. data/bgp/as_path.rb +223 -0
  6. data/bgp/atomic_aggregate.rb +42 -0
  7. data/bgp/attribute.rb +181 -0
  8. data/bgp/attributes.rb +34 -0
  9. data/bgp/cluster_list.rb +117 -0
  10. data/bgp/common.rb +204 -0
  11. data/bgp/communities.rb +139 -0
  12. data/bgp/extended_communities.rb +107 -0
  13. data/bgp/extended_community.rb +254 -0
  14. data/bgp/iana.rb +269 -0
  15. data/bgp/io.rb +116 -0
  16. data/bgp/label.rb +94 -0
  17. data/bgp/local_pref.rb +75 -0
  18. data/bgp/message.rb +894 -0
  19. data/bgp/mp_reach.rb +208 -0
  20. data/bgp/multi_exit_disc.rb +76 -0
  21. data/bgp/neighbor.rb +291 -0
  22. data/bgp/next_hop.rb +63 -0
  23. data/bgp/nlri.rb +303 -0
  24. data/bgp/orf.rb +88 -0
  25. data/bgp/origin.rb +88 -0
  26. data/bgp/originator_id.rb +73 -0
  27. data/bgp/path_attribute.rb +210 -0
  28. data/bgp/prefix_orf.rb +263 -0
  29. data/bgp/rd.rb +107 -0
  30. data/examples/bgp +65 -0
  31. data/examples/routegen +85 -0
  32. data/examples/routegen.yml +50 -0
  33. data/test/aggregator_test.rb +66 -0
  34. data/test/as_path_test.rb +149 -0
  35. data/test/atomic_aggregate_test.rb +35 -0
  36. data/test/attribute_test.rb +57 -0
  37. data/test/cluster_list_test.rb +39 -0
  38. data/test/common_test.rb +68 -0
  39. data/test/communities_test.rb +75 -0
  40. data/test/extended_communities_test.rb +111 -0
  41. data/test/extended_community_test.rb +93 -0
  42. data/test/label_test.rb +50 -0
  43. data/test/local_pref_test.rb +43 -0
  44. data/test/message_test.rb +294 -0
  45. data/test/mp_reach_test.rb +143 -0
  46. data/test/multi_exit_disc_test.rb +46 -0
  47. data/test/neighbor_test.rb +50 -0
  48. data/test/next_hop_test.rb +37 -0
  49. data/test/nlri_test.rb +189 -0
  50. data/test/origin_test.rb +57 -0
  51. data/test/originator_id_test.rb +38 -0
  52. data/test/path_attribute_test.rb +127 -0
  53. data/test/prefix_orf_test.rb +97 -0
  54. data/test/rd_test.rb +44 -0
  55. metadata +133 -0
data/bgp/nlri.rb ADDED
@@ -0,0 +1,303 @@
1
+ #--
2
+ # Copyright 2008, 2009 Jean-Michel Esnault.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #
6
+ #
7
+ # This file is part of BGP4R.
8
+ #
9
+ # BGP4R is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # BGP4R is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with BGP4R. If not, see <http://www.gnu.org/licenses/>.
21
+ #++
22
+
23
+
24
+ require 'bgp/common'
25
+ require 'bgp/iana'
26
+
27
+ module BGP
28
+
29
+ class Base_nlri
30
+
31
+ class Nlri_element < IPAddr
32
+ def to_s
33
+ [super, mlen].join('/')
34
+ end
35
+ def encode_next_hop
36
+ hton
37
+ end
38
+ def nbyte
39
+ (mlen+7)/8
40
+ end
41
+ def encode(len_included=true)
42
+ nbyte = (mlen+7)/8
43
+ if len_included
44
+ [mlen, hton].pack("Ca#{nbyte}")
45
+ else
46
+ [hton].pack("a#{nbyte}")
47
+ end
48
+ end
49
+ def parse4(arg)
50
+ s = arg.dup
51
+ s +=([0]*3).pack('C*')
52
+ plen, *nlri = s.unpack('CC4')
53
+ arg.slice!(0,1+(plen+7)/8) # trim arg accordingly
54
+ ipaddr = nlri.collect { |n| n.to_s }.join('.') + "/" + plen .to_s
55
+ end
56
+ def parse6(arg)
57
+ s = arg.dup
58
+ s +=([0]*16).pack('C*')
59
+ plen, *nlri = s.unpack('Cn8')
60
+ arg.slice!(0,1+(plen+7)/8) # trim arg accordingly
61
+ ipaddr = nlri.collect { |n| n.to_s(16) }.join(':') + "/" + plen .to_s
62
+ end
63
+ end
64
+
65
+ class Ip4 < Nlri_element
66
+ def initialize(arg)
67
+ if arg.is_a?(String) and arg.packed?
68
+ super(parse4(arg))
69
+ elsif arg.is_a?(Ip4)
70
+ super(arg.to_s)
71
+ else
72
+ super(arg)
73
+ end
74
+ end
75
+ end
76
+
77
+ class Ip6 < Nlri_element
78
+ def initialize(arg)
79
+ if arg.is_a?(String) and arg.packed?
80
+ super(parse6(arg))
81
+ elsif arg.is_a?(Ip6)
82
+ super(arg.to_s)
83
+ else
84
+ super(arg)
85
+ end
86
+ end
87
+ end
88
+
89
+ attr_reader :nlris
90
+
91
+ def initialize(*args)
92
+ if args[0].is_a?(String) and args[0].is_packed?
93
+ parse(args[0])
94
+ else
95
+ add(*args)
96
+ end
97
+ end
98
+ def add(*args)
99
+ @nlris ||=[]
100
+ args.flatten.each { |arg| @nlris << Ip4.new(arg) }
101
+ end
102
+ alias << add
103
+
104
+ def parse(s)
105
+ @nlris ||=[]
106
+ while s.size>0
107
+ add(s)
108
+ end
109
+ end
110
+
111
+ def encode(len_included=false)
112
+ enc = @nlris.collect { |x| x.encode }.join
113
+ if len_included
114
+ [enc.size].pack('n') + enc
115
+ else
116
+ enc
117
+ end
118
+ end
119
+
120
+ def to_s
121
+ @nlris.join("\n")
122
+ end
123
+
124
+ def size
125
+ @nlris.size
126
+ end
127
+
128
+ end
129
+
130
+ class Nlri < Base_nlri
131
+ def encode
132
+ super
133
+ end
134
+ end
135
+ class Withdrawn < Base_nlri
136
+ def encode(len_included=true)
137
+ super(len_included)
138
+ end
139
+ end
140
+
141
+ class Nlri
142
+ def self.factory(s, afi, safi)
143
+ case safi
144
+ when 1,2
145
+ Prefix.new(s.is_packed, afi)
146
+ when 4,128,129
147
+ Labeled.new(s.is_packed, afi, safi)
148
+ end
149
+ end
150
+ end
151
+
152
+ class Prefix < Nlri::Nlri_element
153
+ def initialize(*args)
154
+ if args[0].is_a?(String) and args[0].packed?
155
+ afi = args[1] ||=1
156
+ case afi
157
+ when :ip4,1 ; super(parse4(args[0]))
158
+ when :ip6,2 ; super(parse6(args[0]))
159
+ end
160
+ elsif args[0].is_a?(Nlri::Ip4) or args[0].is_a?(Nlri::Ip6) or args[0].is_a?(Prefix)
161
+ super(args[0].to_s)
162
+ else
163
+ super(*args)
164
+ end
165
+ end
166
+ def afi
167
+ if ipv4?
168
+ IANA::AFI::IP
169
+ elsif ipv6?
170
+ IANA::AFI::IP6
171
+ end
172
+ end
173
+ alias bit_length mlen
174
+
175
+ def nexthop
176
+ to_s.split('/')[0]
177
+ end
178
+
179
+ end
180
+
181
+ class Inet_unicast < Prefix
182
+ def safi
183
+ IANA::SAFI::UNICAST_NLRI
184
+ end
185
+ end
186
+
187
+ class Inet_multicast < Prefix
188
+ def safi
189
+ IANA::SAFI::MULTICAST_NLRI
190
+ end
191
+ end
192
+
193
+ end
194
+
195
+ require 'bgp/rd'
196
+
197
+ module BGP
198
+ class Vpn
199
+ attr_reader :prefix, :rd
200
+ def initialize(*args)
201
+ if args.size>0 and args[0].is_a?(String) and args[0].is_packed?
202
+ parse(*args)
203
+ else
204
+ prefix, *rd = args
205
+ self.prefix=(prefix)
206
+ self.rd=rd
207
+ end
208
+ end
209
+ def prefix=(arg)
210
+ if arg.is_a?(Prefix)
211
+ @prefix=arg
212
+ else
213
+ @prefix=Prefix.new(arg)
214
+ end
215
+ end
216
+ def rd=(args)
217
+ args.flatten!
218
+ if args.empty?
219
+ @rd=Rd.new
220
+ elsif args.size==1 and args[0].is_a?(BGP::Rd)
221
+ @rd=args[0]
222
+ else
223
+ @rd=Rd.new(*args)
224
+ end
225
+ end
226
+ # len_included arg is used by labeled encode()
227
+ def encode_next_hop
228
+ Rd.new.encode + @prefix.encode(false)
229
+ end
230
+ def encode(len_included=true)
231
+ if len_included
232
+ [bit_length, @rd.encode, @prefix.encode(false)].pack('Ca*a*')
233
+ else
234
+ @rd.encode + @prefix.encode(false)
235
+ end
236
+ end
237
+ def bit_length
238
+ @rd.bit_length + @prefix.mlen
239
+ end
240
+ def ipv4?
241
+ @prefix.ipv4?
242
+ end
243
+ def afi
244
+ @prefix.afi
245
+ end
246
+ def ipv6?
247
+ @prefix.ipv6?
248
+ end
249
+ def parse(s, afi=1)
250
+ nbits = s.slice!(0,1).unpack('C')[0]
251
+ rd,vpn = s.slice!(0,(7+nbits)/8).unpack("a8a*")
252
+ @rd = Rd.new(rd.is_packed)
253
+ @prefix= Prefix.new([nbits-64,vpn].pack('Ca*'), afi)
254
+ end
255
+ def nexthop
256
+ @prefix.nexthop
257
+ end
258
+ def to_s
259
+ #Label Stack=5806 (bottom) RD=3215:317720610, IPv4=10.45.142.64/32
260
+ "#{@rd.to_s(false)}, #{@prefix.ipv4? ? 'IPv4' : 'IPv6'}=#{@prefix.to_s}"
261
+ end
262
+ end
263
+ end
264
+
265
+ require 'bgp/label'
266
+ module BGP
267
+ class Labeled
268
+ def initialize(*args)
269
+ if args.size>0 and args[0].is_a?(String) and args[0].is_packed?
270
+ parse(*args)
271
+ else
272
+ @prefix, *labels = args
273
+ @labels = Label_stack.new(*labels)
274
+ end
275
+ end
276
+ def bit_length
277
+ @labels.bit_length+@prefix.bit_length
278
+ end
279
+ def encode
280
+ [bit_length, @labels.encode, @prefix.encode(false)].pack('Ca*a*')
281
+ end
282
+ def to_s
283
+ "#{@labels} #{@prefix}"
284
+ end
285
+ def afi
286
+ @prefix.afi
287
+ end
288
+ def parse(s, afi=1, safi=1)
289
+ bitlen = s.slice!(0,1).unpack('C')[0]
290
+ @labels = Label_stack.new(s)
291
+ mlen = bitlen - (24*@labels.size)
292
+ prefix = [mlen,s.slice!(0,(mlen+7)/8)].pack("Ca*")
293
+ case safi
294
+ when 128,129
295
+ @prefix = Vpn.new(prefix)
296
+ else
297
+ @prefix = Prefix.new(prefix, afi)
298
+ end
299
+ end
300
+ end
301
+ end
302
+
303
+ load "../test/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
data/bgp/orf.rb ADDED
@@ -0,0 +1,88 @@
1
+ #--
2
+ # Copyright 2008, 2009 Jean-Michel Esnault.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #
6
+ #
7
+ # This file is part of BGP4R.
8
+ #
9
+ # BGP4R is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # BGP4R is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with BGP4R. If not, see <http://www.gnu.org/licenses/>.
21
+ #++
22
+
23
+
24
+ module BGP
25
+ module ORF
26
+ PREFIX = 64 # rfc 5292
27
+ end
28
+
29
+ class Orf
30
+
31
+ class Entry
32
+ end
33
+
34
+ attr_accessor :type, :entries
35
+
36
+ def initialize(*args)
37
+ @entries=[]
38
+ if args[0].is_a?(String) and args.size==1
39
+ parse(args[0])
40
+ elsif args.size==1 and args[0].is_a?(self.class) and args[0].respond_to?(:encode)
41
+ parse(args[0].encode)
42
+ else
43
+ @type, *arr = args
44
+ arr.flatten.each { |e| add(e) }
45
+ end
46
+ end
47
+
48
+ def add(e)
49
+ raise ArgumentError, "invalid argument" unless e.is_a?(Entry)
50
+ @entries << e
51
+ self
52
+ end
53
+ alias << add
54
+
55
+ def encode
56
+ entries = @entries.collect { |e| e.encode }.join
57
+ [@type, entries.size, entries].pack('Cna*')
58
+ end
59
+
60
+ def to_s
61
+ "#{self.class}, #{@entries.size} entries:\n " + @entries.collect { |e| e.to_s}.join("\n ")
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+
68
+ __END__
69
+
70
+
71
+ an ORF as a type and entries
72
+
73
+ +--------------------------------------------------+
74
+ | ORF Type (1 octet) |
75
+ +--------------------------------------------------+
76
+ | Length of ORFs (2 octets) |
77
+ +--------------------------------------------------+
78
+ | First ORF entry (variable) |
79
+ +--------------------------------------------------+
80
+ | Second ORF entry (variable) |
81
+ +--------------------------------------------------+
82
+ | ... |
83
+ +--------------------------------------------------+
84
+ | N-th ORF entry (variable) |
85
+ +--------------------------------------------------+
86
+
87
+ http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#bgp-parameters-9
88
+
data/bgp/origin.rb ADDED
@@ -0,0 +1,88 @@
1
+ #--
2
+ # Copyright 2008, 2009 Jean-Michel Esnault.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #
6
+ #
7
+ # This file is part of BGP4R.
8
+ #
9
+ # BGP4R is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # BGP4R is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with BGP4R. If not, see <http://www.gnu.org/licenses/>.
21
+ #++
22
+
23
+
24
+ require 'bgp/attribute'
25
+
26
+ module BGP
27
+
28
+ class Origin < Attr
29
+
30
+ def initialize(arg=0)
31
+ @type=ORIGIN
32
+ @flags=WELL_KNOWN_MANDATORY
33
+ if arg.is_a?(String) and arg.packed?
34
+ parse(arg)
35
+ elsif arg.is_a?(self.class)
36
+ parse(arg.encode)
37
+ elsif arg.is_a?(Hash) and arg[:origin]
38
+ @origin = arg[:origin]
39
+ elsif arg.is_a?(Fixnum) and (0..2)===arg
40
+ @origin=arg
41
+ elsif arg.is_a?(Symbol)
42
+ case arg
43
+ when :igp
44
+ @origin=0
45
+ when :egp
46
+ @origin=1
47
+ when :incomplete
48
+ @origin=2
49
+ end
50
+ else
51
+ raise ArgumentError, "invalid argument, #{arg.class} (#{arg})"
52
+ end
53
+ end
54
+
55
+ def encode
56
+ super([@origin].pack('C'))
57
+ end
58
+
59
+ def to_i
60
+ @origin
61
+ end
62
+
63
+ def origin
64
+ case to_i
65
+ when 0 ; 'igp'
66
+ when 1 ; 'egp'
67
+ when 2 ; 'incomplete'
68
+ else
69
+ 'bogus'
70
+ end
71
+ end
72
+
73
+ def to_s(method=:default)
74
+ super(origin, method)
75
+ end
76
+
77
+ private
78
+
79
+ def parse(s)
80
+ @flags, @type, len, @origin=super(s, 'C')
81
+ end
82
+
83
+ end
84
+
85
+ end
86
+
87
+ load "../test/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
88
+
@@ -0,0 +1,73 @@
1
+ #--
2
+ # Copyright 2008, 2009 Jean-Michel Esnault.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #
6
+ #
7
+ # This file is part of BGP4R.
8
+ #
9
+ # BGP4R is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # BGP4R is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with BGP4R. If not, see <http://www.gnu.org/licenses/>.
21
+ #++
22
+
23
+
24
+ require 'bgp/attribute'
25
+
26
+ module BGP
27
+
28
+ module ATTR
29
+ end
30
+
31
+ class Originator_id < Attr
32
+
33
+ def initialize(*args)
34
+ @flags, @type = OPTIONAL, ORIGINATOR_ID
35
+ if args[0].is_a?(String) and args[0].is_packed?
36
+ parse(args[0])
37
+ elsif args[0].is_a?(self.class)
38
+ parse(args[0].encode, *args[1..-1])
39
+ else
40
+ self.originator_id=args[0]
41
+ end
42
+ end
43
+
44
+ def to_i
45
+ @next_hop.to_i
46
+ end
47
+ def parse(s)
48
+ @flags, @type, len, value = super(s)
49
+ @next_hop = IPAddr.create(value)
50
+ end
51
+
52
+ def encode
53
+ super(@next_hop.encode)
54
+ end
55
+
56
+ def to_s(method=:default)
57
+ super(@next_hop.to_s, method)
58
+ end
59
+
60
+ def originator_id
61
+ @next_hop.to_s
62
+ end
63
+
64
+ def originator_id=(val)
65
+ @next_hop=IPAddr.create(val)
66
+ end
67
+
68
+
69
+ end
70
+
71
+ end
72
+
73
+ load "../test/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0