ospfv2 0.0.1

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