netaddr 1.1.0 → 1.2.0

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.

data/lib/net_addr.rb CHANGED
@@ -4,7 +4,9 @@
4
4
  Licensed under the same terms as Ruby, No Warranty is provided.
5
5
  =end
6
6
 
7
-
7
+ require File.join(File.dirname(__FILE__), 'validation_shortcuts.rb')
8
+ require File.join(File.dirname(__FILE__), 'ip_math.rb')
9
+ require File.join(File.dirname(__FILE__), 'cidr_shortcuts.rb')
8
10
  require File.join(File.dirname(__FILE__), 'methods.rb')
9
11
  require File.join(File.dirname(__FILE__), 'cidr.rb')
10
12
  require File.join(File.dirname(__FILE__), 'tree.rb')
data/lib/tree.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  =begin rdoc
2
2
  Copyleft (c) 2006 Dustin Spinhirne (www.spinhirne.com)
3
-
3
+
4
4
  Licensed under the same terms as Ruby, No Warranty is provided.
5
5
  =end
6
6
 
@@ -43,7 +43,8 @@ class Tree
43
43
  #
44
44
  def initialize()
45
45
  # root of our ordered IP tree
46
- @root = NetStruct.new(nil, nil, [])
46
+ @v4_root = NetAddr::CIDRv4.new(0,0,{:Subnets => []})
47
+ @v6_root = NetAddr::CIDRv6.new(0,0,{:Subnets => []})
47
48
  end
48
49
 
49
50
  #==============================================================================#
@@ -64,8 +65,6 @@ class Tree
64
65
  #* nil
65
66
  #
66
67
  def add!(new)
67
- duplicate = false
68
-
69
68
  # validate object
70
69
  if ( !new.kind_of?(NetAddr::CIDR) )
71
70
  begin
@@ -78,34 +77,8 @@ class Tree
78
77
  cidr = new.dup
79
78
  end
80
79
 
81
- version = cidr.version
82
- new_entry = NetStruct.new(cidr, nil, [])
83
-
84
- # find cidr's parent
85
- new_entry.parent = find_parent(cidr, @root)
86
-
87
- # check parent for subnets of cidr
88
- new_entry.parent.children.each do |old_entry|
89
- if (old_entry.cidr.version == version)
90
- comp = cidr.cmp(old_entry.cidr)
91
- if (comp && comp == 1)
92
- old_entry.parent = new_entry
93
- new_entry.children.push(old_entry)
94
- elsif (comp && comp == 0)
95
- duplicate = true
96
- break
97
- end
98
- end
99
- end
100
-
101
- if (!duplicate)
102
- new_entry.children.each do |old_entry|
103
- new_entry.parent.children.delete(old_entry)
104
- end
105
-
106
- # add new object as an ordered entry to parent.children
107
- add_to_parent(new_entry,new_entry.parent)
108
- end
80
+ cidr.tag[:Subnets] = []
81
+ add_to_tree(cidr)
109
82
 
110
83
  return(nil)
111
84
  end
@@ -135,13 +108,12 @@ class Tree
135
108
  "errors: #{error}"
136
109
  end
137
110
  end
138
-
111
+
139
112
  list = []
140
- parent = find_parent(cidr,@root)
141
-
142
- until (parent == @root)
143
- list.push(parent.cidr)
144
- parent = parent.parent
113
+ parent = find_parent(cidr)
114
+ until (!parent.tag[:Parent])
115
+ list.push(parent)
116
+ parent = parent.tag[:Parent]
145
117
  end
146
118
 
147
119
  return(list)
@@ -174,9 +146,8 @@ class Tree
174
146
  end
175
147
 
176
148
  list = []
177
- find_me(cidr).children.each do |child|
178
- list.push(child.cidr)
179
- end
149
+ me = find_me(cidr)
150
+ me.tag[:Subnets].each {|child| list.push(child) } if (me)
180
151
 
181
152
  return(list)
182
153
  end
@@ -198,7 +169,7 @@ class Tree
198
169
  #
199
170
  def descendants(cidr)
200
171
  list = []
201
-
172
+
202
173
  # validate object
203
174
  if ( !cidr.kind_of?(NetAddr::CIDR) )
204
175
  begin
@@ -209,8 +180,8 @@ class Tree
209
180
  end
210
181
  end
211
182
 
212
- me = find_me(cidr)
213
- dump_children(me).each {|x| list.push(x[:NetStruct].cidr)} if (me)
183
+ me = find_me(cidr)
184
+ dump_children(me).each {|x| list.push(x[:CIDR])} if (me)
214
185
 
