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.
- data/COPYING +674 -0
- data/LICENSE.txt +53 -0
- data/README.rdoc +259 -0
- 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 +133 -0
data/LICENSE.txt
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
BGP4R is copyrighted free software by Jean-Michel Esnault.
|
2
|
+
|
3
|
+
You can redistribute it and/or modify it under either the terms of the GPL
|
4
|
+
(see the COPYING file), or the conditions below:
|
5
|
+
|
6
|
+
1. You may make and give away verbatim copies of the source form of the
|
7
|
+
software without restriction, provided that you duplicate all of the
|
8
|
+
original copyright notices and associated disclaimers.
|
9
|
+
|
10
|
+
2. You may modify your copy of the software in any way, provided that
|
11
|
+
you do at least ONE of the following:
|
12
|
+
|
13
|
+
a) place your modifications in the Public Domain or otherwise
|
14
|
+
make them Freely Available, such as by posting said
|
15
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
16
|
+
the author to include your modifications in the software.
|
17
|
+
|
18
|
+
b) use the modified software only within your corporation or
|
19
|
+
organization.
|
20
|
+
|
21
|
+
c) rename any non-standard executables so the names do not conflict
|
22
|
+
with standard executables, which must also be provided.
|
23
|
+
|
24
|
+
d) make other distribution arrangements with the author.
|
25
|
+
|
26
|
+
3. You may distribute the software in object code or executable
|
27
|
+
form, provided that you do at least ONE of the following:
|
28
|
+
|
29
|
+
a) distribute the executables and library files of the software,
|
30
|
+
together with instructions (in the manual page or equivalent)
|
31
|
+
on where to get the original distribution.
|
32
|
+
|
33
|
+
b) accompany the distribution with the machine-readable source of
|
34
|
+
the software.
|
35
|
+
|
36
|
+
c) give non-standard executables non-standard names, with
|
37
|
+
instructions on where to get the original software distribution.
|
38
|
+
|
39
|
+
d) make other distribution arrangements with the author.
|
40
|
+
|
41
|
+
4. You may modify and include the part of the software into any other
|
42
|
+
software (possibly commercial).
|
43
|
+
|
44
|
+
5. The scripts and library files supplied as input to or produced as
|
45
|
+
output from the software do not automatically fall under the
|
46
|
+
copyright of the software, but belong to whomever generated them,
|
47
|
+
and may be sold commercially, and may be aggregated with this
|
48
|
+
software.
|
49
|
+
|
50
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
51
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
52
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
53
|
+
PURPOSE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
= BGP4R
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
BGP4R is a ruby library which enables the creation and manipulation of BGP messages.
|
6
|
+
In BGP4R, all well-known BGP constructs are defined in classes.
|
7
|
+
|
8
|
+
Using BGP4R, the process of building BGP messages becomes a simple matter of adding objects
|
9
|
+
to their respective containers; i.e. an attribute is added to a Path_attribute container,
|
10
|
+
while a Path_attribute object or Nlri object is added to an Update object.
|
11
|
+
|
12
|
+
= A Neighbor class is used to describe a BGP peering adjacency.
|
13
|
+
|
14
|
+
|
15
|
+
==== A Neighbor instance can be started, stopped, and programmed to send BGP messages
|
16
|
+
|
17
|
+
Neighbor#start
|
18
|
+
Neighbor#stop
|
19
|
+
Neighbor#send_message
|
20
|
+
|
21
|
+
==== Neighbor capabilities such as MBGP or 4-byte AS can be set using Neighbor#capability
|
22
|
+
|
23
|
+
e.g.:
|
24
|
+
|
25
|
+
neighbor = Neighbor.new \
|
26
|
+
:version=> 4,
|
27
|
+
:my_as=> 100,
|
28
|
+
:remote_addr => '192.168.1.200',
|
29
|
+
:local_addr => '192.168.1.5',
|
30
|
+
:id=> '1.1.1.1',
|
31
|
+
:holdtime=> 20
|
32
|
+
|
33
|
+
neighbor.capability :as4_byte
|
34
|
+
neighbor.capability :route_refresh
|
35
|
+
neighbor.capability :route_refresh, 128
|
36
|
+
neighbor.capability :mbgp, :ipv4, :unicast
|
37
|
+
neighbor.capability :mbgp, :ipv4, :multicast
|
38
|
+
|
39
|
+
|
40
|
+
= Ruby classes representing BGP messages, attributes, and nlri
|
41
|
+
|
42
|
+
|
43
|
+
==== Messages:
|
44
|
+
|
45
|
+
Open
|
46
|
+
Update
|
47
|
+
Notification
|
48
|
+
Keepalive
|
49
|
+
Route_refresh
|
50
|
+
|
51
|
+
==== Attributes:
|
52
|
+
|
53
|
+
Origin
|
54
|
+
As_path
|
55
|
+
Next_hop
|
56
|
+
Local_pref
|
57
|
+
Multi_exit_disc
|
58
|
+
Communities
|
59
|
+
Atomic_aggregate
|
60
|
+
Aggregator
|
61
|
+
Originator_id
|
62
|
+
Cluster_list
|
63
|
+
Mp_reach
|
64
|
+
Mp_unreach
|
65
|
+
As4_path
|
66
|
+
As4_aggregator
|
67
|
+
Extended_communities
|
68
|
+
|
69
|
+
==== Update containers:
|
70
|
+
|
71
|
+
Nlri
|
72
|
+
Path_attribute
|
73
|
+
Withdrawn
|
74
|
+
|
75
|
+
= Getting started
|
76
|
+
|
77
|
+
=== Here is an example illustrating how to use this API:
|
78
|
+
|
79
|
+
require 'bgp4r'
|
80
|
+
include BGP
|
81
|
+
|
82
|
+
==== Start loggin
|
83
|
+
|
84
|
+
Log.create
|
85
|
+
Log.level=Logger::DEBUG
|
86
|
+
|
87
|
+
==== Create a Neighbor:
|
88
|
+
|
89
|
+
neighbor = Neighbor.new \
|
90
|
+
:version=> 4,
|
91
|
+
:my_as=> 100,
|
92
|
+
:remote_addr => '192.168.1.200',
|
93
|
+
:local_addr => '192.168.1.5',
|
94
|
+
:id=> '1.1.1.1', :holdtime=> 20
|
95
|
+
|
96
|
+
==== Set its capabilities:
|
97
|
+
|
98
|
+
neighbor.capability :as4_byte
|
99
|
+
neighbor.capability :route_refresh
|
100
|
+
neighbor.capability :route_refresh, 128
|
101
|
+
neighbor.capability :mbgp, :ipv4, :unicast
|
102
|
+
neighbor.capability :mbgp, :ipv4, :multicast
|
103
|
+
|
104
|
+
|
105
|
+
==== Start peering:
|
106
|
+
|
107
|
+
neighbor.start :auto_retry
|
108
|
+
|
109
|
+
==== Build an BGP Update object made up of a Path_attribute and a Nlri objects:
|
110
|
+
|
111
|
+
an_update = Update.new(
|
112
|
+
Path_attribute.new(
|
113
|
+
Origin.new(2),
|
114
|
+
Next_hop.new('192.168.1.5'),
|
115
|
+
Multi_exit_disc.new(100),
|
116
|
+
Local_pref.new(100),
|
117
|
+
As_path.new(400,300,200),
|
118
|
+
Communities.new('1311:1 311:59 2805:64')
|
119
|
+
),
|
120
|
+
Nlri.new('77.0.0.0/17', '78.0.0.0/18', '79.0.0.0/19')
|
121
|
+
)
|
122
|
+
|
123
|
+
==== Ship it!
|
124
|
+
|
125
|
+
neighbor.send_message an_update
|
126
|
+
|
127
|
+
|
128
|
+
=== Produces:
|
129
|
+
|
130
|
+
Jean-Michel-Esnaults-MacBook-Pro-17:bgp4r jme$ ruby bgp
|
131
|
+
I, [56:08#28463] INFO -- : Open Socket old state Idle new state Active
|
132
|
+
I, [56:08#28463] INFO -- : SendOpen
|
133
|
+
D, [56:08#28463] DEBUG -- : Send Open Message (1), length: 61
|
134
|
+
Version 4, my AS 100, Holdtime 20s, ID 1.1.1.1
|
135
|
+
Capability(65): 4-octet AS number: 100
|
136
|
+
Option Capabilities Advertisement (2): [02020200]
|
137
|
+
Route Refresh (2), length: 2
|
138
|
+
Option Capabilities Advertisement (2): [02028000]
|
139
|
+
Route Refresh (Cisco) (128), length: 2
|
140
|
+
Option Capabilities Advertisement (2): [0206010400010001]
|
141
|
+
Multiprotocol Extensions (1), length: 4
|
142
|
+
AFI IPv4 (1), SAFI Unicast (1)
|
143
|
+
Option Capabilities Advertisement (2): [0206010400010002]
|
144
|
+
Multiprotocol Extensions (1), length: 4
|
145
|
+
AFI IPv4 (1), SAFI Multicast (2)
|
146
|
+
|
147
|
+
0x0000: ffff ffff ffff ffff ffff ffff ffff ffff
|
148
|
+
0x0001: 003d 0104 0064 0014 0101 0101 2002 0641
|
149
|
+
0x0002: 0400 0000 6402 0202 0002 0280 0002 0601
|
150
|
+
0x0003: 0400 0100 0102 0601 0400 0100
|
151
|
+
|
152
|
+
|
153
|
+
D, [56:08#28463] DEBUG -- : #<BGP::IO::Input:0x40ab50> #<Thread:0x40a7b8> started
|
154
|
+
D, [56:08#28463] DEBUG -- : #<BGP::IO::Output:0x40ab14> #<Thread:0x40a754> started
|
155
|
+
I, [56:08#28463] INFO -- : ev_send_open old state Active new state OpenSent
|
156
|
+
I, [56:08#28463] INFO -- : RecvOpen
|
157
|
+
D, [56:08#28463] DEBUG -- : Recv Open Message (1), length: 61
|
158
|
+
Version 4, my AS 100, Holdtime 180s, ID 2.2.2.2
|
159
|
+
Option Capabilities Advertisement (2): [0206010400010001]
|
160
|
+
Multiprotocol Extensions (1), length: 4
|
161
|
+
AFI IPv4 (1), SAFI Unicast (1)
|
162
|
+
Option Capabilities Advertisement (2): [0206010400010002]
|
163
|
+
Multiprotocol Extensions (1), length: 4
|
164
|
+
AFI IPv4 (1), SAFI Multicast (2)
|
165
|
+
Option Capabilities Advertisement (2): [02028000]
|
166
|
+
Route Refresh (Cisco) (128), length: 2
|
167
|
+
Option Capabilities Advertisement (2): [02020200]
|
168
|
+
Route Refresh (2), length: 2
|
169
|
+
Capability(65): 4-octet AS number: 100
|
170
|
+
|
171
|
+
0x0000: ffff ffff ffff ffff ffff ffff ffff ffff
|
172
|
+
0x0001: 003d 0104 0064 00b4 0202 0202 2002 0601
|
173
|
+
0x0002: 0400 0100 0102 0601 0400 0100 0202 0280
|
174
|
+
0x0003: 0002 0202 0002 0641 0400 0000
|
175
|
+
|
176
|
+
|
177
|
+
I, [56:08#28463] INFO -- : RecvOpen old state OpenSent new state OpenConfirm
|
178
|
+
I, [56:08#28463] INFO -- : RecvKeepalive
|
179
|
+
D, [56:08#28463] DEBUG -- : Recv Keepalive Message (4), length: 19, [001304]
|
180
|
+
|
181
|
+
I, [56:08#28463] INFO -- : SendKeepalive
|
182
|
+
D, [56:08#28463] DEBUG -- : Send Keepalive Message (4), length: 19, [001304]
|
183
|
+
|
184
|
+
D, [56:08#28463] DEBUG -- : SendKeepAlive
|
185
|
+
I, [56:08#28463] INFO -- : RecvKeepAlive old state OpenConfirm new state Established
|
186
|
+
I, [56:08#28463] INFO -- : RecvKeepalive
|
187
|
+
D, [56:08#28463] DEBUG -- : Recv Keepalive Message (4), length: 19, [001304]
|
188
|
+
|
189
|
+
I, [56:08#28463] INFO -- : version: 4, id: 1.1.1.1, as: 100, holdtime: 20, peer addr: 192.168.1.200, local addr: 192.168.1.5 started
|
190
|
+
I, [56:08#28463] INFO -- : SendUpdate
|
191
|
+
D, [56:08#28463] DEBUG -- : Send Update Message (2), 4 bytes AS, length: 92
|
192
|
+
Path Attributes:
|
193
|
+
Origin (1), length: 1, Flags [T]: incomplete
|
194
|
+
0x0000:
|
195
|
+
Next Hop (3), length: 4, Flags [T]: 192.168.1.5
|
196
|
+
0x0000: c0a8 0105
|
197
|
+
Multi Exit Disc (4), length: 4, Flags [O]: (0x0064) 100
|
198
|
+
0x0000: 0000 0064
|
199
|
+
Local Pref (5), length: 4, Flags [T]: (0x0064) 100
|
200
|
+
0x0000: 0000 0064
|
201
|
+
As Path (2), length: 14, Flags [T]: 400 300 200
|
202
|
+
0x0000: 0203 0000 0190 0000 012c 0000 00c8
|
203
|
+
Communities (8), length: 12, Flags [OT]: 1311:1 311:59 2805:64
|
204
|
+
0x0000: 051f 0001 0137 003b 0af5 0040
|
205
|
+
77.0.0.0/17
|
206
|
+
78.0.0.0/18
|
207
|
+
79.0.0.0/19
|
208
|
+
|
209
|
+
0x0000: ffff ffff ffff ffff ffff ffff ffff ffff
|
210
|
+
0x0001: 005c 0200 0000 3940 0101 0240 0304 c0a8
|
211
|
+
0x0002: 0105 8004 0400 0000 6440 0504 0000 0064
|
212
|
+
0x0003: 4002 0e02 0300 0001 9000 0001 2c00 0000
|
213
|
+
0x0004: c8c0 080c 051f 0001 0137 003b 0af5 0040
|
214
|
+
0x0005: 114d 0000 124e 0000 134f 0000
|
215
|
+
|
216
|
+
|
217
|
+
I, [56:13#28463] INFO -- : RecvKeepalive
|
218
|
+
D, [56:13#28463] DEBUG -- : Recv Keepalive Message (4), length: 19, [001304]
|
219
|
+
|
220
|
+
I, [56:14#28463] INFO -- : SendKeepalive
|
221
|
+
D, [56:14#28463] DEBUG -- : Send Keepalive Message (4), length: 19, [001304]
|
222
|
+
|
223
|
+
|
224
|
+
== Source Code
|
225
|
+
|
226
|
+
Source code is hosted on github.
|
227
|
+
|
228
|
+
== Installation
|
229
|
+
|
230
|
+
==== Run the following if you haven't already:
|
231
|
+
|
232
|
+
gem sources -a http://gems.github.com
|
233
|
+
|
234
|
+
==== Install the gem
|
235
|
+
|
236
|
+
sudo gem install jesnault-bgp4r
|
237
|
+
|
238
|
+
=== Or clone bgp4r tree and set RUBYLIB env variable accordingly:
|
239
|
+
|
240
|
+
git clone git://github.com/jesnault/bgp4r.git
|
241
|
+
export RUBYLIB=/home/user/bgp4r
|
242
|
+
|
243
|
+
== Requirements
|
244
|
+
|
245
|
+
|
246
|
+
== License
|
247
|
+
|
248
|
+
BGP4R is free software: you can redistribute it and/or modify
|
249
|
+
it under the terms of the GNU General Public License as published by
|
250
|
+
the Free Software Foundation, either version 3 of the License, or
|
251
|
+
(at your option) any later version.
|
252
|
+
|
253
|
+
BGP4R is distributed in the hope that it will be useful,
|
254
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
255
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
256
|
+
GNU General Public License for more details.
|
257
|
+
|
258
|
+
You should have received a copy of the GNU General Public License
|
259
|
+
along with BGP4R. If not, see <http://www.gnu.org/licenses/>.
|
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
|