netaddr 1.5.1 → 2.0.5

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