215
186
  return(list)
216
187
  end
@@ -232,7 +203,7 @@ class Tree
232
203
  #
233
204
  def delete!(cidr)
234
205
  removed = false
235
-
206
+
236
207
  # validate object
237
208
  if ( !cidr.kind_of?(NetAddr::CIDR) )
238
209
  begin
@@ -245,12 +216,12 @@ class Tree
245
216
 
246
217
  # find matching
247
218
  me = find_me(cidr)
248
-
219
+
249
220
  # remove
250
221
  if (me)
251
- parent = me.parent
252
- children = me.children
253
- parent.children.delete(me)
222
+ parent = me.tag[:Parent]
223
+ children = me.tag[:Subnets]
224
+ parent.tag[:Subnets].delete(me)
254
225
  children.each {|x| add_to_parent(x,parent)}
255
226
  removed = true
256
227
  end
@@ -276,15 +247,8 @@ class Tree
276
247
  # :Depth => (depth level in tree)
277
248
  #
278
249
  def dump()
279
- list = []
280
- dumped = dump_children(@root)
281
-
282
- dumped.each do |entry|
283
- depth = entry[:Depth]
284
- net_struct = entry[:NetStruct]
285
- list.push({:Depth => depth, :CIDR => net_struct.cidr})
286
- end
287
-
250
+ list = dump_children(@v4_root)
251
+ list.concat( dump_children(@v6_root) )
288
252
  return(list)
289
253
  end
290
254
 
@@ -348,13 +312,9 @@ class Tree
348
312
  end
349
313
  end
350
314
 
351
- me = find_me(cidr)
352
- if (me && me.children.length != 0)
353
- list = []
354
- me.children.each {|x| list.push(x.cidr)}
355
- me.cidr.fill_in(list, :Objectify => true).each do |cidr|
356
- self.add!(cidr)
357
- end
315
+ me = find_me(cidr)
316
+ if (me && me.tag[:Subnets].length != 0)
317
+ me.tag[:Subnets] = NetAddr.cidr_fill_in(me, me.tag[:Subnets])
358
318
  filled = true
359
319
  end
360
320
  return(filled)
@@ -385,7 +345,7 @@ class Tree
385
345
  end
386
346
  end
387
347
 
388
- return(find_me(cidr).cidr)
348
+ return(find_me(cidr))
389
349
  end
390
350
 
391
351
  #==============================================================================#
@@ -433,28 +393,23 @@ class Tree
433
393
  raise "Integer or Hash expected, but #{options.class} provided."
434
394
  end
435
395
 
436
- list4 = []
437
- list6 = []
438
- dump_children(@root).each do |entry|
439
- netstruct = entry[:NetStruct]
440
- if (netstruct.cidr.version == 4)
441
- if ( (netstruct.children.length == 0) && (netstruct.cidr.bits <= bits4) )
442
- list4.push(netstruct.cidr)
443
- end
444
- else
445
- if ( (netstruct.children.length == 0) && (netstruct.cidr.bits <= bits6) )
446
- list6.push(netstruct.cidr)
396
+ list = []
397
+ if (!version || version == 4)
398
+ dump_children(@v4_root).each do |entry|
399
+ cidr = entry[:CIDR]
400
+ if ( (cidr.tag[:Subnets].length == 0) && (cidr.bits <= bits4) )
401
+ list.push(cidr)
447
402
  end
448
403
  end
449
404
  end
450
-
451
- list = []
452
- if (!version)
453
- list.concat(list4)
454
- list.concat(list6)
455
- else
456
- list.concat(list4) if (version == 4)
457
- list.concat(list6) if (version == 6)
405
+
406
+ if (!version || version == 6)
407
+ dump_children(@v6_root).each do |entry|
408
+ cidr = entry[:CIDR]
409
+ if ( (cidr.tag[:Subnets].length == 0) && (cidr.bits <= bits6) )
410
+ list.push(cidr)
411
+ end
412
+ end
458
413
  end
459
414
 
460
415
  return(list)
@@ -474,7 +429,7 @@ class Tree
474
429
  #* String or NetAddr::CIDR object
475
430
  #
476
431
  #===Returns:
477
- #* NetAddr::CIDR object, or nil
432
+ #* NetAddr::CIDR object
478
433
  #
479
434
  def longest_match(cidr)
480
435
  if ( !cidr.kind_of?(NetAddr::CIDR) )
@@ -485,53 +440,11 @@ class Tree
485
440
  "errors: #{error}"
486
441
  end
