jesnault-bgp4r 0.0.2 → 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.
- data/bgp/aggregator.rb +104 -0
- data/bgp/as_path.rb +223 -0
- data/bgp/atomic_aggregate.rb +42 -0
- data/bgp/attribute.rb +181 -0
- data/bgp/attributes.rb +34 -0
- data/bgp/cluster_list.rb +117 -0
- data/bgp/common.rb +204 -0
- data/bgp/communities.rb +139 -0
- data/bgp/extended_communities.rb +107 -0
- data/bgp/extended_community.rb +254 -0
- data/bgp/iana.rb +269 -0
- data/bgp/io.rb +116 -0
- data/bgp/label.rb +94 -0
- data/bgp/local_pref.rb +75 -0
- data/bgp/message.rb +894 -0
- data/bgp/mp_reach.rb +208 -0
- data/bgp/multi_exit_disc.rb +76 -0
- data/bgp/neighbor.rb +291 -0
- data/bgp/next_hop.rb +63 -0
- data/bgp/nlri.rb +303 -0
- data/bgp/orf.rb +88 -0
- data/bgp/origin.rb +88 -0
- data/bgp/originator_id.rb +73 -0
- data/bgp/path_attribute.rb +210 -0
- data/bgp/prefix_orf.rb +263 -0
- data/bgp/rd.rb +107 -0
- data/examples/bgp +65 -0
- data/examples/routegen +85 -0
- data/examples/routegen.yml +50 -0
- data/test/aggregator_test.rb +66 -0
- data/test/as_path_test.rb +149 -0
- data/test/atomic_aggregate_test.rb +35 -0
- data/test/attribute_test.rb +57 -0
- data/test/cluster_list_test.rb +39 -0
- data/test/common_test.rb +68 -0
- data/test/communities_test.rb +75 -0
- data/test/extended_communities_test.rb +111 -0
- data/test/extended_community_test.rb +93 -0
- data/test/label_test.rb +50 -0
- data/test/local_pref_test.rb +43 -0
- data/test/message_test.rb +294 -0
- data/test/mp_reach_test.rb +143 -0
- data/test/multi_exit_disc_test.rb +46 -0
- data/test/neighbor_test.rb +50 -0
- data/test/next_hop_test.rb +37 -0
- data/test/nlri_test.rb +189 -0
- data/test/origin_test.rb +57 -0
- data/test/originator_id_test.rb +38 -0
- data/test/path_attribute_test.rb +127 -0
- data/test/prefix_orf_test.rb +97 -0
- data/test/rd_test.rb +44 -0
- metadata +84 -11
data/bgp/aggregator.rb
ADDED
@@ -0,0 +1,104 @@
|
|
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
|
+
require 'bgp/attribute'
|
24
|
+
|
25
|
+
module BGP
|
26
|
+
|
27
|
+
class Aggregator < Attr
|
28
|
+
|
29
|
+
def initialize(*args)
|
30
|
+
@flags, @type, @as4byte =OPTIONAL_TRANSITIVE, AGGREGATOR, false
|
31
|
+
if args[0].is_a?(String) and args[0].is_packed?
|
32
|
+
parse(*args)
|
33
|
+
elsif args.size==2 and
|
34
|
+
args[0].is_a?(String) and (args[1].is_a?(Fixnum) or args[1].is_a?(Bignum))
|
35
|
+
@ip_address = IPAddr.create(args[0])
|
36
|
+
@as = args[1]
|
37
|
+
elsif args[0].is_a?(self.class)
|
38
|
+
parse(args[0].encode, *args[1..-1])
|
39
|
+
else
|
40
|
+
raise ArgumentError, "invalid argument, #{args.inspect}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def address=(val)
|
45
|
+
@ip_address=IPAddr.create(val)
|
46
|
+
end
|
47
|
+
|
48
|
+
def address
|
49
|
+
@ip_address.to_s
|
50
|
+
end
|
51
|
+
|
52
|
+
def as(sep='')
|
53
|
+
case sep
|
54
|
+
when '.'
|
55
|
+
has = @as >> 16
|
56
|
+
las = @as & 0xffff
|
57
|
+
[has,las].join('.')
|
58
|
+
else
|
59
|
+
@as
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def aggregator(as4byte=@as4byte)
|
64
|
+
"#{address}, #{as(as4byte ? '.':'')}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_s(method=:default)
|
68
|
+
super(aggregator, method)
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse(s,as4byte=false)
|
72
|
+
@flags, @type, len, @as, addr = super(s, as4byte ? 'NN' : 'nN')
|
73
|
+
self.address = addr
|
74
|
+
end
|
75
|
+
|
76
|
+
def encode(as4byte=@as4byte)
|
77
|
+
f = as4byte ? 'N' : 'n'
|
78
|
+
super([@as].pack(f) + @ip_address.hton)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
class As4_aggregator < Aggregator
|
84
|
+
def initialize(*args)
|
85
|
+
super(*args)
|
86
|
+
@flags, @type, @as4byte =OPTIONAL_TRANSITIVE, AS4_AGGREGATOR, true
|
87
|
+
end
|
88
|
+
def parse(s,as4byte=@as4byte)
|
89
|
+
super(s,true)
|
90
|
+
end
|
91
|
+
def encode(as4byte=@as4byte)
|
92
|
+
f = as4byte ? 'N' : 'n'
|
93
|
+
super([@as].pack(f) + @ip_address.hton)
|
94
|
+
end
|
95
|
+
|
96
|
+
def aggregator(as4byte=@as4byte)
|
97
|
+
super(true)
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
load "../test/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
data/bgp/as_path.rb
ADDED
@@ -0,0 +1,223 @@
|
|
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
|
+
require 'bgp/attribute'
|
24
|
+
|
25
|
+
module BGP
|
26
|
+
|
27
|
+
class As_path < Attr
|
28
|
+
|
29
|
+
##############################
|
30
|
+
|
31
|
+
class Segment
|
32
|
+
include ATTR
|
33
|
+
|
34
|
+
def self.factory(s, as4byte=false)
|
35
|
+
seg_type, num = s.slice(0,2).unpack('CC')
|
36
|
+
len = num * (as4byte ? 4 : 2)+2
|
37
|
+
segment = s.slice!(0, len).is_packed
|
38
|
+
case seg_type
|
39
|
+
when SET ; Set.new(segment, as4byte)
|
40
|
+
when SEQUENCE ; Sequence.new(segment, as4byte)
|
41
|
+
when CONFED_SEQUENCE ; Confed_sequence.new(segment, as4byte)
|
42
|
+
when CONFED_SET ; Confed_set.new(segment, as4byte)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
attr_reader :as
|
47
|
+
|
48
|
+
def initialize(seg_type, *args)
|
49
|
+
@as=[]
|
50
|
+
if seg_type.is_a?(String) and seg_type.is_packed?
|
51
|
+
parse(seg_type, *args)
|
52
|
+
elsif args.size>0 and args.is_a?(Array)
|
53
|
+
self.seg_type = seg_type
|
54
|
+
@as = args
|
55
|
+
else
|
56
|
+
raise ArgumentError, "invalid argument #{args.inspect}"
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
def seg_type
|
62
|
+
@seg_type
|
63
|
+
end
|
64
|
+
|
65
|
+
def seg_type=(val)
|
66
|
+
case val
|
67
|
+
when :set ; @seg_type = SET
|
68
|
+
when :sequence ; @seg_type = SEQUENCE
|
69
|
+
when :confed_sequence ; @seg_type = CONFED_SEQUENCE
|
70
|
+
when :confed_set ; @seg_type = CONFED_SET
|
71
|
+
else
|
72
|
+
raise ArgumentError, "invalid segment type #{val.class} #{val}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def encode(as4byte=false)
|
77
|
+
[@seg_type, @as.size, @as].flatten.pack("CC#{as4byte ? 'N' : 'n'}*")
|
78
|
+
end
|
79
|
+
|
80
|
+
def as4byte?
|
81
|
+
defined?(@as4byte) and @as4byte
|
82
|
+
end
|
83
|
+
|
84
|
+
def parse(s, as4byte=false)
|
85
|
+
@seg_type, skip, *@as = s.unpack("CC#{as4byte ? 'N' : 'n'}*")
|
86
|
+
@as = [@as].flatten
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_s
|
90
|
+
case @seg_type
|
91
|
+
when SET ; s = "{" ; join=", "
|
92
|
+
when SEQUENCE ; s = "" ; join= " "
|
93
|
+
when CONFED_SET ; s = "[" ; join= ", "
|
94
|
+
when CONFED_SEQUENCE ; s = "(" ; join= " "
|
95
|
+
else ; s = "?("
|
96
|
+
end
|
97
|
+
s += @as.join(join)
|
98
|
+
case @seg_type
|
99
|
+
when SET ; s += "}"
|
100
|
+
when CONFED_SET ; s += "]"
|
101
|
+
when CONFED_SEQUENCE ; s += ")"
|
102
|
+
when SEQUENCE
|
103
|
+
else ; s += ")"
|
104
|
+
end
|
105
|
+
s
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
class As_path::Set < As_path::Segment
|
111
|
+
def initialize(*args)
|
112
|
+
if args[0].is_a?(String)
|
113
|
+
super(*args)
|
114
|
+
else
|
115
|
+
super(:set, *args)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class As_path::Sequence < As_path::Segment
|
121
|
+
def initialize(*args)
|
122
|
+
if args[0].is_a?(String)
|
123
|
+
super(*args)
|
124
|
+
else
|
125
|
+
super(:sequence, *args)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
class As_path::Confed_set < As_path::Segment
|
131
|
+
def initialize(*args)
|
132
|
+
if args[0].is_a?(String)
|
133
|
+
super(*args)
|
134
|
+
else
|
135
|
+
super(:confed_set, *args)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class As_path::Confed_sequence < As_path::Segment
|
141
|
+
def initialize(*args)
|
142
|
+
if args[0].is_a?(String)
|
143
|
+
super(*args)
|
144
|
+
else
|
145
|
+
super(:confed_sequence, *args)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
##############################
|
151
|
+
|
152
|
+
def integer?(arg)
|
153
|
+
arg.is_a?(Fixnum) or arg.is_a?(Bignum)
|
154
|
+
end
|
155
|
+
|
156
|
+
attr_accessor :as4byte
|
157
|
+
|
158
|
+
def initialize(*args)
|
159
|
+
|
160
|
+
@flags, @type, @segments, @as4byte = WELL_KNOWN_MANDATORY, AS_PATH, [], false
|
161
|
+
|
162
|
+
if args[0].is_a?(String) and args[0].is_packed?
|
163
|
+
parse(*args)
|
164
|
+
elsif args[0].is_a?(self.class)
|
165
|
+
parse(args[0].encode, *args[1..-1])
|
166
|
+
elsif integer?(args[0])
|
167
|
+
@segments << Sequence.new(*args.dup)
|
168
|
+
elsif args[0].is_a?(Segment)
|
169
|
+
unless args.find { |seg| ! seg.is_a?(Segment) }.nil?
|
170
|
+
raise ArgumentError, "at least one arg is not a segment"
|
171
|
+
end
|
172
|
+
@segments = args.dup
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
def <<(val)
|
178
|
+
raise ArgumentError, "invalid argument, #{val.class} #{val}" unless val.is_a?(Segment)
|
179
|
+
@segments << val
|
180
|
+
end
|
181
|
+
|
182
|
+
def encode(as4byte=@as4byte)
|
183
|
+
super(@segments.collect { |segment| segment.encode(as4byte) }.join)
|
184
|
+
end
|
185
|
+
|
186
|
+
def encode4
|
187
|
+
encode(true)
|
188
|
+
end
|
189
|
+
|
190
|
+
def as_path
|
191
|
+
return 'empty' if @segments.empty?
|
192
|
+
@segments.collect { |seg| seg.to_s }.join(' ')
|
193
|
+
end
|
194
|
+
|
195
|
+
def to_s(method=:default, as4byte=false)
|
196
|
+
super(as_path, method, as4byte)
|
197
|
+
end
|
198
|
+
|
199
|
+
private
|
200
|
+
|
201
|
+
def parse(s,as4byte=false)
|
202
|
+
@flags, @type, len, value=super(s)
|
203
|
+
while value.size>0
|
204
|
+
@segments << Segment.factory(value.is_packed, as4byte)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
class As4_path < As_path
|
211
|
+
def initialize(*args)
|
212
|
+
super(*args)
|
213
|
+
@flags, @type, @as4byte =OPTIONAL_TRANSITIVE, AS4_PATH, true
|
214
|
+
end
|
215
|
+
def parse(s,as4byte=@as4byte)
|
216
|
+
super(s,true)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
load "../test/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
223
|
+
|
@@ -0,0 +1,42 @@
|
|
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 Atomic_aggregate < Attr
|
29
|
+
def initialize(arg=nil)
|
30
|
+
@flags, @type=OPTIONAL, ATOMIC_AGGREGATE
|
31
|
+
if arg.is_a?(String) and arg.is_packed?
|
32
|
+
parse(arg)
|
33
|
+
elsif arg.nil?
|
34
|
+
else
|
35
|
+
raise ArgumentError, "invalid argument, #{arg.class} #{arg}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
load "../test/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
data/bgp/attribute.rb
ADDED
@@ -0,0 +1,181 @@
|
|
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
|
+
require 'bgp/common'
|
24
|
+
|
25
|
+
module BGP
|
26
|
+
|
27
|
+
module ATTR
|
28
|
+
|
29
|
+
### http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#bgp-parameters-2
|
30
|
+
|
31
|
+
ORIGIN = 1
|
32
|
+
AS_PATH = 2
|
33
|
+
NEXT_HOP = 3
|
34
|
+
MULTI_EXIT_DISC = 4
|
35
|
+
LOCAL_PREF = 5
|
36
|
+
ATOMIC_AGGREGATE = 6
|
37
|
+
AGGREGATOR = 7
|
38
|
+
COMMUNITIES = 8
|
39
|
+
ORIGINATOR_ID = 9
|
40
|
+
CLUSTER_LIST = 10
|
41
|
+
|
42
|
+
MP_REACH = 14
|
43
|
+
MP_UNREACH = 15
|
44
|
+
EXTENDED_COMMUNITY = 16
|
45
|
+
AS4_PATH = 17
|
46
|
+
AS4_AGGREGATOR = 18
|
47
|
+
|
48
|
+
SET = 1
|
49
|
+
SEQUENCE = 2
|
50
|
+
CONFED_SEQUENCE = 3
|
51
|
+
CONFED_SET = 4
|
52
|
+
|
53
|
+
OPTIONAL = 0x8
|
54
|
+
TRANSITIVE = 0x4
|
55
|
+
PARTIAL = 0x2
|
56
|
+
EXTENDED_LENGTH = 0x1
|
57
|
+
NONE = 0x0
|
58
|
+
|
59
|
+
WELL_KNOWN_MANDATORY = TRANSITIVE
|
60
|
+
WELL_KNOWN_DISCRETIONARY = TRANSITIVE
|
61
|
+
OPTIONAL_TRANSITIVE = OPTIONAL | TRANSITIVE
|
62
|
+
OPTIONAL_NON_TRANSITIVE = OPTIONAL
|
63
|
+
|
64
|
+
def encode(value='',value_fmt=nil)
|
65
|
+
len, len_fmt = value.size, 'C'
|
66
|
+
if len>255
|
67
|
+
@flags |= EXTENDED_LENGTH
|
68
|
+
len_fmt='n'
|
69
|
+
end
|
70
|
+
if value_fmt
|
71
|
+
[@flags<<4, @type, len, *value].pack("CC#{len_fmt}#{value_fmt}")
|
72
|
+
else
|
73
|
+
([@flags<<4, @type, len].pack("CC#{len_fmt}") + value).is_packed
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def parse(*args)
|
78
|
+
_parse_(*args)
|
79
|
+
end
|
80
|
+
|
81
|
+
def _parse_(s,vf=nil)
|
82
|
+
value, arr = '', []
|
83
|
+
flags = s.unpack('C')[0]
|
84
|
+
if flags & 0x10>0
|
85
|
+
arr = s.unpack("CCn")
|
86
|
+
len = arr[2]
|
87
|
+
if vf
|
88
|
+
value = s[4..-1].unpack(vf)
|
89
|
+
else
|
90
|
+
value = s[4..-1].unpack("a#{len}")
|
91
|
+
end
|
92
|
+
s.slice!(0,arr[2]+4).is_packed
|
93
|
+
else
|
94
|
+
arr = s.unpack("CCC")
|
95
|
+
len = arr[2]
|
96
|
+
if vf
|
97
|
+
value = s[3..-1].unpack(vf)
|
98
|
+
else
|
99
|
+
value = s[3..-1].unpack("a#{len}")
|
100
|
+
end
|
101
|
+
s.slice!(0,arr[2]+3).is_packed
|
102
|
+
end
|
103
|
+
arr[0]= arr[0] >>4
|
104
|
+
value[0].is_packed unless vf
|
105
|
+
arr + value
|
106
|
+
end
|
107
|
+
|
108
|
+
def name
|
109
|
+
self.class.to_s.split('::').last
|
110
|
+
end
|
111
|
+
|
112
|
+
def flags
|
113
|
+
flags = @flags
|
114
|
+
s ="["
|
115
|
+
(flags&8>0) ? s +="O" : s += "w"
|
116
|
+
(flags&4>0) ? s +="T" : s += "n"
|
117
|
+
(flags&2>0) ? s +="P" : s += "c"
|
118
|
+
(flags&1>0) ? s +="E" : s += "r"
|
119
|
+
s +="]"
|
120
|
+
end
|
121
|
+
|
122
|
+
def flags_short
|
123
|
+
flags = @flags
|
124
|
+
s ="["
|
125
|
+
s +="O" if (flags&8>0)
|
126
|
+
s +="T" if (flags&4>0)
|
127
|
+
s +="P" if (flags&2>0)
|
128
|
+
s +="E" if (flags&1>0)
|
129
|
+
s +="]"
|
130
|
+
end
|
131
|
+
|
132
|
+
def attribute_name
|
133
|
+
name.split('_').collect { |w| w.capitalize }.join(' ')
|
134
|
+
end
|
135
|
+
|
136
|
+
def to_s(value='', mode=:tcpdump, as4byte=false)
|
137
|
+
|
138
|
+
shex = as4byte ? to_shex4_len(20) : to_shex_len(20)
|
139
|
+
|
140
|
+
mode = :brief unless [:tcpdump, :brief, :hexlify].include?(mode)
|
141
|
+
|
142
|
+
case mode
|
143
|
+
when :brief
|
144
|
+
sprintf "%s %4s %10s: [%s]%s", flags, "(#{@type})", attribute_name, shex, "#{value.size>0 ? " '#{value}'" :''}"
|
145
|
+
when :hexlify
|
146
|
+
s = sprintf "%s %4s %10s: [%s]%s", flags, "(#{@type})", attribute_name, shex, "#{value.size>0 ? " '#{value}" :''}"
|
147
|
+
s +="\n\n"
|
148
|
+
if as4byte
|
149
|
+
s += self.encode4.hexlify.join("\n")
|
150
|
+
else
|
151
|
+
s += self.encode.hexlify.join("\n")
|
152
|
+
end
|
153
|
+
when :tcpdump
|
154
|
+
if as4byte
|
155
|
+
f, t, len, enc_value = _parse_(self.encode4, nil)
|
156
|
+
else
|
157
|
+
f, t, len, enc_value = _parse_(self.encode, nil)
|
158
|
+
end
|
159
|
+
s = sprintf "%s (%d), length: %d, Flags %s: %s", attribute_name, @type, len, flags_short, value
|
160
|
+
s += enc_value.hexlify.join(("\n "))
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
class Attr
|
167
|
+
|
168
|
+
include ATTR
|
169
|
+
include Comparable
|
170
|
+
|
171
|
+
def method_missing(name, *args, &block)
|
172
|
+
if name == :encode4
|
173
|
+
send :encode, *args, &block
|
174
|
+
else
|
175
|
+
super
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
data/bgp/attributes.rb
ADDED
@@ -0,0 +1,34 @@
|
|
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
|
+
require 'bgp/origin'
|
24
|
+
require 'bgp/next_hop'
|
25
|
+
require 'bgp/local_pref'
|
26
|
+
require 'bgp/multi_exit_disc'
|
27
|
+
require 'bgp/as_path'
|
28
|
+
require 'bgp/communities'
|
29
|
+
require 'bgp/aggregator'
|
30
|
+
require 'bgp/atomic_aggregate'
|
31
|
+
require 'bgp/originator_id'
|
32
|
+
require 'bgp/cluster_list'
|
33
|
+
require 'bgp/mp_reach'
|
34
|
+
require 'bgp/extended_communities'
|
data/bgp/cluster_list.rb
ADDED
@@ -0,0 +1,117 @@
|
|
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 Cluster_list < Attr
|
29
|
+
|
30
|
+
##########################################################
|
31
|
+
# CLUSTER ID #
|
32
|
+
##########################################################
|
33
|
+
class Id
|
34
|
+
def initialize(id)
|
35
|
+
@id = IPAddr.create(id)
|
36
|
+
end
|
37
|
+
def to_s
|
38
|
+
@id.to_s
|
39
|
+
end
|
40
|
+
def to_i
|
41
|
+
@id.to_i
|
42
|
+
end
|
43
|
+
def encode
|
44
|
+
@id.hton
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
##########################################################
|
49
|
+
# CLUSTER_LIST ATTRIBUTE #
|
50
|
+
##########################################################
|
51
|
+
|
52
|
+
def initialize(*args)
|
53
|
+
@flags, @type = OPTIONAL, CLUSTER_LIST
|
54
|
+
if args[0].is_a?(String) and args[0].is_packed?
|
55
|
+
parse(args[0])
|
56
|
+
elsif args[0].is_a?(self.class)
|
57
|
+
parse(args[0].encode, *args[1..-1])
|
58
|
+
else
|
59
|
+
add(*args)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def add(*args)
|
64
|
+
@cluster_ids ||=[]
|
65
|
+
args.flatten.each do |arg|
|
66
|
+
if arg.is_a?(String) and arg.split(' ').size>1
|
67
|
+
arg.split.each { |v| @cluster_ids << Id.new(v) }
|
68
|
+
elsif arg.is_a?(String) and arg.split(',').size>1
|
69
|
+
arg.split(',').each { |v| @cluster_ids << Id.new(v) }
|
70
|
+
elsif arg.is_a?(Id)
|
71
|
+
@cluster_ids << arg
|
72
|
+
else
|
73
|
+
@cluster_ids << Id.new(arg)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
alias << add
|
78
|
+
|
79
|
+
def cluster_list
|
80
|
+
@cluster_ids.collect { |comm| comm.to_s }.join(' ')
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_s(method=:default)
|
84
|
+
super(cluster_list, method)
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_ary
|
88
|
+
@cluster_ids.collect { |c| c.to_i }
|
89
|
+
end
|
90
|
+
|
91
|
+
def encode
|
92
|
+
super(@cluster_ids.collect { |comm| comm.encode }.join)
|
93
|
+
end
|
94
|
+
|
95
|
+
def parse(s)
|
96
|
+
@flags, @type, len, value=super(s)
|
97
|
+
self << value.unpack("N#{len/4}")
|
98
|
+
end
|
99
|
+
|
100
|
+
def sort
|
101
|
+
Cluster_list.new(to_ary.sort)
|
102
|
+
end
|
103
|
+
|
104
|
+
def sort!
|
105
|
+
@cluster_ids = @cluster_ids.sort_by { |c| c.to_i }
|
106
|
+
self
|
107
|
+
end
|
108
|
+
|
109
|
+
def <=>(other)
|
110
|
+
self.sort.to_shex <=> other.sort.to_shex
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
load "../test/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|