netaddr 1.5.3 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of netaddr might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/LICENSE +201 -0
- data/README.md +28 -8
- data/lib/eui48.rb +65 -0
- data/lib/eui64.rb +77 -0
- data/lib/ipv4.rb +77 -0
- data/lib/ipv4net.rb +245 -0
- data/lib/ipv6.rb +110 -0
- data/lib/ipv6net.rb +246 -0
- data/lib/mask128.rb +68 -0
- data/lib/mask32.rb +99 -0
- data/lib/netaddr.rb +104 -20
- data/lib/util.rb +310 -0
- data/test/eui48_test.rb +30 -0
- data/test/eui64_test.rb +32 -0
- data/test/examples.rb +137 -0
- data/test/ipv4_test.rb +54 -0
- data/test/ipv4net_test.rb +166 -0
- data/test/ipv6_test.rb +90 -0
- data/test/ipv6net_test.rb +146 -0
- data/test/mask128_test.rb +45 -0
- data/test/mask32_test.rb +51 -0
- data/test/netaddr_test.rb +127 -0
- data/test/run_all.rb +10 -0
- metadata +28 -22
- data/Errors +0 -7
- data/changelog +0 -52
- data/lib/cidr.rb +0 -2014
- data/lib/cidr_shortcuts.rb +0 -401
- data/lib/eui.rb +0 -402
- data/lib/ip_math.rb +0 -227
- data/lib/methods.rb +0 -1013
- data/lib/tree.rb +0 -816
- data/lib/validation_shortcuts.rb +0 -201
- data/license +0 -13
- data/test/cidr_test.rb +0 -545
- data/test/eui_test.rb +0 -101
- data/test/methods_test.rb +0 -331
- data/test/tree_test.rb +0 -347
data/lib/tree.rb
DELETED
@@ -1,816 +0,0 @@
|
|
1
|
-
module NetAddr
|
2
|
-
|
3
|
-
#=Tree
|
4
|
-
#
|
5
|
-
#A class & series of methods for creating and manipulating IP-based
|
6
|
-
#heirarchical trees. Both IPv4 and IPv6 are supported.
|
7
|
-
#
|
8
|
-
#A sample tree would look like:
|
9
|
-
# 192.168.1.0/24
|
10
|
-
# 192.168.1.0/26
|
11
|
-
# 192.168.1.0/27
|
12
|
-
# 192.168.1.0/28
|
13
|
-
# 192.168.1.16/29
|
14
|
-
# 192.168.1.16/30
|
15
|
-
# 192.168.1.24/30
|
16
|
-
# 192.168.1.25/32
|
17
|
-
# 192.168.1.28/30
|
18
|
-
# 192.168.1.32/27
|
19
|
-
# 192.168.1.64/26
|
20
|
-
# 192.168.1.64/27
|
21
|
-
# 192.168.1.128/26
|
22
|
-
# 192.168.1.192/26
|
23
|
-
#
|
24
|
-
class Tree
|
25
|
-
|
26
|
-
#===Synopsis
|
27
|
-
#Create a new Tree object.
|
28
|
-
#
|
29
|
-
# Example:
|
30
|
-
# NetAddr::Tree.new()
|
31
|
-
#
|
32
|
-
#===Arguments:
|
33
|
-
#* none
|
34
|
-
#
|
35
|
-
def initialize()
|
36
|
-
# root of our ordered IP tree
|
37
|
-
@v4_root = NetAddr::CIDRv4.new(0,0,{:Subnets => []})
|
38
|
-
@v6_root = NetAddr::CIDRv6.new(0,0,{:Subnets => []})
|
39
|
-
end
|
40
|
-
|
41
|
-
#===Synopsis
|
42
|
-
# Add a CIDR address or NetAddr::CIDR object to the tree.
|
43
|
-
# Example:
|
44
|
-
# tree.add!('192.168.1.0/24')
|
45
|
-
# cidr = NetAddr::CIDR.create('192.168.1.0/24', :Tag => {:title => 'test net'}
|
46
|
-
# tree.add!(cidr)
|
47
|
-
#
|
48
|
-
#===Arguments:
|
49
|
-
#* String or NetAddr::CIDR object
|
50
|
-
#
|
51
|
-
#===Returns:
|
52
|
-
#* nil
|
53
|
-
#
|
54
|
-
def add!(new)
|
55
|
-
# validate object
|
56
|
-
if ( !new.kind_of?(NetAddr::CIDR) )
|
57
|
-
begin
|
58
|
-
cidr = NetAddr::CIDR.create(new)
|
59
|
-
rescue Exception => error
|
60
|
-
raise ArgumentError, "Provided argument raised the following " +
|
61
|
-
"errors: #{error}"
|
62
|
-
end
|
63
|
-
else
|
64
|
-
cidr = new.dup
|
65
|
-
end
|
66
|
-
|
67
|
-
cidr.tag[:Subnets] = []
|
68
|
-
add_to_tree(cidr)
|
69
|
-
|
70
|
-
return(nil)
|
71
|
-
end
|
72
|
-
|
73
|
-
#===Synopsis
|
74
|
-
# Returns all the ancestors of the provided CIDR addresses.
|
75
|
-
#
|
76
|
-
# Example:
|
77
|
-
# tree.ancestors('192.168.1.0/27')
|
78
|
-
#
|
79
|
-
#===Arguments:
|
80
|
-
#* String or NetAddr::CIDR object
|
81
|
-
#
|
82
|
-
#===Returns:
|
83
|
-
#* Array of NetAddr::CIDR objects
|
84
|
-
#
|
85
|
-
def ancestors(cidr)
|
86
|
-
# validate object
|
87
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
88
|
-
begin
|
89
|
-
cidr = NetAddr::CIDR.create(cidr)
|
90
|
-
rescue Exception => error
|
91
|
-
raise ArgumentError, "Provided argument raised the following " +
|
92
|
-
"errors: #{error}"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
list = []
|
97
|
-
parent = find_parent(cidr)
|
98
|
-
until (!parent.tag[:Parent])
|
99
|
-
list.push( NetAddr.cidr_build(parent.version, parent.to_i(:network), parent.to_i(:netmask)) )
|
100
|
-
parent = parent.tag[:Parent]
|
101
|
-
end
|
102
|
-
|
103
|
-
return(list)
|
104
|
-
end
|
105
|
-
|
106
|
-
#===Synopsis
|
107
|
-
# Returns all the immediate children of the provided CIDR addresses.
|
108
|
-
#
|
109
|
-
# Example:
|
110
|
-
# tree.children('192.168.1.0/24')
|
111
|
-
#
|
112
|
-
#===Arguments:
|
113
|
-
#* String or NetAddr::CIDR object
|
114
|
-
#
|
115
|
-
#===Returns:
|
116
|
-
#* Array of NetAddr::CIDR objects
|
117
|
-
#
|
118
|
-
def children(cidr)
|
119
|
-
# validate object
|
120
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
121
|
-
begin
|
122
|
-
cidr = NetAddr::CIDR.create(cidr)
|
123
|
-
rescue Exception => error
|
124
|
-
raise ArgumentError, "Provided argument raised the following " +
|
125
|
-
"errors: #{error}"
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
list = []
|
130
|
-
me = find_me(cidr)
|
131
|
-
if (me)
|
132
|
-
me.tag[:Subnets].each do |child|
|
133
|
-
list.push( NetAddr.cidr_build(child.version, child.to_i(:network), child.to_i(:netmask)) )
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
return(list)
|
138
|
-
end
|
139
|
-
|
140
|
-
#===Synopsis
|
141
|
-
# Return all descendants of the provided CIDR address.
|
142
|
-
#
|
143
|
-
# Example:
|
144
|
-
# tree.descendants('192.168.1.0/24')
|
145
|
-
#
|
146
|
-
#===Arguments:
|
147
|
-
#* String or NetAddr::CIDR object
|
148
|
-
#
|
149
|
-
#===Returns:
|
150
|
-
#* Array of NetAddr::CIDR objects
|
151
|
-
#
|
152
|
-
def descendants(cidr)
|
153
|
-
list = []
|
154
|
-
|
155
|
-
# validate object
|
156
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
157
|
-
begin
|
158
|
-
cidr = NetAddr::CIDR.create(cidr)
|
159
|
-
rescue Exception => error
|
160
|
-
raise ArgumentError, "Provided argument raised the following " +
|
161
|
-
"errors: #{error}"
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
me = find_me(cidr)
|
166
|
-
if (me)
|
167
|
-
dump_children(me).each do |x|
|
168
|
-
child = x[:CIDR]
|
169
|
-
list.push( NetAddr.cidr_build(child.version, child.to_i(:network), child.to_i(:netmask)) )
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
return(list)
|
174
|
-
end
|
175
|
-
|
176
|
-
#===Synopsis
|
177
|
-
# Remove the provided CIDR address from the tree.
|
178
|
-
#
|
179
|
-
# Example:
|
180
|
-
# tree.remove!('192.168.1.0/24')
|
181
|
-
#
|
182
|
-
#===Arguments:
|
183
|
-
#* String or NetAddr::CIDR object
|
184
|
-
#
|
185
|
-
#===Returns:
|
186
|
-
#* true on success or false on fail
|
187
|
-
#
|
188
|
-
def delete!(cidr)
|
189
|
-
removed = false
|
190
|
-
|
191
|
-
# validate object
|
192
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
193
|
-
begin
|
194
|
-
cidr = NetAddr::CIDR.create(cidr)
|
195
|
-
rescue Exception => error
|
196
|
-
raise ArgumentError, "Provided argument raised the following " +
|
197
|
-
"errors: #{error}"
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
# find matching
|
202
|
-
me = find_me(cidr)
|
203
|
-
|
204
|
-
# remove
|
205
|
-
if (me)
|
206
|
-
parent = me.tag[:Parent]
|
207
|
-
children = me.tag[:Subnets]
|
208
|
-
parent.tag[:Subnets].delete(me)
|
209
|
-
children.each {|x| add_to_parent(x,parent)}
|
210
|
-
removed = true
|
211
|
-
end
|
212
|
-
|
213
|
-
return(removed)
|
214
|
-
end
|
215
|
-
|
216
|
-
#===Synopsis
|
217
|
-
# Dump the contents of this tree.
|
218
|
-
#
|
219
|
-
# Example:
|
220
|
-
# tree.dump()
|
221
|
-
#
|
222
|
-
#===Arguments:
|
223
|
-
#* none
|
224
|
-
#
|
225
|
-
#===Returns:
|
226
|
-
#* ordered array of hashes with the following fields:
|
227
|
-
# :CIDR => NetAddr::CIDR object
|
228
|
-
# :Depth => (depth level in tree)
|
229
|
-
#
|
230
|
-
def dump()
|
231
|
-
list = dump_children(@v4_root)
|
232
|
-
list.concat( dump_children(@v6_root) )
|
233
|
-
list.each {|x| x[:CIDR] = NetAddr.cidr_build(x[:CIDR].version, x[:CIDR].to_i(:network), x[:CIDR].to_i(:netmask)) }
|
234
|
-
return(list)
|
235
|
-
end
|
236
|
-
|
237
|
-
#===Synopsis
|
238
|
-
# Has a CIDR address already been added to the tree?
|
239
|
-
#
|
240
|
-
# Example:
|
241
|
-
# tree.exists?('192.168.1.0/24')
|
242
|
-
#
|
243
|
-
#===Arguments:
|
244
|
-
#* String or NetAddr::CIDR object
|
245
|
-
#
|
246
|
-
#===Returns:
|
247
|
-
#* true or false
|
248
|
-
#
|
249
|
-
def exists?(cidr)
|
250
|
-
found = false
|
251
|
-
|
252
|
-
# validate object
|
253
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
254
|
-
begin
|
255
|
-
cidr = NetAddr::CIDR.create(cidr)
|
256
|
-
rescue Exception => error
|
257
|
-
raise ArgumentError, "Provided argument raised the following " +
|
258
|
-
"errors: #{error}"
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
found = true if (find_me(cidr))
|
263
|
-
return(found)
|
264
|
-
end
|
265
|
-
|
266
|
-
#===Synopsis
|
267
|
-
# Fill in the missing subnets of a particular CIDR.
|
268
|
-
#
|
269
|
-
# Example:
|
270
|
-
# tree.fill_in!('192.168.1.0/24')
|
271
|
-
#
|
272
|
-
#===Arguments:
|
273
|
-
#* String or NetAddr::CIDR object
|
274
|
-
#
|
275
|
-
#===Returns:
|
276
|
-
#* true or false
|
277
|
-
#
|
278
|
-
def fill_in!(cidr)
|
279
|
-
filled = false
|
280
|
-
|
281
|
-
# validate object
|
282
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
283
|
-
begin
|
284
|
-
cidr = NetAddr::CIDR.create(cidr)
|
285
|
-
rescue Exception => error
|
286
|
-
raise ArgumentError, "Provided argument raised the following " +
|
287
|
-
"errors: #{error}"
|
288
|
-
end
|
289
|
-
end
|
290
|
-
|
291
|
-
me = find_me(cidr)
|
292
|
-
if (me && me.tag[:Subnets].length != 0)
|
293
|
-
me.tag[:Subnets] = NetAddr.cidr_fill_in(me, me.tag[:Subnets])
|
294
|
-
me.tag[:Subnets].each do |subnet|
|
295
|
-
subnet.tag[:Subnets] = [] if (!subnet.tag.has_key?(:Subnets))
|
296
|
-
end
|
297
|
-
filled = true
|
298
|
-
end
|
299
|
-
return(filled)
|
300
|
-
end
|
301
|
-
|
302
|
-
#===Synopsis
|
303
|
-
# Find and return a CIDR from within the tree.
|
304
|
-
#
|
305
|
-
# Example:
|
306
|
-
# tree.find('192.168.1.0/24')
|
307
|
-
#
|
308
|
-
#===Arguments:
|
309
|
-
#* String or NetAddr::CIDR object
|
310
|
-
#
|
311
|
-
#===Returns:
|
312
|
-
#* NetAddr::CIDR object, or nil
|
313
|
-
#
|
314
|
-
def find(cidr)
|
315
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
316
|
-
begin
|
317
|
-
cidr = NetAddr::CIDR.create(cidr)
|
318
|
-
rescue Exception => error
|
319
|
-
raise ArgumentError, "Provided argument raised the following " +
|
320
|
-
"errors: #{error}"
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
me = find_me(cidr)
|
325
|
-
if (me)
|
326
|
-
me = NetAddr.cidr_build(me.version, me.to_i(:network), me.to_i(:netmask))
|
327
|
-
end
|
328
|
-
|
329
|
-
return(me)
|
330
|
-
end
|
331
|
-
|
332
|
-
#===Synopsis
|
333
|
-
# Find subnets that are of at least size X. Only subnets that are not themselves
|
334
|
-
# subnetted will be returned. :Subnet takes precedence over :IPCount
|
335
|
-
#
|
336
|
-
# Example:
|
337
|
-
# tree.find_space(:IPCount => 16)
|
338
|
-
#
|
339
|
-
#===Arguments:
|
340
|
-
#* Minimum subnet size in bits, or a Hash with the following keys:
|
341
|
-
# :Subnet - minimum subnet size in bits for returned subnets
|
342
|
-
# :IPCount - minimum IP count per subnet required for returned subnets
|
343
|
-
# :Version - restrict results to IPvX
|
344
|
-
#
|
345
|
-
#===Returns:
|
346
|
-
#* Array of NetAddr::CIDR objects
|
347
|
-
#
|
348
|
-
def find_space(options)
|
349
|
-
known_args = [:Subnet, :IPCount, :Version]
|
350
|
-
version = nil
|
351
|
-
if (options.kind_of? Integer)
|
352
|
-
bits4 = options
|
353
|
-
bits6 = options
|
354
|
-
elsif (options.kind_of? Hash)
|
355
|
-
NetAddr.validate_args(options.keys,known_args)
|
356
|
-
if (options.has_key?(:Version))
|
357
|
-
version = options[:Version]
|
358
|
-
raise "IP version should be 4 or 6, but was #{version}." if (version != 4 && version !=6)
|
359
|
-
end
|
360
|
-
|
361
|
-
if (options.has_key?(:Subnet))
|
362
|
-
bits4 = options[:Subnet]
|
363
|
-
bits6 = options[:Subnet]
|
364
|
-
elsif(options.has_key?(:IPCount))
|
365
|
-
bits4 = NetAddr.minimum_size(options[:IPCount], :Version => 4)
|
366
|
-
bits6 = NetAddr.minimum_size(options[:IPCount], :Version => 6)
|
367
|
-
else
|
368
|
-
raise "Missing arguments: :Subnet/:IPCount"
|
369
|
-
end
|
370
|
-
else
|
371
|
-
raise "Integer or Hash expected, but #{options.class} provided."
|
372
|
-
end
|
373
|
-
|
374
|
-
list = []
|
375
|
-
if (!version || version == 4)
|
376
|
-
dump_children(@v4_root).each do |entry|
|
377
|
-
cidr = entry[:CIDR]
|
378
|
-
if ( (cidr.tag[:Subnets].length == 0) && (cidr.bits <= bits4) )
|
379
|
-
list.push(cidr)
|
380
|
-
end
|
381
|
-
end
|
382
|
-
end
|
383
|
-
|
384
|
-
if (!version || version == 6)
|
385
|
-
dump_children(@v6_root).each do |entry|
|
386
|
-
cidr = entry[:CIDR]
|
387
|
-
if ( (cidr.tag[:Subnets].length == 0) && (cidr.bits <= bits6) )
|
388
|
-
list.push(cidr)
|
389
|
-
end
|
390
|
-
end
|
391
|
-
end
|
392
|
-
|
393
|
-
new_list = []
|
394
|
-
list.each {|x| new_list.push( NetAddr.cidr_build(x.version, x.to_i(:network), x.to_i(:netmask)) )}
|
395
|
-
|
396
|
-
return(new_list)
|
397
|
-
end
|
398
|
-
|
399
|
-
#===Synopsis
|
400
|
-
#Find the longest matching branch of our tree to which a
|
401
|
-
#CIDR address belongs. Useful for performing 'routing table' style lookups.
|
402
|
-
#
|
403
|
-
# Example:
|
404
|
-
# tree.longest_match('192.168.1.1')
|
405
|
-
#
|
406
|
-
#===Arguments:
|
407
|
-
#* String or NetAddr::CIDR object
|
408
|
-
#
|
409
|
-
#===Returns:
|
410
|
-
#* NetAddr::CIDR object
|
411
|
-
#
|
412
|
-
def longest_match(cidr)
|
413
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
414
|
-
begin
|
415
|
-
cidr = NetAddr::CIDR.create(cidr)
|
416
|
-
rescue Exception => error
|
417
|
-
raise ArgumentError, "Provided argument raised the following " +
|
418
|
-
"errors: #{error}"
|
419
|
-
end
|
420
|
-
end
|
421
|
-
|
422
|
-
found = find_me(cidr)
|
423
|
-
found = find_parent(cidr) if !found
|
424
|
-
|
425
|
-
return( NetAddr.cidr_build(found.version, found.to_i(:network), found.to_i(:netmask)) )
|
426
|
-
end
|
427
|
-
|
428
|
-
#===Synopsis
|
429
|
-
# Remove all subnets of the provided CIDR address.
|
430
|
-
#
|
431
|
-
# Example:
|
432
|
-
# tree.prune!('192.168.1.0/24')
|
433
|
-
#
|
434
|
-
#===Arguments:
|
435
|
-
#* String or NetAddr::CIDR object
|
436
|
-
#
|
437
|
-
#===Returns:
|
438
|
-
#* true on success or false on fail
|
439
|
-
#
|
440
|
-
def prune!(cidr)
|
441
|
-
pruned = false
|
442
|
-
|
443
|
-
# validate object
|
444
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
445
|
-
begin
|
446
|
-
cidr = NetAddr::CIDR.create(cidr)
|
447
|
-
rescue Exception => error
|
448
|
-
raise ArgumentError, "Provided argument raised the following " +
|
449
|
-
"errors: #{error}"
|
450
|
-
end
|
451
|
-
end
|
452
|
-
|
453
|
-
me = find_me(cidr)
|
454
|
-
|
455
|
-
if (me)
|
456
|
-
me.tag[:Subnets].clear
|
457
|
-
pruned = true
|
458
|
-
end
|
459
|
-
|
460
|
-
return(pruned)
|
461
|
-
end
|
462
|
-
|
463
|
-
#===Synopsis
|
464
|
-
# Remove the provided CIDR address, and all of its subnets from the tree.
|
465
|
-
#
|
466
|
-
# Example:
|
467
|
-
# tree.remove!('192.168.1.0/24')
|
468
|
-
#
|
469
|
-
#===Arguments:
|
470
|
-
#* String or NetAddr::CIDR object
|
471
|
-
#
|
472
|
-
#===Returns:
|
473
|
-
#* true on success or false on fail
|
474
|
-
#
|
475
|
-
def remove!(cidr)
|
476
|
-
removed = false
|
477
|
-
found = nil
|
478
|
-
|
479
|
-
# validate object
|
480
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
481
|
-
begin
|
482
|
-
cidr = NetAddr::CIDR.create(cidr)
|
483
|
-
rescue Exception => error
|
484
|
-
raise ArgumentError, "Provided argument raised the following " +
|
485
|
-
"errors: #{error}"
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
|
-
me = find_me(cidr)
|
490
|
-
|
491
|
-
if (me)
|
492
|
-
parent = me.tag[:Parent]
|
493
|
-
parent.tag[:Subnets].delete(me)
|
494
|
-
removed = true
|
495
|
-
end
|
496
|
-
|
497
|
-
return(removed)
|
498
|
-
end
|
499
|
-
|
500
|
-
#===Synopsis
|
501
|
-
# Resize the provided CIDR address.
|
502
|
-
#
|
503
|
-
# Example:
|
504
|
-
# tree.resize!('192.168.1.0/24', 23)
|
505
|
-
#
|
506
|
-
#===Arguments:
|
507
|
-
#* CIDR address as a String or an NetAddr::CIDR object
|
508
|
-
#* Integer representing the bits of the new netmask
|
509
|
-
#
|
510
|
-
#===Returns:
|
511
|
-
#* true on success or false on fail
|
512
|
-
#
|
513
|
-
def resize!(cidr,bits)
|
514
|
-
resized = false
|
515
|
-
|
516
|
-
# validate cidr
|
517
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
518
|
-
begin
|
519
|
-
cidr = NetAddr::CIDR.create(cidr)
|
520
|
-
rescue Exception => error
|
521
|
-
raise ArgumentError, "Provided argument raised the following " +
|
522
|
-
"errors: #{error}"
|
523
|
-
end
|
524
|
-
end
|
525
|
-
|
526
|
-
me = find_me(cidr)
|
527
|
-
|
528
|
-
if (me)
|
529
|
-
new = me.resize(bits)
|
530
|
-
delete!(me)
|
531
|
-
add!(new)
|
532
|
-
resized = true
|
533
|
-
end
|
534
|
-
|
535
|
-
return(resized)
|
536
|
-
end
|
537
|
-
|
538
|
-
#===Synopsis
|
539
|
-
# Returns the root of the provided CIDR address.
|
540
|
-
#
|
541
|
-
# Example:
|
542
|
-
# tree.root('192.168.1.32/27')
|
543
|
-
#
|
544
|
-
#===Arguments:
|
545
|
-
#* String or NetAddr::CIDR object
|
546
|
-
#
|
547
|
-
#===Returns:
|
548
|
-
#* NetAddr::CIDR object
|
549
|
-
#
|
550
|
-
def root(cidr)
|
551
|
-
# validate object
|
552
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
553
|
-
begin
|
554
|
-
cidr = NetAddr::CIDR.create(cidr)
|
555
|
-
rescue Exception => error
|
556
|
-
raise ArgumentError, "Provided argument raised the following " +
|
557
|
-
"errors: #{error}"
|
558
|
-
end
|
559
|
-
end
|
560
|
-
|
561
|
-
parent = find_parent(cidr)
|
562
|
-
if (parent.tag.has_key?(:Parent)) # if parent is not 0/0
|
563
|
-
while(1)
|
564
|
-
grandparent = parent.tag[:Parent]
|
565
|
-
break if (!grandparent.tag.has_key?(:Parent)) # if grandparent is 0/0
|
566
|
-
parent = grandparent
|
567
|
-
end
|
568
|
-
end
|
569
|
-
|
570
|
-
return( NetAddr.cidr_build(parent.version, parent.to_i(:network), parent.to_i(:netmask)) )
|
571
|
-
end
|
572
|
-
|
573
|
-
#===Synopsis
|
574
|
-
# Print the tree as a formatted string.
|
575
|
-
#
|
576
|
-
# Example:
|
577
|
-
# tree.show()
|
578
|
-
#
|
579
|
-
#===Arguments:
|
580
|
-
#* none
|
581
|
-
#
|
582
|
-
#===Returns:
|
583
|
-
#* String
|
584
|
-
#
|
585
|
-
def show()
|
586
|
-
printed = "IPv4 Tree\n---------\n"
|
587
|
-
list4 = dump_children(@v4_root)
|
588
|
-
list6 = dump_children(@v6_root)
|
589
|
-
|
590
|
-
list4.each do |entry|
|
591
|
-
cidr = entry[:CIDR]
|
592
|
-
depth = entry[:Depth]
|
593
|
-
|
594
|
-
if (depth == 0)
|
595
|
-
indent = ""
|
596
|
-
else
|
597
|
-
indent = " " * (depth*3)
|
598
|
-
end
|
599
|
-
|
600
|
-
printed << "#{indent}#{cidr.desc}\n"
|
601
|
-
end
|
602
|
-
|
603
|
-
printed << "\n\nIPv6 Tree\n---------\n" if (list6.length != 0)
|
604
|
-
|
605
|
-
list6.each do |entry|
|
606
|
-
cidr = entry[:CIDR]
|
607
|
-
depth = entry[:Depth]
|
608
|
-
|
609
|
-
if (depth == 0)
|
610
|
-
indent = ""
|
611
|
-
else
|
612
|
-
indent = " " * (depth*3)
|
613
|
-
end
|
614
|
-
|
615
|
-
printed << "#{indent}#{cidr.desc(:Short => true)}\n"
|
616
|
-
end
|
617
|
-
|
618
|
-
return(printed)
|
619
|
-
end
|
620
|
-
|
621
|
-
#===Synopsis
|
622
|
-
# Return list of the sibling CIDRs of the provided CIDR address.
|
623
|
-
#
|
624
|
-
# Example:
|
625
|
-
# tree.siblings('192.168.1.0/27')
|
626
|
-
#
|
627
|
-
#===Arguments:
|
628
|
-
#* String or NetAddr::CIDR object
|
629
|
-
#
|
630
|
-
#===Returns:
|
631
|
-
#* Array of NetAddr::CIDR objects
|
632
|
-
#
|
633
|
-
def siblings(cidr)
|
634
|
-
# validate object
|
635
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
636
|
-
begin
|
637
|
-
cidr = NetAddr::CIDR.create(cidr)
|
638
|
-
rescue Exception => error
|
639
|
-
raise ArgumentError, "Provided argument raised the following " +
|
640
|
-
"errors: #{error}"
|
641
|
-
end
|
642
|
-
end
|
643
|
-
|
644
|
-
list = []
|
645
|
-
find_parent(cidr).tag[:Subnets].each do |entry|
|
646
|
-
if (!cidr.cmp(entry))
|
647
|
-
list.push( NetAddr.cidr_build(entry.version, entry.to_i(:network), entry.to_i(:netmask)) )
|
648
|
-
end
|
649
|
-
end
|
650
|
-
|
651
|
-
return(list)
|
652
|
-
end
|
653
|
-
|
654
|
-
#===Synopsis
|
655
|
-
# Summarize all subnets of the provided CIDR address. The subnets will be
|
656
|
-
# placed under the new summary address within the tree.
|
657
|
-
#
|
658
|
-
# Example:
|
659
|
-
# tree.summarize_subnets!('192.168.1.0/24')
|
660
|
-
#
|
661
|
-
#===Arguments:
|
662
|
-
#* String or NetAddr::CIDR object
|
663
|
-
#
|
664
|
-
#===Returns:
|
665
|
-
#* true on success or false on fail
|
666
|
-
#
|
667
|
-
def summarize_subnets!(cidr)
|
668
|
-
merged = false
|
669
|
-
|
670
|
-
# validate object
|
671
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
672
|
-
begin
|
673
|
-
cidr = NetAddr::CIDR.create(cidr)
|
674
|
-
rescue Exception => error
|
675
|
-
raise ArgumentError, "Provided argument raised the following " +
|
676
|
-
"errors: #{error}"
|
677
|
-
end
|
678
|
-
end
|
679
|
-
|
680
|
-
me = find_me(cidr)
|
681
|
-
|
682
|
-
if (me)
|
683
|
-
merged = NetAddr.cidr_summarize(me.tag[:Subnets])
|
684
|
-
me.tag[:Subnets] = merged
|
685
|
-
merged = true
|
686
|
-
end
|
687
|
-
|
688
|
-
return(merged)
|
689
|
-
end
|
690
|
-
alias :merge_subnets! :summarize_subnets!
|
691
|
-
|
692
|
-
#===Synopsis
|
693
|
-
# Return list of the top-level supernets of this tree.
|
694
|
-
#
|
695
|
-
# Example:
|
696
|
-
# tree.supernets()
|
697
|
-
#
|
698
|
-
#===Arguments:
|
699
|
-
#* none
|
700
|
-
#
|
701
|
-
#===Returns:
|
702
|
-
#* Array of NetAddr::CIDR objects
|
703
|
-
#
|
704
|
-
def supernets()
|
705
|
-
supernets = []
|
706
|
-
@v4_root.tag[:Subnets].each {|x| supernets.push( NetAddr.cidr_build(x.version, x.to_i(:network), x.to_i(:netmask)) )}
|
707
|
-
@v6_root.tag[:Subnets].each {|x| supernets.push( NetAddr.cidr_build(x.version, x.to_i(:network), x.to_i(:netmask)) )}
|
708
|
-
return (supernets)
|
709
|
-
end
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
private
|
715
|
-
|
716
|
-
# Add NetStruct object to an array of NetStruct's
|
717
|
-
#
|
718
|
-
def add_to_parent(cidr, parent)
|
719
|
-
duplicate = false
|
720
|
-
duplicate = true if (NetAddr.cidr_find_in_list(cidr,parent.tag[:Subnets]).kind_of?(Integer))
|
721
|
-
|
722
|
-
if (!duplicate)
|
723
|
-
# check parent for subnets of cidr
|
724
|
-
new_parent_subs = []
|
725
|
-
parent.tag[:Subnets].length.times do
|
726
|
-
old_cidr = parent.tag[:Subnets].shift
|
727
|
-
cmp = NetAddr.cidr_compare(cidr, old_cidr)
|
728
|
-
if (cmp && cmp == 1)
|
729
|
-
old_cidr.tag[:Parent] = cidr
|
730
|
-
cidr.tag[:Subnets].push(old_cidr)
|
731
|
-
else
|
732
|
-
new_parent_subs.push(old_cidr)
|
733
|
-
end
|
734
|
-
end
|
735
|
-
|
736
|
-
cidr.tag[:Parent] = parent
|
737
|
-
parent.tag[:Subnets] = new_parent_subs
|
738
|
-
parent.tag[:Subnets].push(cidr)
|
739
|
-
parent.tag[:Subnets] = NetAddr.cidr_sort(parent.tag[:Subnets])
|
740
|
-
end
|
741
|
-
|
742
|
-
return(nil)
|
743
|
-
end
|
744
|
-
|
745
|
-
# Add CIDR to a Tree
|
746
|
-
#
|
747
|
-
def add_to_tree(cidr,root=nil)
|
748
|
-
parent = find_parent(cidr)
|
749
|
-
add_to_parent(cidr,parent)
|
750
|
-
|
751
|
-
return(nil)
|
752
|
-
end
|
753
|
-
|
754
|
-
# Dump contents of an Array of NetStruct objects
|
755
|
-
#
|
756
|
-
def dump_children(parent,depth=0)
|
757
|
-
list = []
|
758
|
-
|
759
|
-
parent.tag[:Subnets].each do |entry|
|
760
|
-
list.push({:CIDR => entry, :Depth => depth})
|
761
|
-
|
762
|
-
if (entry.tag[:Subnets].length > 0)
|
763
|
-
list.concat( dump_children(entry, (depth+1) ) )
|
764
|
-
end
|
765
|
-
end
|
766
|
-
|
767
|
-
return(list)
|
768
|
-
end
|
769
|
-
|
770
|
-
# Find the NetStruct to which a cidr belongs.
|
771
|
-
#
|
772
|
-
def find_me(cidr)
|
773
|
-
me = nil
|
774
|
-
root = nil
|
775
|
-
if (cidr.version == 4)
|
776
|
-
root = @v4_root
|
777
|
-
else
|
778
|
-
root = @v6_root
|
779
|
-
end
|
780
|
-
|
781
|
-
# find matching
|
782
|
-
parent = find_parent(cidr,root)
|
783
|
-
index = NetAddr.cidr_find_in_list(cidr,parent.tag[:Subnets])
|
784
|
-
me = parent.tag[:Subnets][index] if (index.kind_of?(Integer))
|
785
|
-
|
786
|
-
return(me)
|
787
|
-
end
|
788
|
-
|
789
|
-
# Find the parent NetStruct to which a child NetStruct belongs.
|
790
|
-
#
|
791
|
-
def find_parent(cidr,parent=nil)
|
792
|
-
if (!parent)
|
793
|
-
if (cidr.version == 4)
|
794
|
-
parent = @v4_root
|
795
|
-
else
|
796
|
-
parent = @v6_root
|
797
|
-
end
|
798
|
-
end
|
799
|
-
bit_diff = cidr.bits - parent.bits
|
800
|
-
|
801
|
-
# if bit_diff greater than 1 bit then check if one of the children is the actual parent.
|
802
|
-
if (bit_diff > 1 && parent.tag[:Subnets].length != 0)
|
803
|
-
list = parent.tag[:Subnets]
|
804
|
-
found = NetAddr.cidr_find_in_list(cidr,list)
|
805
|
-
if (found.kind_of?(NetAddr::CIDR))
|
806
|
-
parent = find_parent(cidr,found)
|
807
|
-
end
|
808
|
-
end
|
809
|
-
|
810
|
-
return(parent)
|
811
|
-
end
|
812
|
-
|
813
|
-
end # class Tree
|
814
|
-
|
815
|
-
end # module NetAddr
|
816
|
-
__END__
|