487
442
  end
488
-
489
- found = find_me(cidr)
490
- found = find_parent(cidr, @root) if !found
491
-
492
- return(found.cidr)
493
- end
494
-
495
- #==============================================================================#
496
- # merge_subnets!()
497
- #==============================================================================#
498
443
 
499
- #===Synopsis
500
- # Merge (summarize) all subnets of the provided CIDR address.
501
- #
502
- # tree.merge_subnets!('192.168.1.0/24')
503
- #
504
- #===Arguments:
505
- #* String or NetAddr::CIDR object
506
- #
507
- #===Returns:
508
- #* true on success or false on fail
509
- #
510
- def merge_subnets!(cidr)
511
- merged = false
512
-
513
- # validate object
514
- if ( !cidr.kind_of?(NetAddr::CIDR) )
515
- begin
516
- cidr = NetAddr::CIDR.create(cidr)
517
- rescue Exception => error
518
- raise ArgumentError, "Provided argument raised the following " +
519
- "errors: #{error}"
520
- end
521
- end
522
-
523
- me = find_me(cidr)
524
-
525
- if (me)
526
- to_merge = []
527
- me.children.each {|x| to_merge.push(x.cidr)}
528
- to_merge.each {|x| delete!(x)}
529
-
530
- NetAddr.merge(to_merge).each {|x| add!(x)}
531
- merged = true
532
- end
444
+ found = find_me(cidr)
445
+ found = find_parent(cidr) if !found
533
446
 
534
- return(merged)
447
+ return(found)
535
448
  end
536
449
 
537
450
  #==============================================================================#
@@ -551,7 +464,7 @@ class Tree
551
464
  #
552
465
  def prune!(cidr)
553
466
  pruned = false
554
-
467
+
555
468
  # validate object
556
469
  if ( !cidr.kind_of?(NetAddr::CIDR) )
557
470
  begin
@@ -563,9 +476,9 @@ class Tree
563
476
  end
564
477
 
565
478
  me = find_me(cidr)
566
-
479
+
567
480
  if (me)
568
- me.children.clear
481
+ me.tag[:Subnets].clear
569
482
  pruned = true
570
483
  end
571
484
 
@@ -590,7 +503,7 @@ class Tree
590
503
  def remove!(cidr)
591
504
  removed = false
592
505
  found = nil
593
-
506
+
594
507
  # validate object
595
508
  if ( !cidr.kind_of?(NetAddr::CIDR) )
596
509
  begin
@@ -602,13 +515,13 @@ class Tree
602
515
  end
603
516
 
604
517
  me = find_me(cidr)
605
-
518
+
606
519
  if (me)
607
- parent = me.parent
608
- parent.children.delete(me)
520
+ parent = me.tag[:Parent]
521
+ parent.tag[:Subnets].delete(me)
609
522
  removed = true
610
523
  end
611
-
524
+
612
525
  return(removed)
613
526
  end
614
527
 
@@ -630,7 +543,7 @@ class Tree
630
543
  #
631
544
  def resize!(cidr,bits)
632
545
  resized = false
633
-
546
+
634
547
  # validate cidr
635
548
  if ( !cidr.kind_of?(NetAddr::CIDR) )
636
549
  begin
@@ -642,14 +555,14 @@ class Tree
642
555
  end
643
556
 
644
557
  me = find_me(cidr)
645
-
558
+
646
559
  if (me)
647
- new = me.cidr.resize(bits)
648
- delete!(me.cidr)
560
+ new = me.resize(bits)
561
+ delete!(me)
649
562
  add!(new)
650
563
  resized = true
651
564
  end
652
-
565
+
653
566
  return(resized)
654
567
  end
655
568
 
@@ -678,16 +591,17 @@ class Tree
678
591
  "errors: #{error}"
679
592
  end
680
593
  end
681
-
682
- parent = find_parent(cidr,@root)
683
-
684
- if (parent && parent != @root)
685
- until (parent.parent == @root)
686
- parent = parent.parent
594
+
595
+ parent = find_parent(cidr)
596
+ if (parent.tag.has_key?(:Parent)) # if parent is not 0/0
597
+ while(1)
598
+ grandparent = parent.tag[:Parent]
599
+ break if (!grandparent.tag.has_key?(:Parent)) # if grandparent is 0/0
600
+ parent = grandparent
687
601
  end
688
602
  end
689
603
 
690
- return(parent.cidr)
604
+ return(parent)
691
605
  end
692
606
 
693
607
  #==============================================================================#
