bgp4r 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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