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
data/lib/packet/hello.rb
ADDED
@@ -0,0 +1,327 @@
|
|
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
|
+
# A.3.2 The Hello packet
|
25
|
+
#
|
26
|
+
# Hello packets are OSPF packet type 1. These packets are sent
|
27
|
+
# periodically on all interfaces (including virtual links) in order to
|
28
|
+
# establish and maintain neighbor relationships. In addition, Hello
|
29
|
+
# Packets are multicast on those physical networks having a multicast
|
30
|
+
# or broadcast capability, enabling dynamic discovery of neighboring
|
31
|
+
# routers.
|
32
|
+
#
|
33
|
+
# All routers connected to a common network must agree on certain
|
34
|
+
# parameters (Network mask, HelloInterval and RouterDeadInterval).
|
35
|
+
# These parameters are included in Hello packets, so that differences
|
36
|
+
# can inhibit the forming of neighbor relationships. A detailed
|
37
|
+
# explanation of the receive processing for Hello packets is presented
|
38
|
+
# in Section 10.5. The sending of Hello packets is covered in Section
|
39
|
+
# 9.5.
|
40
|
+
#
|
41
|
+
# 0 1 2 3
|
42
|
+
# 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
|
43
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
44
|
+
# | Version # | 1 | Packet length |
|
45
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
46
|
+
# | Router ID |
|
47
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
48
|
+
# | Area ID |
|
49
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
50
|
+
# | Checksum | AuType |
|
51
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
52
|
+
# | Authentication |
|
53
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
54
|
+
# | Authentication |
|
55
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
56
|
+
# | Network Mask |
|
57
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
58
|
+
# | HelloInterval | Options | Rtr Pri |
|
59
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
60
|
+
# | RouterDeadInterval |
|
61
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
62
|
+
# | Designated Router |
|
63
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
64
|
+
# | Backup Designated Router |
|
65
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
66
|
+
# | Neighbor |
|
67
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
68
|
+
# | ... |
|
69
|
+
#
|
70
|
+
#
|
71
|
+
# Network mask
|
72
|
+
# The network mask associated with this interface. For example,
|
73
|
+
# if the interface is to a class B network whose third byte is
|
74
|
+
# used for subnetting, the network mask is 0xffffff00.
|
75
|
+
#
|
76
|
+
# Options
|
77
|
+
# The optional capabilities supported by the router, as documented
|
78
|
+
# in Section A.2.
|
79
|
+
#
|
80
|
+
# HelloInterval
|
81
|
+
# The number of seconds between this router's Hello packets.
|
82
|
+
#
|
83
|
+
# Rtr Pri
|
84
|
+
# This router's Router Priority. Used in (Backup) Designated
|
85
|
+
# Router election. If set to 0, the router will be ineligible to
|
86
|
+
# become (Backup) Designated Router.
|
87
|
+
#
|
88
|
+
# RouterDeadInterval
|
89
|
+
# The number of seconds before declaring a silent router down.
|
90
|
+
#
|
91
|
+
# Designated Router
|
92
|
+
# The identity of the Designated Router for this network, in the
|
93
|
+
# view of the sending router. The Designated Router is identified
|
94
|
+
# here by its IP interface address on the network. Set to 0.0.0.0
|
95
|
+
# if there is no Designated Router.
|
96
|
+
#
|
97
|
+
# Backup Designated Router
|
98
|
+
# The identity of the Backup Designated Router for this network,
|
99
|
+
# in the view of the sending router. The Backup Designated Router
|
100
|
+
# is identified here by its IP interface address on the network.
|
101
|
+
# Set to 0.0.0.0 if there is no Backup Designated Router.
|
102
|
+
#
|
103
|
+
# Neighbor
|
104
|
+
# The Router IDs of each router from whom valid Hello packets have
|
105
|
+
# been seen recently on the network. Recently means in the last
|
106
|
+
# RouterDeadInterval seconds.
|
107
|
+
#
|
108
|
+
#
|
109
|
+
# A.2 The Options field
|
110
|
+
#
|
111
|
+
# The 24-bit OSPF Options field is present in OSPF Hello packets,
|
112
|
+
# Database Description packets and certain LSAs (router-LSAs, network-
|
113
|
+
# LSAs, inter-area-router-LSAs and link-LSAs). The Options field
|
114
|
+
# enables OSPF routers to support (or not support) optional
|
115
|
+
# capabilities, and to communicate their capability level to other OSPF
|
116
|
+
# routers. Through this mechanism routers of differing capabilities
|
117
|
+
# can be mixed within an OSPF routing domain.
|
118
|
+
#
|
119
|
+
# An option mismatch between routers can cause a variety of behaviors,
|
120
|
+
# depending on the particular option. Some option mismatches prevent
|
121
|
+
# neighbor relationships from forming (e.g., the E-bit below); these
|
122
|
+
# mismatches are discovered through the sending and receiving of Hello
|
123
|
+
# packets. Some option mismatches prevent particular LSA types from
|
124
|
+
# being flooded across adjacencies (e.g., the MC-bit below); these are
|
125
|
+
# discovered through the sending and receiving of Database Description
|
126
|
+
# packets. Some option mismatches prevent routers from being included
|
127
|
+
# in one or more of the various routing calculations because of their
|
128
|
+
# reduced functionality (again the MC-bit is an example); these
|
129
|
+
# mismatches are discovered by examining LSAs.
|
130
|
+
#
|
131
|
+
# Six bits of the OSPF Options field have been assigned. Each bit is
|
132
|
+
# described briefly below. Routers should reset (i.e. clear)
|
133
|
+
# unrecognized bits in the Options field when sending Hello packets or
|
134
|
+
# Database Description packets and when originating LSAs. Conversely,
|
135
|
+
# routers encountering unrecognized Option bits in received Hello
|
136
|
+
# Packets, Database Description packets or LSAs should ignore the
|
137
|
+
# capability and process the packet/LSA normally.
|
138
|
+
#
|
139
|
+
#
|
140
|
+
# 1 2
|
141
|
+
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
|
142
|
+
# -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+--+--+--+--+--+
|
143
|
+
# | | | | | | | | | | | | | | | | | |DC| R| N|MC| E|V6|
|
144
|
+
# -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+--+--+--+--+--+
|
145
|
+
#
|
146
|
+
# The Options field
|
147
|
+
#
|
148
|
+
# V6-bit
|
149
|
+
# If this bit is clear, the router/link should be excluded from IPv6
|
150
|
+
# routing calculations. See Section 3.8 of this memo.
|
151
|
+
#
|
152
|
+
# E-bit
|
153
|
+
# This bit describes the way AS-external-LSAs are flooded, as
|
154
|
+
# described in Sections 3.6, 9.5, 10.8 and 12.1.2 of [Ref1].
|
155
|
+
#
|
156
|
+
# MC-bit
|
157
|
+
# This bit describes whether IP multicast datagrams are forwarded
|
158
|
+
# according to the specifications in [Ref7].
|
159
|
+
#
|
160
|
+
# N-bit
|
161
|
+
# This bit describes the handling of Type-7 LSAs, as specified in
|
162
|
+
# [Ref8].
|
163
|
+
#
|
164
|
+
# R-bit
|
165
|
+
# This bit (the `Router' bit) indicates whether the originator is an
|
166
|
+
# active router. If the router bit is clear routes which transit the
|
167
|
+
# advertising node cannot be computed. Clearing the router bit would
|
168
|
+
# be appropriate for a multi-homed host that wants to participate in
|
169
|
+
# routing, but does not want to forward non-locally addressed
|
170
|
+
# packets.
|
171
|
+
#
|
172
|
+
# DC-bit
|
173
|
+
# This bit describes the router's handling of demand circuits, as
|
174
|
+
# specified in [Ref10].
|
175
|
+
#
|
176
|
+
#
|
177
|
+
|
178
|
+
require 'packet/ospf_packet'
|
179
|
+
require 'ie/options'
|
180
|
+
require 'set'
|
181
|
+
|
182
|
+
module OSPFv2
|
183
|
+
|
184
|
+
class Hello < OspfPacket
|
185
|
+
|
186
|
+
DesignatedRouterId = Class.new(Id)
|
187
|
+
BackupDesignatedRouterId = Class.new(Id)
|
188
|
+
Netmask = Class.new(Id)
|
189
|
+
|
190
|
+
attr_reader :netmask, :designated_router_id, :backup_designated_router_id
|
191
|
+
attr_reader :hello_interval, :options, :rtr_pri, :router_dead_interval, :neighbors
|
192
|
+
attr_writer_delegate :designated_router_id, :backup_designated_router_id, :neighbors
|
193
|
+
|
194
|
+
class Neighbors
|
195
|
+
Neighbor = Class.new(OSPFv2::Id)
|
196
|
+
attr_reader :routers
|
197
|
+
def initialize(arg=nil)
|
198
|
+
@set = Set.new
|
199
|
+
[arg].compact.flatten.each { |x| self + x }
|
200
|
+
end
|
201
|
+
def +(id)
|
202
|
+
@set << neighbor(id)
|
203
|
+
end
|
204
|
+
def neighbors
|
205
|
+
@set.collect.sort
|
206
|
+
end
|
207
|
+
alias :ids :neighbors
|
208
|
+
def has?(id)
|
209
|
+
ids.include?(neighbor(id))
|
210
|
+
end
|
211
|
+
def -(id)
|
212
|
+
@set.delete neighbor(id)
|
213
|
+
end
|
214
|
+
def encode
|
215
|
+
ids.pack('N*')
|
216
|
+
end
|
217
|
+
def [](val)
|
218
|
+
neighbors[val]
|
219
|
+
end
|
220
|
+
def to_s_ary
|
221
|
+
ids.collect { |id| Neighbor.new(id).to_ip }
|
222
|
+
end
|
223
|
+
private
|
224
|
+
def neighbor(id)
|
225
|
+
Neighbor.new(id).to_i
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
def initialize(_arg={})
|
232
|
+
arg = _arg.dup
|
233
|
+
if arg.is_a?(Hash)
|
234
|
+
arg.merge!({:packet_type=>1})
|
235
|
+
super arg
|
236
|
+
@designated_router_id = DesignatedRouterId.new
|
237
|
+
@backup_designated_router_id = BackupDesignatedRouterId.new
|
238
|
+
@options = Options.new
|
239
|
+
@rtr_pri = 0
|
240
|
+
@netmask = Netmask.new
|
241
|
+
@neighbors = nil
|
242
|
+
@hello_interval, @router_dead_interval = 10, 40
|
243
|
+
set arg
|
244
|
+
|
245
|
+
elsif arg.is_a?(String)
|
246
|
+
parse arg
|
247
|
+
elsif arg.is_a?(Hello)
|
248
|
+
parse arg.encode
|
249
|
+
else
|
250
|
+
raise ArgumentError, "Invalid argument", caller
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def neighbors=(val)
|
255
|
+
@neighbors ||=Hello::Neighbors.new
|
256
|
+
self.neighbors + val
|
257
|
+
end
|
258
|
+
|
259
|
+
def remove_neighbor(val)
|
260
|
+
self.neighbors - val
|
261
|
+
end
|
262
|
+
def has_neighbor?(neighbor)
|
263
|
+
@neighbors ||=Hello::Neighbors.new
|
264
|
+
neighbors.has?(neighbor)
|
265
|
+
end
|
266
|
+
|
267
|
+
def add_router_id(hello)
|
268
|
+
self.neighbors = hello.router_id.to_hash
|
269
|
+
end
|
270
|
+
|
271
|
+
def to_s
|
272
|
+
super
|
273
|
+
end
|
274
|
+
|
275
|
+
def to_s_verbose
|
276
|
+
super +
|
277
|
+
[@netmask, @options, rtr_pri_to_s, @designated_router_id, @backup_designated_router_id, neighbors_to_s].collect { |x| x.to_s }.join("\n ")
|
278
|
+
end
|
279
|
+
|
280
|
+
def to_s
|
281
|
+
s = []
|
282
|
+
s << super
|
283
|
+
s << "HellInt #{hello_interval}, DeadInt #{router_dead_interval}, Options #{options.to_s}, mask #{netmask}"
|
284
|
+
s << "Prio #{@rtr_pri}, DR #{designated_router_id.to_ip}, BDR #{backup_designated_router_id.to_ip}"
|
285
|
+
s << "Neighbors: #{@neighbors.to_s_ary.join(',')}" if @neighbors
|
286
|
+
s.join("\n ")
|
287
|
+
end
|
288
|
+
|
289
|
+
def encode
|
290
|
+
packet =[]
|
291
|
+
packet << netmask.encode
|
292
|
+
packet << [@hello_interval, @options.to_i, @rtr_pri, @router_dead_interval].pack('nCCN')
|
293
|
+
packet << @designated_router_id.encode
|
294
|
+
packet << @backup_designated_router_id.encode
|
295
|
+
packet << neighbors.encode if neighbors
|
296
|
+
super packet.join
|
297
|
+
rescue Exception => e
|
298
|
+
p e
|
299
|
+
end
|
300
|
+
|
301
|
+
private
|
302
|
+
|
303
|
+
|
304
|
+
def neighbors_to_s
|
305
|
+
["Neighbors:", neighbors.collect { |x| x.to_s(nil) } ].join("\n ")
|
306
|
+
end
|
307
|
+
def router_dead_interval_s
|
308
|
+
["Neighbors:", neighbors.collect { |x| x.to_s(nil) } ].join("\n ")
|
309
|
+
end
|
310
|
+
|
311
|
+
def parse(s)
|
312
|
+
netmask, @hello_interval, options, @rtr_pri, @router_dead_interval, dr, bdr, neighbors = super(s).unpack('NnCCNNNa*')
|
313
|
+
@netmask = Netmask.new netmask
|
314
|
+
@options = Options.new options
|
315
|
+
@designated_router_id = DesignatedRouterId.new dr
|
316
|
+
@backup_designated_router_id = BackupDesignatedRouterId.new bdr
|
317
|
+
@neighbors ||=Hello::Neighbors.new
|
318
|
+
while neighbors.size>0
|
319
|
+
self.neighbors= neighbors.slice!(0,4).unpack('N')[0]
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
end
|
324
|
+
|
325
|
+
end
|
326
|
+
|
327
|
+
load "../../../test/ospfv2/packet/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
@@ -0,0 +1,144 @@
|
|
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
|
+
# A.3.6 The Link State Acknowledgment packet
|
24
|
+
#
|
25
|
+
# Link State Acknowledgment Packets are OSPF packet type 5. To make
|
26
|
+
# the flooding of LSAs reliable, flooded LSAs are explicitly
|
27
|
+
# acknowledged. This acknowledgment is accomplished through the
|
28
|
+
# sending and receiving of Link State Acknowledgment packets.
|
29
|
+
# Multiple LSAs can be acknowledged in a single Link State
|
30
|
+
# Acknowledgment packet.
|
31
|
+
#
|
32
|
+
# Depending on the state of the sending interface and the sender of
|
33
|
+
# the corresponding Link State Update packet, a Link State
|
34
|
+
# Acknowledgment packet is sent either to the multicast address
|
35
|
+
# AllSPFRouters, to the multicast address AllDRouters, or as a
|
36
|
+
# unicast. The sending of Link State Acknowledgement packets is
|
37
|
+
# documented in Section 13.5. The reception of Link State
|
38
|
+
# Acknowledgement packets is documented in Section 13.7.
|
39
|
+
#
|
40
|
+
# The format of this packet is similar to that of the Data Description
|
41
|
+
# packet. The body of both packets is simply a list of LSA headers.
|
42
|
+
#
|
43
|
+
#
|
44
|
+
# 0 1 2 3
|
45
|
+
# 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
|
46
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
47
|
+
# | Version # | 5 | Packet length |
|
48
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
49
|
+
# | Router ID |
|
50
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
51
|
+
# | Area ID |
|
52
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
53
|
+
# | Checksum | AuType |
|
54
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
55
|
+
# | Authentication |
|
56
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
57
|
+
# | Authentication |
|
58
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
59
|
+
# | |
|
60
|
+
# +- -+
|
61
|
+
# | |
|
62
|
+
# +- An LSA Header -+
|
63
|
+
# | |
|
64
|
+
# +- -+
|
65
|
+
# | |
|
66
|
+
# +- -+
|
67
|
+
# | |
|
68
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
69
|
+
# | ... |
|
70
|
+
#
|
71
|
+
#
|
72
|
+
|
73
|
+
require 'packet/ospf_packet'
|
74
|
+
|
75
|
+
module OSPFv2
|
76
|
+
|
77
|
+
class LinkStateAck < OspfPacket
|
78
|
+
|
79
|
+
attr_accessor :lsa_headers
|
80
|
+
|
81
|
+
def self.ack_ls_update(lsu, *args)
|
82
|
+
ls_ack = new *args
|
83
|
+
ls_ack.lsa_headers = lsu.lsas
|
84
|
+
ls_ack
|
85
|
+
end
|
86
|
+
|
87
|
+
def initialize(_arg={})
|
88
|
+
arg = _arg.dup
|
89
|
+
@lsa_headers=[]
|
90
|
+
if arg.is_a?(Hash)
|
91
|
+
arg.merge!({:packet_type=>5})
|
92
|
+
super arg
|
93
|
+
elsif arg.is_a?(String)
|
94
|
+
parse arg
|
95
|
+
elsif arg.is_a?(self.class)
|
96
|
+
parse arg.encode
|
97
|
+
else
|
98
|
+
raise ArgumentError, "Invalid argument", caller
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def add_lsa_header(lsu)
|
103
|
+
lsu.lsas
|
104
|
+
end
|
105
|
+
|
106
|
+
def encode
|
107
|
+
headers = []
|
108
|
+
headers << lsa_headers.collect { |x| x.encode.slice(0,20) }.join
|
109
|
+
super headers.join
|
110
|
+
end
|
111
|
+
|
112
|
+
def each_key
|
113
|
+
@lsa_headers.each do |lsa|
|
114
|
+
yield lsa.key
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def each
|
119
|
+
@lsa_headers.each do |lsa|
|
120
|
+
yield lsa
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def parse(s)
|
125
|
+
headers = super(s)
|
126
|
+
while headers.size>0
|
127
|
+
lsa = Lsa.new headers.slice!(0,20)
|
128
|
+
@lsa_headers <<lsa
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def to_s
|
133
|
+
s =[]
|
134
|
+
s << super
|
135
|
+
s << "Age Options Type Link-State ID Advr Router Sequence Checksum Length" if lsa_headers.size>0
|
136
|
+
s << lsa_headers.collect { |x| x.to_s_dd }
|
137
|
+
s.join("\n ")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
load "../../../test/ospfv2/packet/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
144
|
+
|
@@ -0,0 +1,153 @@
|
|
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
|
+
|
26
|
+
|
27
|
+
A.3.4 The Link State Request packet
|
28
|
+
|
29
|
+
Link State Request packets are OSPF packet type 3. After exchanging
|
30
|
+
Database Description packets with a neighboring router, a router may
|
31
|
+
find that parts of its link-state database are out-of-date. The
|
32
|
+
Link State Request packet is used to request the pieces of the
|
33
|
+
neighbor's database that are more up-to-date. Multiple Link State
|
34
|
+
Request packets may need to be used.
|
35
|
+
|
36
|
+
A router that sends a Link State Request packet has in mind the
|
37
|
+
precise instance of the database pieces it is requesting. Each
|
38
|
+
instance is defined by its LS sequence number, LS checksum, and LS
|
39
|
+
age, although these fields are not specified in the Link State
|
40
|
+
Request Packet itself. The router may receive even more recent
|
41
|
+
instances in response.
|
42
|
+
|
43
|
+
The sending of Link State Request packets is documented in Section
|
44
|
+
10.9. The reception of Link State Request packets is documented in
|
45
|
+
Section 10.7.
|
46
|
+
|
47
|
+
0 1 2 3
|
48
|
+
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
|
49
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
50
|
+
| Version # | 3 | Packet length |
|
51
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
52
|
+
| Router ID |
|
53
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
54
|
+
| Area ID |
|
55
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
56
|
+
| Checksum | AuType |
|
57
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
58
|
+
| Authentication |
|
59
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
60
|
+
| Authentication |
|
61
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
62
|
+
| LS type |
|
63
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
64
|
+
| Link State ID |
|
65
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
66
|
+
| Advertising Router |
|
67
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
68
|
+
| ... |
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
Each LSA requested is specified by its LS type, Link State ID, and
|
73
|
+
Advertising Router. This uniquely identifies the LSA, but not its
|
74
|
+
instance. Link State Request packets are understood to be requests
|
75
|
+
for the most recent instance (whatever that might be).
|
76
|
+
|
77
|
+
=end
|
78
|
+
|
79
|
+
require 'packet/ospf_packet'
|
80
|
+
module OSPFv2
|
81
|
+
class LinkStateRequest < OspfPacket
|
82
|
+
|
83
|
+
attr_reader :requests
|
84
|
+
|
85
|
+
def initialize(arg={})
|
86
|
+
@requests=[]
|
87
|
+
if arg.is_a?(String)
|
88
|
+
parse arg
|
89
|
+
elsif arg.is_a?(Hash)
|
90
|
+
arg.merge! :packet_type=>3
|
91
|
+
super arg
|
92
|
+
elsif arg.is_a?(self)
|
93
|
+
parse arg.encode
|
94
|
+
else
|
95
|
+
raise ArgumentError, "Invalid argument"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def <<(req)
|
100
|
+
@request << req
|
101
|
+
end
|
102
|
+
|
103
|
+
def encode
|
104
|
+
requests = []
|
105
|
+
requests << @requests.collect { |lsa| lsa.pack('NNN') }.join
|
106
|
+
super requests.join
|
107
|
+
end
|
108
|
+
|
109
|
+
def parse(s)
|
110
|
+
requests = super(s)
|
111
|
+
while requests.size>0
|
112
|
+
@requests << requests.slice!(0,12).unpack('NNN')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_s
|
117
|
+
s = []
|
118
|
+
s << super
|
119
|
+
s << @requests.collect { |x|
|
120
|
+
"LS type #{ls_type_to_s(x[0])} Link State ID #{ls_id_to_s(x[1])} Advertising Router #{advr_to_s(x[2])}"
|
121
|
+
}.join("\n ")
|
122
|
+
s.join("\n ")
|
123
|
+
end
|
124
|
+
|
125
|
+
def to_lsu(ls_db, arg={})
|
126
|
+
LinkStateUpdate.new_lsas arg.merge(:lsas => collect { |req| ls_db[req] })
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def collect
|
132
|
+
@requests.collect do |r|
|
133
|
+
yield r
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def ls_type_to_s(ls_type)
|
138
|
+
LsType.to_sym(ls_type)
|
139
|
+
end
|
140
|
+
|
141
|
+
def ls_id_to_s(id)
|
142
|
+
IPAddr.create(id).to_s
|
143
|
+
end
|
144
|
+
|
145
|
+
def advr_to_s(id)
|
146
|
+
IPAddr.create(id).to_s
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
load "../../../test/ospfv2/packet/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|