ipadmin 0.2.1 → 0.2.2
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/README +77 -13
- data/lib/cidr.rb +1459 -0
- data/lib/ip_admin.rb +3 -3682
- data/lib/methods.rb +2168 -0
- data/lib/tree.rb +735 -0
- data/tests/cidr_test.rb +34 -2
- data/tests/methods_test.rb +151 -102
- metadata +5 -2
data/lib/tree.rb
ADDED
@@ -0,0 +1,735 @@
|
|
1
|
+
=begin rdoc
|
2
|
+
Copyright (c) 2006 Dustin Spinhirne -
|
3
|
+
Licensed under the same terms as Ruby, No Warranty is provided.
|
4
|
+
=end
|
5
|
+
|
6
|
+
|
7
|
+
module IPAdmin
|
8
|
+
class Tree
|
9
|
+
|
10
|
+
# instance variables
|
11
|
+
# @all_f
|
12
|
+
# @max_bits
|
13
|
+
# @root
|
14
|
+
# @version
|
15
|
+
|
16
|
+
#==============================================================================#
|
17
|
+
# attr_reader / attr_writer
|
18
|
+
#==============================================================================#
|
19
|
+
|
20
|
+
# IP version for this tree (4 or 6)
|
21
|
+
attr_reader :version
|
22
|
+
|
23
|
+
#======================================#
|
24
|
+
#
|
25
|
+
#======================================#
|
26
|
+
|
27
|
+
|
28
|
+
#==============================================================================#
|
29
|
+
# initialize()
|
30
|
+
#==============================================================================#
|
31
|
+
|
32
|
+
# - Arguments:
|
33
|
+
# * Hash with the following fields:
|
34
|
+
# - :Version -- IP version - Integer
|
35
|
+
#
|
36
|
+
# Example:
|
37
|
+
# table = IPAdmin::CIDRTable.new(:Version => 4)
|
38
|
+
#
|
39
|
+
def initialize(options)
|
40
|
+
if (!options.kind_of? Hash)
|
41
|
+
raise ArgumentError, "Expected Hash, but #{options.class} provided."
|
42
|
+
end
|
43
|
+
|
44
|
+
if ( options.has_key?(:Version) )
|
45
|
+
@version = options[:Version]
|
46
|
+
|
47
|
+
if ( @version != 4 && @version != 6 )
|
48
|
+
raise "IP version should be either 4 or 6."
|
49
|
+
end
|
50
|
+
else
|
51
|
+
raise ArgumentError, "Missing argument: Version."
|
52
|
+
end
|
53
|
+
|
54
|
+
if (@version == 4)
|
55
|
+
@max_bits = 32
|
56
|
+
@all_f = 2**@max_bits - 1
|
57
|
+
else
|
58
|
+
@max_bits = 128
|
59
|
+
@all_f = 2**@max_bits - 1
|
60
|
+
end
|
61
|
+
|
62
|
+
# root of our ordered IP tree
|
63
|
+
@root = []
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
#======================================#
|
68
|
+
#
|
69
|
+
#======================================#
|
70
|
+
|
71
|
+
|
72
|
+
#==============================================================================#
|
73
|
+
# add()
|
74
|
+
#==============================================================================#
|
75
|
+
|
76
|
+
# Add an IPAdmin::CIDR object to the tree.
|
77
|
+
#
|
78
|
+
# - Arguments:
|
79
|
+
# * CIDR object
|
80
|
+
#
|
81
|
+
# - Returns:
|
82
|
+
# * nothing
|
83
|
+
#
|
84
|
+
# Example:
|
85
|
+
# tree.add(cidr)
|
86
|
+
#
|
87
|
+
def add(object)
|
88
|
+
|
89
|
+
# validate object
|
90
|
+
if ( !object.kind_of?(IPAdmin::CIDR) )
|
91
|
+
raise ArgumentError, "IPAdmin::CIDR object " +
|
92
|
+
"required but #{object.class} provided."
|
93
|
+
end
|
94
|
+
|
95
|
+
if ( object.version != @version )
|
96
|
+
raise "IP version #{object.version} is incompatible with " +
|
97
|
+
"Tree IP version #{@version}."
|
98
|
+
end
|
99
|
+
|
100
|
+
net_struct = IPAdmin.create_net_struct(object)
|
101
|
+
|
102
|
+
# search tree for it's home branch
|
103
|
+
search_results = find_home(net_struct, @root)
|
104
|
+
home_struct = search_results[0] if (search_results)
|
105
|
+
home_branch = home_struct.subnets if (search_results)
|
106
|
+
home_branch = @root if (!home_branch)
|
107
|
+
|
108
|
+
# make sure we dont have a duplicate
|
109
|
+
if (home_struct)
|
110
|
+
if ( (net_struct.network == home_struct.network) &&
|
111
|
+
(net_struct.netmask == home_struct.netmask) )
|
112
|
+
raise "Attempted to add #{object.desc()} multiple times."
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# now that we have our branch location, check that other entries
|
117
|
+
# of this branch are not subnets of our new object. if they are
|
118
|
+
# then make them a branch of our new object
|
119
|
+
home_branch.each do |entry|
|
120
|
+
is_contained = contains(net_struct, entry)
|
121
|
+
|
122
|
+
if (is_contained)
|
123
|
+
net_struct.subnets.push(entry)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
net_struct.subnets.each do |entry|
|
128
|
+
home_branch.delete(entry)
|
129
|
+
end
|
130
|
+
|
131
|
+
# add new object as an ordered entry to home_branch
|
132
|
+
add_to_branch(net_struct,home_branch)
|
133
|
+
|
134
|
+
return(nil)
|
135
|
+
end
|
136
|
+
|
137
|
+
#======================================#
|
138
|
+
#
|
139
|
+
#======================================#
|
140
|
+
|
141
|
+
|
142
|
+
#==============================================================================#
|
143
|
+
# collapse()
|
144
|
+
#==============================================================================#
|
145
|
+
|
146
|
+
# Collapse (supernet) all subnets of the tree,
|
147
|
+
# and return a new tree. The supernetting of subnets will only occur in
|
148
|
+
# situations where the newly created supernet will not result in the
|
149
|
+
# 'creation' of additional space. For example the following blocks
|
150
|
+
# (192.168.0.0/24, 192.168.1.0/24, and 192.168.2.0/24) would merge into
|
151
|
+
# 192.168.0.0/23 and 192.168.2.0/24 rather than into 192.168.0.0/22.
|
152
|
+
#
|
153
|
+
# - Arguments:
|
154
|
+
# * none
|
155
|
+
#
|
156
|
+
# - Returns:
|
157
|
+
# * Tree object
|
158
|
+
#
|
159
|
+
# Example:
|
160
|
+
# new_tree = tree.collapse()
|
161
|
+
#
|
162
|
+
def collapse()
|
163
|
+
tree = IPAdmin::Tree.new(:Version => @version)
|
164
|
+
branch = IPAdmin.merge(:List => @root, :NetStruct => 1)
|
165
|
+
dumped = dump_branch(branch)
|
166
|
+
dumped.each do |entry|
|
167
|
+
net_struct = entry[:NetStruct]
|
168
|
+
network = IPAdmin.unpack_ip_addr(:Integer => net_struct.network,
|
169
|
+
:Version => @version)
|
170
|
+
netmask = IPAdmin.unpack_ip_netmask(:Integer => net_struct.netmask,
|
171
|
+
:Version => @version)
|
172
|
+
cidr = IPAdmin::CIDR.new(:CIDR => "#{network}/#{netmask}")
|
173
|
+
tree.add(cidr)
|
174
|
+
end
|
175
|
+
return(tree)
|
176
|
+
end
|
177
|
+
|
178
|
+
#======================================#
|
179
|
+
#
|
180
|
+
#======================================#
|
181
|
+
|
182
|
+
|
183
|
+
#==============================================================================#
|
184
|
+
# dump
|
185
|
+
#==============================================================================#
|
186
|
+
|
187
|
+
# Dump the contents of this tree.
|
188
|
+
#
|
189
|
+
# - Arguments:
|
190
|
+
# * none
|
191
|
+
#
|
192
|
+
# - Returns:
|
193
|
+
# * ordered array of hashes with the following fields:
|
194
|
+
# - :Object => CIDR object
|
195
|
+
# - :Depth => (depth level in tree)
|
196
|
+
# Example:
|
197
|
+
# dumped = tree.dump()
|
198
|
+
#
|
199
|
+
def dump()
|
200
|
+
list = []
|
201
|
+
dumped = dump_branch(@root)
|
202
|
+
|
203
|
+
dumped.each do |entry|
|
204
|
+
depth = entry[:Depth]
|
205
|
+
net_struct = entry[:NetStruct]
|
206
|
+
object = net_struct.object
|
207
|
+
list.push({:Depth => depth, :Object => object})
|
208
|
+
end
|
209
|
+
|
210
|
+
return(list)
|
211
|
+
end
|
212
|
+
|
213
|
+
#======================================#
|
214
|
+
#
|
215
|
+
#======================================#
|
216
|
+
|
217
|
+
|
218
|
+
#==============================================================================#
|
219
|
+
# exists?()
|
220
|
+
#==============================================================================#
|
221
|
+
|
222
|
+
# Has an IPAdmin::CIDR object already been added to the tree?
|
223
|
+
#
|
224
|
+
# - Arguments:
|
225
|
+
# * CIDR object
|
226
|
+
#
|
227
|
+
# - Returns:
|
228
|
+
# * true or false
|
229
|
+
#
|
230
|
+
# Example:
|
231
|
+
# added = tree.exists?(cidr)
|
232
|
+
#
|
233
|
+
def exists?(object)
|
234
|
+
|
235
|
+
# validate object
|
236
|
+
if ( !object.kind_of?(IPAdmin::CIDR) )
|
237
|
+
raise ArgumentError, "IPAdmin::CIDR object " +
|
238
|
+
"required but #{object.class} provided."
|
239
|
+
end
|
240
|
+
|
241
|
+
if ( !object.version == @version )
|
242
|
+
raise "IP version #{object.version} is incompatible with " +
|
243
|
+
"Tree IP version #{@version}."
|
244
|
+
end
|
245
|
+
|
246
|
+
net_struct = IPAdmin.create_net_struct(object)
|
247
|
+
home_struct,home_branch = find_home(net_struct, @root)
|
248
|
+
|
249
|
+
# check for match
|
250
|
+
found = false
|
251
|
+
if (home_struct)
|
252
|
+
if ( (net_struct.network == home_struct.network) &&
|
253
|
+
(net_struct.netmask == home_struct.netmask) )
|
254
|
+
found = true
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
return(found)
|
260
|
+
end
|
261
|
+
|
262
|
+
#======================================#
|
263
|
+
#
|
264
|
+
#======================================#
|
265
|
+
|
266
|
+
|
267
|
+
#==============================================================================#
|
268
|
+
# find()
|
269
|
+
#==============================================================================#
|
270
|
+
|
271
|
+
# Find the longest matching branch of our tree to which an
|
272
|
+
# IPAdmin::CIDR object belongs. Useful for performing 'routing table' lookups.
|
273
|
+
#
|
274
|
+
# - Arguments:
|
275
|
+
# * CIDR object
|
276
|
+
#
|
277
|
+
# - Returns:
|
278
|
+
# * CIDR object, or nil
|
279
|
+
#
|
280
|
+
# Example:
|
281
|
+
# longest_match = tree.find(ip)
|
282
|
+
#
|
283
|
+
def find(object)
|
284
|
+
if ( !object.kind_of?(IPAdmin::CIDR) )
|
285
|
+
raise ArgumentError, "IPAdmin::CIDR object " +
|
286
|
+
"required but #{object.class} provided."
|
287
|
+
end
|
288
|
+
|
289
|
+
if ( object.version != @version )
|
290
|
+
raise "IP version #{object.version} is incompatible with " +
|
291
|
+
"Tree IP version #{@version}."
|
292
|
+
end
|
293
|
+
|
294
|
+
net_struct = IPAdmin.create_net_struct(object)
|
295
|
+
home_struct,home_branch = find_home(net_struct, @root)
|
296
|
+
found_obj = home_struct.object if (home_struct)
|
297
|
+
|
298
|
+
return(found_obj)
|
299
|
+
end
|
300
|
+
|
301
|
+
#======================================#
|
302
|
+
#
|
303
|
+
#======================================#
|
304
|
+
|
305
|
+
|
306
|
+
#==============================================================================#
|
307
|
+
# find_space()
|
308
|
+
#==============================================================================#
|
309
|
+
|
310
|
+
# Find Tree entries that can hold a subnet of size X. Returns only the smallest
|
311
|
+
# matching subnets of each supernet. If neither IPCount or Subnet or provided,
|
312
|
+
# then method returns all entries that can fit a single IP.
|
313
|
+
#
|
314
|
+
# - Arguments:
|
315
|
+
# * Hash with the following fields:
|
316
|
+
# - :IPCount -- Minimum number of IP's that should fit within subnet - Integer (optional)
|
317
|
+
# - :Limit -- Maximum entries to return - Integer (optional)
|
318
|
+
# - :Subnet -- Netmask (in bits) of space to find - Integer (optional)
|
319
|
+
#
|
320
|
+
# - Returns:
|
321
|
+
# * Array of CIDR objects
|
322
|
+
#
|
323
|
+
# - Notes:
|
324
|
+
# * :Subnet always takes precedence over :IPCount.
|
325
|
+
#
|
326
|
+
# Example:
|
327
|
+
# list = tree.find_space(:Subnet => 27)
|
328
|
+
# list = tree.find_space(:IPCount => 33, :Limit => 2)
|
329
|
+
#
|
330
|
+
def find_space(options)
|
331
|
+
limit = nil
|
332
|
+
list = []
|
333
|
+
|
334
|
+
# validate options
|
335
|
+
if (!options.kind_of? Hash)
|
336
|
+
raise ArgumentError, "Expected Hash, but #{options.class} provided."
|
337
|
+
end
|
338
|
+
|
339
|
+
if ( options.has_key?(:Limit) )
|
340
|
+
limit = options[:Limit]
|
341
|
+
end
|
342
|
+
|
343
|
+
if ( options.has_key?(:IPCount) )
|
344
|
+
subnet_size = IPAdmin.minimum_size(:IPCount =>options[:IPCount],
|
345
|
+
:Version => @version)
|
346
|
+
end
|
347
|
+
|
348
|
+
if ( options.has_key?(:Subnet) )
|
349
|
+
subnet_size = options[:Subnet]
|
350
|
+
end
|
351
|
+
|
352
|
+
# set subnet_size if not already
|
353
|
+
if (!subnet_size)
|
354
|
+
if (@version == 4)
|
355
|
+
subnet_size = 32
|
356
|
+
else
|
357
|
+
subnet_size = 128
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
# check that subnet_size is a valid size
|
362
|
+
if ( (subnet_size < 1) || (subnet_size > @max_bits) )
|
363
|
+
raise "#{subnet_size} is out of range for an " +
|
364
|
+
"IP version #{@version} Tree."
|
365
|
+
end
|
366
|
+
|
367
|
+
# search
|
368
|
+
search_list = dump_branch(@root)
|
369
|
+
search_list.each do |entry|
|
370
|
+
depth = entry[:Depth]
|
371
|
+
net_struct = entry[:NetStruct]
|
372
|
+
|
373
|
+
# we only want leaf nodes of type IPAdmin::CIDR
|
374
|
+
if ( (net_struct.subnets.length == 0) &&
|
375
|
+
(net_struct.object.kind_of?(IPAdmin::CIDR)) )
|
376
|
+
|
377
|
+
if (subnet_size >= net_struct.object.bits)
|
378
|
+
list.push(net_struct.object)
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
if (limit && (list.length >= limit) )
|
383
|
+
break
|
384
|
+
end
|
385
|
+
|
386
|
+
end
|
387
|
+
|
388
|
+
return(list)
|
389
|
+
|
390
|
+
end
|
391
|
+
|
392
|
+
#======================================#
|
393
|
+
#
|
394
|
+
#======================================#
|
395
|
+
|
396
|
+
|
397
|
+
#==============================================================================#
|
398
|
+
# prune()
|
399
|
+
#==============================================================================#
|
400
|
+
|
401
|
+
# Remove an IPAdmin::CIDR object, and all child
|
402
|
+
# objects from the tree.
|
403
|
+
#
|
404
|
+
# - Arguments:
|
405
|
+
# * CIDR object
|
406
|
+
#
|
407
|
+
# - Returns:
|
408
|
+
# * true or false
|
409
|
+
#
|
410
|
+
# Example:
|
411
|
+
# did_prune = tree.prune(ip)
|
412
|
+
#
|
413
|
+
def prune(object)
|
414
|
+
if ( !object.kind_of?(IPAdmin::CIDR) )
|
415
|
+
raise ArgumentError, "IPAdmin::CIDR object " +
|
416
|
+
"required but #{object.class} provided."
|
417
|
+
end
|
418
|
+
|
419
|
+
if (object.version != @version )
|
420
|
+
raise "IP version #{object.version} is incompatible with " +
|
421
|
+
"Tree IP version #{@version}."
|
422
|
+
end
|
423
|
+
|
424
|
+
net_struct = IPAdmin.create_net_struct(object)
|
425
|
+
home_struct,home_branch = find_home(net_struct, @root)
|
426
|
+
|
427
|
+
if(!home_struct)
|
428
|
+
raise "#{object.desc} could not be found."
|
429
|
+
end
|
430
|
+
|
431
|
+
# remove if home_struct.object = object
|
432
|
+
pruned = false
|
433
|
+
if (home_struct.object = object)
|
434
|
+
home_branch.delete(home_struct)
|
435
|
+
pruned = true
|
436
|
+
end
|
437
|
+
|
438
|
+
return(pruned)
|
439
|
+
end
|
440
|
+
|
441
|
+
#======================================#
|
442
|
+
#
|
443
|
+
#======================================#
|
444
|
+
|
445
|
+
|
446
|
+
#==============================================================================#
|
447
|
+
# remove()
|
448
|
+
#==============================================================================#
|
449
|
+
|
450
|
+
# Remove a single CIDR object from the tree.
|
451
|
+
#
|
452
|
+
# - Arguments:
|
453
|
+
# * CIDR object
|
454
|
+
#
|
455
|
+
# - Returns:
|
456
|
+
# * true or false
|
457
|
+
#
|
458
|
+
# Example:
|
459
|
+
# did_remove = tree.remove(ip)
|
460
|
+
#
|
461
|
+
def remove(object)
|
462
|
+
if ( !object.kind_of?(IPAdmin::CIDR) )
|
463
|
+
raise ArgumentError, "IPAdmin::CIDR object " +
|
464
|
+
"required but #{object.class} provided."
|
465
|
+
end
|
466
|
+
|
467
|
+
if (object.version != @version )
|
468
|
+
raise "IP version #{object.version} is incompatible with " +
|
469
|
+
"Tree IP version #{@version}."
|
470
|
+
end
|
471
|
+
|
472
|
+
net_struct = IPAdmin.create_net_struct(object)
|
473
|
+
home_struct,home_branch = find_home(net_struct, @root)
|
474
|
+
|
475
|
+
# remove if home_struct.object = object
|
476
|
+
removed = false
|
477
|
+
if (home_struct.object = object)
|
478
|
+
|
479
|
+
# if we have children subnets, move them up one level
|
480
|
+
if (home_struct.subnets.length > 0)
|
481
|
+
home_struct.subnets.each do |entry|
|
482
|
+
index = 0
|
483
|
+
home_branch.each do
|
484
|
+
if(entry.network < (home_branch[index]).network)
|
485
|
+
break
|
486
|
+
end
|
487
|
+
index += 1
|
488
|
+
end
|
489
|
+
home_branch.insert(index, entry)
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
home_branch.delete(home_struct)
|
494
|
+
removed = true
|
495
|
+
end
|
496
|
+
|
497
|
+
return(removed)
|
498
|
+
end
|
499
|
+
|
500
|
+
#======================================#
|
501
|
+
#
|
502
|
+
#======================================#
|
503
|
+
|
504
|
+
|
505
|
+
#==============================================================================#
|
506
|
+
# show()
|
507
|
+
#==============================================================================#
|
508
|
+
|
509
|
+
# Print the tree in a nicely formatted string.
|
510
|
+
#
|
511
|
+
# - Arguments:
|
512
|
+
# * none
|
513
|
+
#
|
514
|
+
# - Returns:
|
515
|
+
# * String representing the contents of the tree
|
516
|
+
#
|
517
|
+
# Example:
|
518
|
+
# puts tree.show()
|
519
|
+
#
|
520
|
+
def show()
|
521
|
+
printed = ""
|
522
|
+
list = dump_branch(@root)
|
523
|
+
|
524
|
+
list.each do |entry|
|
525
|
+
net_struct = entry[:NetStruct]
|
526
|
+
depth = entry[:Depth]
|
527
|
+
network = IPAdmin.unpack_ip_addr(:Integer => net_struct.network,
|
528
|
+
:Version => @version)
|
529
|
+
netmask = IPAdmin.unpack_ip_netmask(:Integer => net_struct.netmask,
|
530
|
+
:Version => @version)
|
531
|
+
network = IPAdmin.shorten(network) if (@version == 6)
|
532
|
+
|
533
|
+
if (depth == 0)
|
534
|
+
indent = ""
|
535
|
+
else
|
536
|
+
indent = " " * (depth*3)
|
537
|
+
end
|
538
|
+
|
539
|
+
printed << "#{indent}#{network}/#{netmask}\n"
|
540
|
+
end
|
541
|
+
|
542
|
+
return(printed)
|
543
|
+
end
|
544
|
+
|
545
|
+
#======================================#
|
546
|
+
#
|
547
|
+
#======================================#
|
548
|
+
|
549
|
+
|
550
|
+
|
551
|
+
|
552
|
+
# PRIVATE METHODS
|
553
|
+
private
|
554
|
+
|
555
|
+
#==============================================================================#
|
556
|
+
# add_to_branch() private
|
557
|
+
#==============================================================================#
|
558
|
+
|
559
|
+
# Add Netstruct object to an array of NetStruct's
|
560
|
+
#
|
561
|
+
# - Arguments:
|
562
|
+
# * NetStruct, and array of NetStruct's in which to add it
|
563
|
+
#
|
564
|
+
# - Returns:
|
565
|
+
# * none
|
566
|
+
#
|
567
|
+
# Example:
|
568
|
+
# add_to_branch(net_struct,branch)
|
569
|
+
#
|
570
|
+
def add_to_branch(net_struct,branch)
|
571
|
+
# make sure we have appropriate types
|
572
|
+
if (!net_struct.kind_of?(IPAdmin::NetStruct) ||
|
573
|
+
!branch.kind_of?(Array) )
|
574
|
+
raise ArgumentError, "Incorrect argument types " +
|
575
|
+
"#{net_struct.class} and #{branch}."
|
576
|
+
end
|
577
|
+
|
578
|
+
index = 0
|
579
|
+
branch.each do
|
580
|
+
if(net_struct.network < (branch[index]).network)
|
581
|
+
break
|
582
|
+
end
|
583
|
+
index += 1
|
584
|
+
end
|
585
|
+
|
586
|
+
branch.insert(index, net_struct)
|
587
|
+
|
588
|
+
return()
|
589
|
+
end
|
590
|
+
|
591
|
+
#======================================#
|
592
|
+
#
|
593
|
+
#======================================#
|
594
|
+
|
595
|
+
|
596
|
+
#==============================================================================#
|
597
|
+
# contains() private
|
598
|
+
#==============================================================================#
|
599
|
+
|
600
|
+
# Is the first NetStruct object the supernet of the second?
|
601
|
+
#
|
602
|
+
# - Arguments:
|
603
|
+
# * Two NetStruct objects
|
604
|
+
#
|
605
|
+
# - Returns:
|
606
|
+
# * true if struct1 contains or is equal to struct2, or false if not.
|
607
|
+
#
|
608
|
+
# Example:
|
609
|
+
# is_contained = contains(struct1,struct2)
|
610
|
+
#
|
611
|
+
def contains(struct1,struct2)
|
612
|
+
|
613
|
+
# make sure we have appropriate types
|
614
|
+
if (!struct1.kind_of?(IPAdmin::NetStruct) ||
|
615
|
+
!struct2.kind_of?(IPAdmin::NetStruct) )
|
616
|
+
raise ArgumentError, "Incorrect argument types " +
|
617
|
+
"#{struct1.class} and #{struct2.class}."
|
618
|
+
end
|
619
|
+
|
620
|
+
network1 = struct1.network
|
621
|
+
netmask1 = struct1.netmask
|
622
|
+
network2 = struct2.network
|
623
|
+
netmask2 = struct2.netmask
|
624
|
+
hostmask1 = netmask1 ^ @all_f
|
625
|
+
|
626
|
+
# if network1 == network2, then we have to go by netmask length
|
627
|
+
# else we can tell by or'ing network1 and network2 by hostmask1
|
628
|
+
# and comparing the results
|
629
|
+
is_contained = false
|
630
|
+
if (network1 == network2)
|
631
|
+
if (netmask2 >= netmask1)
|
632
|
+
is_contained = true
|
633
|
+
end
|
634
|
+
else
|
635
|
+
if ( (network1 | hostmask1) == (network2 | hostmask1) )
|
636
|
+
is_contained = true
|
637
|
+
end
|
638
|
+
end
|
639
|
+
|
640
|
+
return(is_contained)
|
641
|
+
end
|
642
|
+
|
643
|
+
#======================================#
|
644
|
+
#
|
645
|
+
#======================================#
|
646
|
+
|
647
|
+
|
648
|
+
#==============================================================================#
|
649
|
+
# dump_branch() private
|
650
|
+
#==============================================================================#
|
651
|
+
|
652
|
+
# Dump contents of an Array of NetStruct objects
|
653
|
+
#
|
654
|
+
# - Arguments:
|
655
|
+
# * array of NetStruct objects, and an optional depth within the tree
|
656
|
+
#
|
657
|
+
# - Returns:
|
658
|
+
# * array of hashes in form: :NetStruct => IPAdmin::NetStruct object
|
659
|
+
# :Depth => (depth level in tree)
|
660
|
+
# Example:
|
661
|
+
# dumped = dump_branch(branch)
|
662
|
+
#
|
663
|
+
def dump_branch(branch,depth=nil)
|
664
|
+
list = []
|
665
|
+
depth = 0 if (!depth)
|
666
|
+
|
667
|
+
branch.each do |entry|
|
668
|
+
subnets = entry.subnets
|
669
|
+
list.push({:NetStruct => entry, :Depth => depth})
|
670
|
+
|
671
|
+
if (subnets.length > 0)
|
672
|
+
list.concat( dump_branch(subnets, (depth+1) ) )
|
673
|
+
end
|
674
|
+
|
675
|
+
end
|
676
|
+
|
677
|
+
return(list)
|
678
|
+
end
|
679
|
+
|
680
|
+
#======================================#
|
681
|
+
#
|
682
|
+
#======================================#
|
683
|
+
|
684
|
+
|
685
|
+
#==============================================================================#
|
686
|
+
# find_home() private
|
687
|
+
#==============================================================================#
|
688
|
+
|
689
|
+
# Find the branch to which a NetStruct object belongs.
|
690
|
+
#
|
691
|
+
# - Arguments:
|
692
|
+
# * IPAdmin::NetStruct to find, and Array of
|
693
|
+
# IPAdmin::NetStruct's to search
|
694
|
+
#
|
695
|
+
# - Returns:
|
696
|
+
# * array of: container IPAdmin::NetStruct object,
|
697
|
+
# and container branch, or nil
|
698
|
+
#
|
699
|
+
# Example:
|
700
|
+
# branch = find_home(net_struct,branch)
|
701
|
+
#
|
702
|
+
def find_home(net_struct,branch)
|
703
|
+
ret_val = nil
|
704
|
+
|
705
|
+
branch.each do |entry|
|
706
|
+
is_contained = contains(entry,net_struct)
|
707
|
+
|
708
|
+
if (is_contained)
|
709
|
+
home_struct = entry
|
710
|
+
home_branch = branch
|
711
|
+
|
712
|
+
if (home_struct.subnets.length > 0)
|
713
|
+
search_results = find_home(net_struct,home_struct.subnets)
|
714
|
+
if (search_results)
|
715
|
+
home_struct = search_results[0]
|
716
|
+
home_branch = search_results[1]
|
717
|
+
end
|
718
|
+
end
|
719
|
+
|
720
|
+
ret_val = [home_struct,home_branch]
|
721
|
+
break
|
722
|
+
end
|
723
|
+
end
|
724
|
+
|
725
|
+
return(ret_val)
|
726
|
+
end
|
727
|
+
|
728
|
+
#======================================#
|
729
|
+
#
|
730
|
+
#======================================#
|
731
|
+
|
732
|
+
end
|
733
|
+
|
734
|
+
end # module IPAdmin
|
735
|
+
__END__
|