ospfv2 0.0.1
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/bin/ospfv2 +136 -0
- data/lib/ie/au_type.rb +79 -0
- data/lib/ie/external_route.rb +181 -0
- data/lib/ie/id.rb +97 -0
- data/lib/ie/interface_mtu.rb +64 -0
- data/lib/ie/ls_age.rb +89 -0
- data/lib/ie/ls_type.rb +148 -0
- data/lib/ie/metric.rb +63 -0
- data/lib/ie/mt_metric.rb +119 -0
- data/lib/ie/options.rb +356 -0
- data/lib/ie/ospf_version.rb +67 -0
- data/lib/ie/packet_type.rb +65 -0
- data/lib/ie/router_link.rb +167 -0
- data/lib/ie/router_link_factory.rb +53 -0
- data/lib/ie/router_link_type.rb +86 -0
- data/lib/ie/sequence_number.rb +144 -0
- data/lib/ie/tos_metric.rb +102 -0
- data/lib/infra/ospf_common.rb +291 -0
- data/lib/infra/ospf_constants.rb +73 -0
- data/lib/infra/ospf_io.rb +133 -0
- data/lib/infra/ospf_socket.rb +126 -0
- data/lib/infra/parse_options.rb +135 -0
- data/lib/infra/timer.rb +104 -0
- data/lib/infra/to_s.rb +38 -0
- data/lib/ls_db/advertised_routers.rb +78 -0
- data/lib/ls_db/common.rb +31 -0
- data/lib/ls_db/link_state_database.rb +376 -0
- data/lib/ls_db/link_state_database_build.rb +181 -0
- data/lib/ls_db/link_state_database_links.rb +178 -0
- data/lib/ls_db/links.rb +160 -0
- data/lib/lsa/external.rb +347 -0
- data/lib/lsa/lsa.rb +438 -0
- data/lib/lsa/lsa_factory.rb +59 -0
- data/lib/lsa/network.rb +166 -0
- data/lib/lsa/router.rb +336 -0
- data/lib/lsa/summary.rb +393 -0
- data/lib/neighbor/neighbor.rb +298 -0
- data/lib/neighbor/neighbor_event_handler.rb +61 -0
- data/lib/neighbor/recv_database_description.rb +153 -0
- data/lib/neighbor/recv_hello.rb +53 -0
- data/lib/neighbor/recv_ospf_packet.rb +68 -0
- data/lib/neighbor_sm/attempt_state.rb +44 -0
- data/lib/neighbor_sm/down_state.rb +46 -0
- data/lib/neighbor_sm/exchange_state.rb +32 -0
- data/lib/neighbor_sm/exstart_state.rb +69 -0
- data/lib/neighbor_sm/full_state.rb +36 -0
- data/lib/neighbor_sm/init_state.rb +43 -0
- data/lib/neighbor_sm/loading_state.rb +33 -0
- data/lib/neighbor_sm/neighbor_state.rb +87 -0
- data/lib/packet/database_description.rb +300 -0
- data/lib/packet/hello.rb +327 -0
- data/lib/packet/link_state_ack.rb +144 -0
- data/lib/packet/link_state_request.rb +153 -0
- data/lib/packet/link_state_update.rb +189 -0
- data/lib/packet/ospf_packet.rb +306 -0
- metadata +116 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2010 Jean-Michel Esnault.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#
|
6
|
+
#
|
7
|
+
# This file is part of OSPFv2.
|
8
|
+
#
|
9
|
+
# OSPFv2 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
|
+
# OSPFv2 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 OSPFv2. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
#++
|
22
|
+
|
23
|
+
|
24
|
+
module OSPFv2
|
25
|
+
module NeighborState
|
26
|
+
class State
|
27
|
+
|
28
|
+
def change_state(neighbor, *args)
|
29
|
+
neighbor.change_state(*args)
|
30
|
+
end
|
31
|
+
alias :new_state :change_state
|
32
|
+
|
33
|
+
def kill_nbr(neighbor)
|
34
|
+
new_state neighbor, Down.new, 'll_down or kill_nbr'
|
35
|
+
end
|
36
|
+
alias :ll_down :kill_nbr
|
37
|
+
|
38
|
+
def inactivity_timer(neighbor)
|
39
|
+
|
40
|
+
neighbor.instance_eval {
|
41
|
+
@ls_db.reset if @ls_db
|
42
|
+
@ls_req_list={}
|
43
|
+
@periodic_refresh.cancel
|
44
|
+
@periodic_rxmt.cancel
|
45
|
+
}
|
46
|
+
|
47
|
+
new_state neighbor, Down.new, 'Inactivity Timer'
|
48
|
+
end
|
49
|
+
|
50
|
+
def recv_hello(neighbor, rcv_hello, *args)
|
51
|
+
neighbor.instance_eval {
|
52
|
+
hello.add_router_id rcv_hello
|
53
|
+
hello.designated_router_id = rcv_hello.designated_router_id.to_ip
|
54
|
+
inactivity_timer.start { new_state Down.new, 'Inactivity Timer' }
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def adj_ok?
|
59
|
+
end
|
60
|
+
def seq_number_mismatch(neighbor)
|
61
|
+
end
|
62
|
+
def bad_ls_req(neighbor)
|
63
|
+
end
|
64
|
+
def one_way_received(neighbor)
|
65
|
+
end
|
66
|
+
def two_way_received(neighbor)
|
67
|
+
end
|
68
|
+
|
69
|
+
def method_missing(method, *args, &block)
|
70
|
+
if method.to_s =~ /^recv_(.+)$/
|
71
|
+
args[0].__send__ debug, "*** ignoring packet #{$1} : received while in #{self} ***"
|
72
|
+
else
|
73
|
+
raise
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
require 'neighbor_sm/down_state'
|
82
|
+
require 'neighbor_sm/attempt_state'
|
83
|
+
require 'neighbor_sm/init_state'
|
84
|
+
require 'neighbor_sm/exstart_state'
|
85
|
+
require 'neighbor_sm/exchange_state'
|
86
|
+
require 'neighbor_sm/loading_state'
|
87
|
+
require 'neighbor_sm/full_state'
|
@@ -0,0 +1,300 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2010 Jean-Michel Esnault.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#
|
6
|
+
#
|
7
|
+
# This file is part of OSPFv2.
|
8
|
+
#
|
9
|
+
# OSPFv2 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
|
+
# OSPFv2 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 OSPFv2. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
#++
|
22
|
+
|
23
|
+
|
24
|
+
=begin rdoc
|
25
|
+
A.3.3 The Database Description packet
|
26
|
+
|
27
|
+
Database Description packets are OSPF packet type 2. These packets
|
28
|
+
are exchanged when an adjacency is being initialized. They describe
|
29
|
+
the contents of the link-state database. Multiple packets may be
|
30
|
+
used to describe the database. For this purpose a poll-response
|
31
|
+
procedure is used. One of the routers is designated to be the
|
32
|
+
master, the other the slave. The master sends Database Description
|
33
|
+
packets (polls) which are acknowledged by Database Description
|
34
|
+
packets sent by the slave (responses). The responses are linked to
|
35
|
+
the polls via the packets' DD sequence numbers.
|
36
|
+
|
37
|
+
0 1 2 3
|
38
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
39
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
40
|
+
| Version # | 2 | Packet length |
|
41
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
42
|
+
| Router ID |
|
43
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
44
|
+
| Area ID |
|
45
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
46
|
+
| Checksum | AuType |
|
47
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
48
|
+
| Authentication |
|
49
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
50
|
+
| Authentication |
|
51
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
52
|
+
| Interface MTU | Options |0|0|0|0|0|I|M|MS
|
53
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
54
|
+
| DD sequence number |
|
55
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
56
|
+
| |
|
57
|
+
+- -+
|
58
|
+
| |
|
59
|
+
+- An LSA Header -+
|
60
|
+
| |
|
61
|
+
+- -+
|
62
|
+
| |
|
63
|
+
+- -+
|
64
|
+
| |
|
65
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
66
|
+
| ... |
|
67
|
+
|
68
|
+
|
69
|
+
The format of the Database Description packet is very similar to
|
70
|
+
both the Link State Request and Link State Acknowledgment packets.
|
71
|
+
The main part of all three is a list of items, each item describing
|
72
|
+
a piece of the link-state database. The sending of Database
|
73
|
+
Description Packets is documented in Section 10.8. The reception of
|
74
|
+
Database Description packets is documented in Section 10.6.
|
75
|
+
|
76
|
+
Interface MTU
|
77
|
+
The size in bytes of the largest IP datagram that can be sent
|
78
|
+
out the associated interface, without fragmentation. The MTUs
|
79
|
+
of common Internet link types can be found in Table 7-1 of
|
80
|
+
[Ref22]. Interface MTU should be set to 0 in Database
|
81
|
+
Description packets sent over virtual links.
|
82
|
+
|
83
|
+
Options
|
84
|
+
The optional capabilities supported by the router, as documented
|
85
|
+
in Section A.2.
|
86
|
+
|
87
|
+
I-bit
|
88
|
+
The Init bit. When set to 1, this packet is the first in the
|
89
|
+
sequence of Database Description Packets.
|
90
|
+
|
91
|
+
M-bit
|
92
|
+
The More bit. When set to 1, it indicates that more Database
|
93
|
+
Description Packets are to follow.
|
94
|
+
|
95
|
+
MS-bit
|
96
|
+
The Master/Slave bit. When set to 1, it indicates that the
|
97
|
+
router is the master during the Database Exchange process.
|
98
|
+
Otherwise, the router is the slave.
|
99
|
+
|
100
|
+
DD sequence number
|
101
|
+
Used to sequence the collection of Database Description Packets.
|
102
|
+
The initial value (indicated by the Init bit being set) should
|
103
|
+
be unique. The DD sequence number then increments until the
|
104
|
+
complete database description has been sent.
|
105
|
+
|
106
|
+
The rest of the packet consists of a (possibly partial) list of the
|
107
|
+
link-state database's pieces. Each LSA in the database is described
|
108
|
+
by its LSA header. The LSA header is documented in Section A.4.1.
|
109
|
+
It contains all the information required to uniquely identify both
|
110
|
+
the LSA and the LSA's current instance.
|
111
|
+
|
112
|
+
|
113
|
+
=end
|
114
|
+
|
115
|
+
require 'packet/ospf_packet'
|
116
|
+
require 'ie/interface_mtu'
|
117
|
+
require 'ie/options'
|
118
|
+
require 'lsa/lsa'
|
119
|
+
require 'ls_db/link_state_database'
|
120
|
+
|
121
|
+
module OSPFv2
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
class DatabaseDescription < OspfPacket
|
126
|
+
|
127
|
+
class << self
|
128
|
+
|
129
|
+
def seqn
|
130
|
+
@seqn ||= rand(0x4fff)
|
131
|
+
@seqn +=1
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
attr_reader :options, :ls_db, :interface_mtu, :dd_sequence_number
|
137
|
+
|
138
|
+
attr_checked :imms do |x|
|
139
|
+
(0..7) === x
|
140
|
+
end
|
141
|
+
attr_checked :dd_sequence_number do |x|
|
142
|
+
(0..0xffffffff) === x
|
143
|
+
end
|
144
|
+
alias :dd_seqn :dd_sequence_number
|
145
|
+
alias :dd_seqn= :dd_sequence_number=
|
146
|
+
|
147
|
+
def initialize(_arg={})
|
148
|
+
arg = _arg.dup
|
149
|
+
@interface_mtu = InterfaceMtu.new
|
150
|
+
@options = Options.new
|
151
|
+
@imms, @dd_sequence_number, @number_of_lsa=0, nil, nil
|
152
|
+
|
153
|
+
if arg.is_a?(Hash)
|
154
|
+
arg.merge!({:packet_type=>:dd})
|
155
|
+
super arg
|
156
|
+
elsif arg.is_a?(String)
|
157
|
+
parse arg
|
158
|
+
elsif arg.is_a?(DatabaseDescription)
|
159
|
+
parse arg.encode
|
160
|
+
else
|
161
|
+
raise ArgumentError, "Invalid argument", caller
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
def to_s
|
167
|
+
s = []
|
168
|
+
s << super(:brief)
|
169
|
+
s << "MTU #{interface_mtu.to_i}, Options 0x#{options.to_i.to_s(16)}, #{imms_to_s}, DD_SEQ: 0x#{dd_sequence_number_to_shex}"
|
170
|
+
s << "Age Options Type Link-State ID Advr Router Sequence Checksum Length" if @lsas
|
171
|
+
s <<((@lsas.collect { |x| x.to_s_dd })).join("\n ") if @lsas
|
172
|
+
s.join("\n ")
|
173
|
+
end
|
174
|
+
|
175
|
+
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
176
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
177
|
+
# | Version # | 2 | Packet length |
|
178
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
179
|
+
# | Router ID |
|
180
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
181
|
+
# | Area ID |
|
182
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
183
|
+
# | Checksum | AuType |
|
184
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
185
|
+
# | Authentication |
|
186
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
187
|
+
# | Authentication |
|
188
|
+
|
189
|
+
|
190
|
+
|
191
|
+
|
192
|
+
# 16:57 (exstart) snd DatabaseDescription:
|
193
|
+
# Version 2, RouterId 0.0.0.1, AreaId 0.0.0.0, AuType 0, Checksum 0x9580, len 9999
|
194
|
+
# MTU 1500, Options 0x0, I|M|MS: 0 [000], DD_SEQ: d022675
|
195
|
+
# 123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.
|
196
|
+
# Age Options Type Link-State ID Advr Router Sequence Checksum Length
|
197
|
+
# 41 0x22 router 128.1.0.2 128.1.0.2 0x80000001 0x9580 36
|
198
|
+
# 41 0x00 external 50.0.1.0 128.1.0.1 0x80000001 0x115a 48
|
199
|
+
# 42 0x22 router 128.1.0.1 128.1.0.1 0x80000001 0xa86e 36
|
200
|
+
# 41 0x00 summary 30.0.1.0 128.1.0.1 0x80000001 0x6459 28
|
201
|
+
|
202
|
+
|
203
|
+
def to_s_short
|
204
|
+
"I|M|MS: [#{[imms].pack('C').unpack('B8')[0][5..7]}] SEQN: #{dd_sequence_number}"
|
205
|
+
end
|
206
|
+
def encode
|
207
|
+
packet =[]
|
208
|
+
packet << @interface_mtu.encode
|
209
|
+
packet << [options.to_i, imms, dd_sequence_number].pack('CCN')
|
210
|
+
packet << @lsas.collect { |x| x.encode.slice(0,20) }.join if @lsas
|
211
|
+
super packet.join
|
212
|
+
end
|
213
|
+
|
214
|
+
def options=(val)
|
215
|
+
@options = Options.new(val)
|
216
|
+
end
|
217
|
+
|
218
|
+
def more
|
219
|
+
@imms |= 2
|
220
|
+
end
|
221
|
+
|
222
|
+
def no_more
|
223
|
+
@imms &= ~2
|
224
|
+
end
|
225
|
+
|
226
|
+
def master
|
227
|
+
@imms |= 1
|
228
|
+
end
|
229
|
+
alias :is_master :master
|
230
|
+
|
231
|
+
def init
|
232
|
+
@imms |= 4
|
233
|
+
end
|
234
|
+
alias :in_init :init
|
235
|
+
|
236
|
+
def more?
|
237
|
+
imms & 2 == 2
|
238
|
+
end
|
239
|
+
|
240
|
+
def master?
|
241
|
+
imms & 1 == 1
|
242
|
+
end
|
243
|
+
|
244
|
+
def init?
|
245
|
+
imms & 4 == 4
|
246
|
+
end
|
247
|
+
|
248
|
+
alias :seqn :dd_sequence_number
|
249
|
+
alias :seqn= :dd_sequence_number=
|
250
|
+
|
251
|
+
def each
|
252
|
+
@lsas.each do |lsa|
|
253
|
+
yield lsa
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
private
|
258
|
+
|
259
|
+
def imms_to_s
|
260
|
+
"I|M|MS: #{imms} [#{[imms].pack('C').unpack('B8')[0][5..7]}]"
|
261
|
+
end
|
262
|
+
|
263
|
+
def dd_sequence_number_to_s
|
264
|
+
"DD sequence number: #{dd_sequence_number_to_shex}"
|
265
|
+
end
|
266
|
+
|
267
|
+
def dd_sequence_number_to_shex
|
268
|
+
dd_sequence_number.to_s(16)
|
269
|
+
end
|
270
|
+
|
271
|
+
def parse(s)
|
272
|
+
interface_mtu, options, @imms, @dd_sequence_number, headers = super(s).unpack('nCCNa*')
|
273
|
+
self.options = Options.new options
|
274
|
+
@interface_mtu = InterfaceMtu.new interface_mtu
|
275
|
+
@lsas ||=[]
|
276
|
+
while headers.size>0
|
277
|
+
lsa = Lsa.new headers.slice!(0,20)
|
278
|
+
@lsas <<lsa
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def number_of_lsa
|
283
|
+
#FIXME: rename interface mtu method...
|
284
|
+
@number_of_lsa ||=interface_mtu.n0flsa
|
285
|
+
end
|
286
|
+
|
287
|
+
def set(arg)
|
288
|
+
super
|
289
|
+
if arg[:ls_db].is_a?(OSPFv2::LSDB::LinkStateDatabase)
|
290
|
+
ls_db = arg[:ls_db]
|
291
|
+
@lsas = ls_db.lsas[ls_db.offset, number_of_lsa] ||=[]
|
292
|
+
ls_db.offset += number_of_lsa
|
293
|
+
self.more if ls_db.size > ls_db.offset
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
load "../../../test/ospfv2/packet/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|