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.
Files changed (56) hide show
  1. data/bin/ospfv2 +136 -0
  2. data/lib/ie/au_type.rb +79 -0
  3. data/lib/ie/external_route.rb +181 -0
  4. data/lib/ie/id.rb +97 -0
  5. data/lib/ie/interface_mtu.rb +64 -0
  6. data/lib/ie/ls_age.rb +89 -0
  7. data/lib/ie/ls_type.rb +148 -0
  8. data/lib/ie/metric.rb +63 -0
  9. data/lib/ie/mt_metric.rb +119 -0
  10. data/lib/ie/options.rb +356 -0
  11. data/lib/ie/ospf_version.rb +67 -0
  12. data/lib/ie/packet_type.rb +65 -0
  13. data/lib/ie/router_link.rb +167 -0
  14. data/lib/ie/router_link_factory.rb +53 -0
  15. data/lib/ie/router_link_type.rb +86 -0
  16. data/lib/ie/sequence_number.rb +144 -0
  17. data/lib/ie/tos_metric.rb +102 -0
  18. data/lib/infra/ospf_common.rb +291 -0
  19. data/lib/infra/ospf_constants.rb +73 -0
  20. data/lib/infra/ospf_io.rb +133 -0
  21. data/lib/infra/ospf_socket.rb +126 -0
  22. data/lib/infra/parse_options.rb +135 -0
  23. data/lib/infra/timer.rb +104 -0
  24. data/lib/infra/to_s.rb +38 -0
  25. data/lib/ls_db/advertised_routers.rb +78 -0
  26. data/lib/ls_db/common.rb +31 -0
  27. data/lib/ls_db/link_state_database.rb +376 -0
  28. data/lib/ls_db/link_state_database_build.rb +181 -0
  29. data/lib/ls_db/link_state_database_links.rb +178 -0
  30. data/lib/ls_db/links.rb +160 -0
  31. data/lib/lsa/external.rb +347 -0
  32. data/lib/lsa/lsa.rb +438 -0
  33. data/lib/lsa/lsa_factory.rb +59 -0
  34. data/lib/lsa/network.rb +166 -0
  35. data/lib/lsa/router.rb +336 -0
  36. data/lib/lsa/summary.rb +393 -0
  37. data/lib/neighbor/neighbor.rb +298 -0
  38. data/lib/neighbor/neighbor_event_handler.rb +61 -0
  39. data/lib/neighbor/recv_database_description.rb +153 -0
  40. data/lib/neighbor/recv_hello.rb +53 -0
  41. data/lib/neighbor/recv_ospf_packet.rb +68 -0
  42. data/lib/neighbor_sm/attempt_state.rb +44 -0
  43. data/lib/neighbor_sm/down_state.rb +46 -0
  44. data/lib/neighbor_sm/exchange_state.rb +32 -0
  45. data/lib/neighbor_sm/exstart_state.rb +69 -0
  46. data/lib/neighbor_sm/full_state.rb +36 -0
  47. data/lib/neighbor_sm/init_state.rb +43 -0
  48. data/lib/neighbor_sm/loading_state.rb +33 -0
  49. data/lib/neighbor_sm/neighbor_state.rb +87 -0
  50. data/lib/packet/database_description.rb +300 -0
  51. data/lib/packet/hello.rb +327 -0
  52. data/lib/packet/link_state_ack.rb +144 -0
  53. data/lib/packet/link_state_request.rb +153 -0
  54. data/lib/packet/link_state_update.rb +189 -0
  55. data/lib/packet/ospf_packet.rb +306 -0
  56. metadata +116 -0
@@ -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