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