ospfv2 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|