@@ -706,11 +620,27 @@ class Tree
706
620
  #* String
707
621
  #
708
622
  def show()
709
- printed = ""
710
- list = dump_children(@root)
623
+ printed = "IPv4 Tree\n---------\n"
624
+ list4 = dump_children(@v4_root)
625
+ list6 = dump_children(@v6_root)
626
+
627
+ list4.each do |entry|
628
+ cidr = entry[:CIDR]
629
+ depth = entry[:Depth]
630
+
631
+ if (depth == 0)
632
+ indent = ""
633
+ else
634
+ indent = " " * (depth*3)
635
+ end
636
+
637
+ printed << "#{indent}#{cidr.desc}\n"
638
+ end
711
639
 
712
- list.each do |entry|
713
- cidr = entry[:NetStruct].cidr
640
+ printed << "\n\nIPv6 Tree\n---------\n" if (list6.length != 0)
641
+
642
+ list6.each do |entry|
643
+ cidr = entry[:CIDR]
714
644
  depth = entry[:Depth]
715
645
 
716
646
  if (depth == 0)
@@ -750,17 +680,58 @@ class Tree
750
680
  "errors: #{error}"
751
681
  end
752
682
  end
753
-
683
+
754
684
  list = []
755
- find_parent(cidr,@root).children.each do |entry|
756
- if (!cidr.cmp(entry.cidr))
757
- list.push(entry.cidr)
685
+ find_parent(cidr).tag[:Subnets].each do |entry|
686
+ if (!cidr.cmp(entry))
687
+ list.push(entry)
758
688
  end
759
689
  end
760
690
 
761
691
  return(list)
762
692
  end
763
693
 
694
+ #==============================================================================#
695
+ # summarize_subnets!()
696
+ #==============================================================================#
697
+
698
+ #===Synopsis
699
+ # Summarize all subnets of the provided CIDR address. The subnets will be
700
+ # placed under the new summary address within the tree.
701
+ #
702
+ # tree.summarize_subnets!('192.168.1.0/24')
703
+ #
704
+ #===Arguments:
705
+ #* String or NetAddr::CIDR object
706
+ #
707
+ #===Returns:
708
+ #* true on success or false on fail
709
+ #
710
+ def summarize_subnets!(cidr)
711
+ merged = false
712
+
713
+ # validate object
714
+ if ( !cidr.kind_of?(NetAddr::CIDR) )
715
+ begin
716
+ cidr = NetAddr::CIDR.create(cidr)
717
+ rescue Exception => error
718
+ raise ArgumentError, "Provided argument raised the following " +
719
+ "errors: #{error}"
720
+ end
721
+ end
722
+
723
+ me = find_me(cidr)
724
+
725
+ if (me)
726
+ merged = NetAddr.cidr_summarize(me.tag[:Subnets])
727
+ me.tag[:Subnets] = merged
728
+ merged = true
729
+ end
730
+
731
+ return(merged)
732
+ end
733
+ alias :merge_subnets! :summarize_subnets!
734
+
764
735
  #==============================================================================#
765
736
  # supernets()
766
737
  #==============================================================================#
@@ -778,7 +749,8 @@ class Tree
778
749
  #
779
750
  def supernets()
780
751
  supernets = []
781
- @root.children.each {|x| supernets.push(x.cidr)}
752
+ @v4_root.tag[:Subnets].each {|x| supernets.push(x)}
753
+ @v6_root.tag[:Subnets].each {|x| supernets.push(x)}
782
754
  return (supernets)
783
755
  end
784
756
 
@@ -787,27 +759,56 @@ class Tree
787
759
  private
788
760
 
789
761
  #==============================================================================#
790
- # add_to_parent() private
762
+ # add_to_parent()
791
763
  #==============================================================================#
792
764
 
793
765
  # Add NetStruct object to an array of NetStruct's
794
766
  #
795
- def add_to_parent(new_entry, parent)
796
- index = 0
797
- parent.children.each do
798
- if(new_entry.cidr.packed_network < parent.children[index].cidr.packed_network)
799
- break
767
+ def add_to_parent(cidr, parent)
768
+ duplicate = false
769
+ duplicate = true if (NetAddr.cidr_find_in_list(cidr,parent.tag[:Subnets]).kind_of?(Integer))
770
+
771
+ if (!duplicate)
772
+ # check parent for subnets of cidr
773
+ parent.tag[:Subnets].length.times do |index|
774
+ index -= 1
775
+ old_cidr = parent.tag[:Subnets][index]
776
+ cmp = NetAddr.cidr_compare(cidr, old_cidr)
777
+ if (cmp && cmp == 1)
778
+ old_cidr.tag[:Parent] = cidr
779
+ cidr.tag[:Subnets].push(old_cidr)
780
+ parent.tag[:Subnets][index] = nil
781
+ end
800
782
  end
801
- index += 1
783
+
784
+ cidr.tag[:Parent] = parent
785
+ parent.tag[:Subnets].compact!
786
+ parent.tag[:Subnets].push(cidr)
787
+ parent.tag[:Subnets] = NetAddr.cidr_sort(parent.tag[:Subnets])
802
788
  end
803
789
 
804
- parent.children.insert(index, new_entry)
790
+ return(nil)
791
+ end
805
792
 
806
- return()
793
+ #==============================================================================#
794
+ # add_to_tree()
795
+ #==============================================================================#
796
+
797
+ # Add CIDR to a Tree
798
+ #
799
+ def add_to_tree(cidr,root=nil)
800
+
801
+ # find cidr's parent
802
+ parent = find_parent(cidr)
803
+ if (parent)
804
+ add_to_parent(cidr,parent)
805
+ end
806
+
807
+ return(nil)
807
808
  end
808
809
 
809
810
  #==============================================================================#
810
- # dump_children() private
811
+ # dump_children()
811
812
  #==============================================================================#
812
813
 
813
814
  # Dump contents of an Array of NetStruct objects
@@ -816,10 +817,10 @@ private
816
817
  list = []
817
818
  depth = 0 if (!depth)
818
819
 
819
- parent.children.each do |entry|
820
- list.push({:NetStruct => entry, :Depth => depth})
820
+ parent.tag[:Subnets].each do |entry|
821
+ list.push({:CIDR => entry, :Depth => depth})
821
822
 
822
- if (entry.children.length > 0)
823
+ if (entry.tag[:Subnets].length > 0)
823
824
  list.concat( dump_children(entry, (depth+1) ) )
824
825
  end
825
826
  end
@@ -828,46 +829,51 @@ private
828
829
  end
829
830
 
830
831
  #==============================================================================#
831
- # find_me() private
832
+ # find_me()
832
833
  #==============================================================================#
833
834
 
834
835
  # Find the NetStruct to which a cidr belongs.
835
836
  #
836
837
  def find_me(cidr)
837
838
  me = nil
838
-
839
- # find matching
840
- parent = find_parent(cidr,@root)
841
- parent.children.each do |entry|
842
- if (entry.cidr.version == cidr.version)
843
- if (entry.cidr.cmp(cidr) == 0)
844
- me = entry
845
- break
846
- end
847
- end
839
+ root = nil
840
+ if (cidr.version == 4)
841
+ root = @v4_root
842
+ else
843
+ root = @v6_root
848
844
  end
849
845
 
846
+ # find matching
847
+ parent = find_parent(cidr,root)
848
+ index = NetAddr.cidr_find_in_list(cidr,parent.tag[:Subnets])
849
+ me = parent.tag[:Subnets][index] if (index.kind_of?(Integer))
850
+
850
851
  return(me)
851
852
  end
852
853
 
853
854
  #==============================================================================#
854
- # find_parent() private
855
+ # find_parent()
855
856
  #==============================================================================#
856
857
 
857
858
  # Find the parent NetStruct to which a child NetStruct belongs.
858
859
  #
859
- def find_parent(cidr,parent)
860
- version = cidr.version
861
-
862
- parent.children.each do |entry|
863
- if (entry.cidr.version == version && entry.cidr.contains?(cidr))
864
- parent = entry
860
+ def find_parent(cidr,parent=nil)
861
+ if (!parent)
862
+ if (cidr.version == 4)
863
+ parent = @v4_root
864
+ else
865
+ parent = @v6_root
866
+ end
867
+ end
868
+ bit_diff = cidr.bits - parent.bits
865
869
 
866
- if (parent.children.length > 0)
867
- search_results = find_parent(cidr,parent)
868
- parent = search_results if (search_results)
869
- end
870
- break
870
+ # if netmask of cidr is greater by 1 bit position, then this is the parent.
871
+ # if not then check to make sure that one of the children is the actual parent.
872
+ if (bit_diff > 1 && parent.tag[:Subnets].length != 0)
873
+ list = parent.tag[:Subnets]
874
+ found = NetAddr.cidr_find_in_list(cidr,list)
875
+ if (found.kind_of?(NetAddr::CIDR))
876
+ parent = find_parent(cidr,found)
871
877
  end
872
878
  end
873
879