ipadmin 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +190 -151
- data/lib/cidr.rb +412 -210
- data/lib/eui.rb +92 -115
- data/lib/methods.rb +409 -438
- data/lib/tree.rb +609 -367
- data/tests/cidr_test.rb +56 -43
- data/tests/eui_test.rb +16 -14
- data/tests/methods_test.rb +191 -185
- data/tests/tree_test.rb +191 -231
- metadata +3 -3
data/lib/cidr.rb
CHANGED
@@ -1,9 +1,3 @@
|
|
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
1
|
module IPAdmin
|
8
2
|
class CIDR
|
9
3
|
|
@@ -26,6 +20,9 @@ class CIDR
|
|
26
20
|
|
27
21
|
# Hash of custom tags. Should be in the format tag => value.
|
28
22
|
attr_reader :tag
|
23
|
+
|
24
|
+
# Integer of either 32 or 128 bits in length, with all bits set to 1
|
25
|
+
attr_reader :all_f
|
29
26
|
|
30
27
|
# Hash of custom tags. Should be in the format tag => value.
|
31
28
|
#
|
@@ -50,7 +47,7 @@ class CIDR
|
|
50
47
|
#==============================================================================#
|
51
48
|
|
52
49
|
# - Arguments:
|
53
|
-
# * Hash with the following fields:
|
50
|
+
# * CIDR address as a string, or a Hash with the following fields:
|
54
51
|
# - :CIDR -- IP address in CIDR notation - String (optional)
|
55
52
|
# - :Netmask -- IP Netmask - String or Integer (optional)
|
56
53
|
# - :PackedIP -- Integer representation of an IP address (optional)
|
@@ -66,7 +63,8 @@ class CIDR
|
|
66
63
|
# * Netmask within :CIDR takes precedence over :Netmask.
|
67
64
|
# * Version will be auto-detected if not specified
|
68
65
|
#
|
69
|
-
#
|
66
|
+
# Examples:
|
67
|
+
# cidr4 = IPAdmin::CIDR.new('192.168.1.1/24')
|
70
68
|
# cidr4 = IPAdmin::CIDR.new(:CIDR => '192.168.1.1/24')
|
71
69
|
# cidr4_2 = IPAdmin::CIDR.new(:PackedIP => 0x0a010001,
|
72
70
|
# :PackedNetmask => 0xffffff00
|
@@ -76,47 +74,51 @@ class CIDR
|
|
76
74
|
# cidr6_2 = IPAdmin::CIDR.new(:CIDR => '::ffff:192.168.1.1/96')
|
77
75
|
#
|
78
76
|
def initialize(options)
|
79
|
-
|
80
|
-
|
77
|
+
@tag = {}
|
78
|
+
if (!options.kind_of?(Hash) && !options.kind_of?(String))
|
79
|
+
raise ArgumentError, "Expected Hash or String, but #{options.class} provided."
|
81
80
|
end
|
82
81
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
raise ArgumentError, "Expected Integer, but #{packed_ip.class} " +
|
87
|
-
"provided for option :PackedIP." if (!packed_ip.kind_of?(Integer))
|
88
|
-
elsif (options.has_key?(:CIDR))
|
89
|
-
cidr = options[:CIDR]
|
90
|
-
raise ArgumentError, "Expected String, but #{cidr.class} " +
|
91
|
-
"provided for option :CIDR." if (!cidr.kind_of?(String))
|
92
|
-
else
|
93
|
-
raise ArgumentError, "Missing argument: CIDR or PackedIP."
|
94
|
-
end
|
95
|
-
|
82
|
+
if (options.kind_of? String)
|
83
|
+
cidr = options
|
84
|
+
end
|
96
85
|
|
97
|
-
if (options.
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
86
|
+
if (options.kind_of? Hash)
|
87
|
+
if (options.has_key?(:PackedIP))
|
88
|
+
packed_ip = options[:PackedIP]
|
89
|
+
raise ArgumentError, "Expected Integer, but #{packed_ip.class} " +
|
90
|
+
"provided for option :PackedIP." if (!packed_ip.kind_of?(Integer))
|
91
|
+
elsif (options.has_key?(:CIDR))
|
92
|
+
cidr = options[:CIDR]
|
93
|
+
raise ArgumentError, "Expected String, but #{cidr.class} " +
|
94
|
+
"provided for option :CIDR." if (!cidr.kind_of?(String))
|
95
|
+
else
|
96
|
+
raise ArgumentError, "Missing argument: CIDR or PackedIP."
|
97
|
+
end
|
107
98
|
|
99
|
+
if (options.has_key?(:PackedNetmask))
|
100
|
+
packed_netmask = options[:PackedNetmask]
|
101
|
+
raise ArgumentError, "Expected Integer, but #{packed_netmask.class} " +
|
102
|
+
"provided for option :PackedNetmask." if (!packed_netmask.kind_of?(Integer))
|
103
|
+
|
104
|
+
elsif (options.has_key?(:Netmask))
|
105
|
+
netmask = options[:Netmask]
|
106
|
+
raise ArgumentError, "Expected String or Integer, but #{netmask.class} " +
|
107
|
+
"provided for option :Netmask." if (!netmask.kind_of?(String) && !netmask.kind_of?(Integer))
|
108
|
+
end
|
108
109
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
110
|
+
if (options.has_key?(:Version))
|
111
|
+
@version = options[:Version]
|
112
|
+
if (@version != 4 && @version != 6)
|
113
|
+
raise ArgumentError, ":Version should be 4 or 6, but was '#{version}'."
|
114
|
+
end
|
113
115
|
end
|
114
|
-
end
|
115
116
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
117
|
+
if (options.has_key?(:Tag))
|
118
|
+
@tag = options[:Tag]
|
119
|
+
if (!@tag.kind_of? Hash)
|
120
|
+
raise ArgumentError, "Expected Hash, but #{@tag.class} provided for option :Tag."
|
121
|
+
end
|
120
122
|
end
|
121
123
|
end
|
122
124
|
|
@@ -156,8 +158,7 @@ class CIDR
|
|
156
158
|
@netmask = 2**128-1 if (!netmask && !packed_netmask)
|
157
159
|
end
|
158
160
|
|
159
|
-
#
|
160
|
-
IPAdmin.validate_ip_addr(:IP => ip, :Version => @version)
|
161
|
+
# pack ip
|
161
162
|
@ip = IPAdmin.pack_ip_addr(:IP => ip, :Version => @version)
|
162
163
|
|
163
164
|
end
|
@@ -208,8 +209,8 @@ class CIDR
|
|
208
209
|
# - Returns:
|
209
210
|
# * String
|
210
211
|
#
|
211
|
-
#
|
212
|
-
# arpa = cidr4.arpa()
|
212
|
+
# Examples:
|
213
|
+
# arpa = cidr4.arpa()
|
213
214
|
#
|
214
215
|
def arpa()
|
215
216
|
|
@@ -270,8 +271,8 @@ class CIDR
|
|
270
271
|
# - Returns:
|
271
272
|
# * Integer.
|
272
273
|
#
|
273
|
-
#
|
274
|
-
# puts cidr4.bits()
|
274
|
+
# Examples:
|
275
|
+
# puts cidr4.bits()
|
275
276
|
#
|
276
277
|
def bits()
|
277
278
|
return(IPAdmin.unpack_ip_netmask(:Integer => @netmask))
|
@@ -287,33 +288,35 @@ class CIDR
|
|
287
288
|
#==============================================================================#
|
288
289
|
|
289
290
|
# Determines if this CIDR contains (is supernet of)
|
290
|
-
# the provided CIDR object.
|
291
|
+
# the provided CIDR addresss or IPAdmin::CIDR object.
|
291
292
|
#
|
292
293
|
# - Arguments:
|
293
|
-
# * CIDR object
|
294
|
+
# * CIDR addresss or IPAdmin::CIDR object
|
294
295
|
#
|
295
296
|
# - Returns:
|
296
297
|
# * true or false
|
297
298
|
#
|
298
|
-
#
|
299
|
-
#
|
300
|
-
# contains? = cidr4.contains(cidr4_2) --> true
|
299
|
+
# Examples:
|
300
|
+
# contains? = cidr4.contains('192.168.1.32/27')
|
301
301
|
#
|
302
|
-
def contains?(
|
302
|
+
def contains?(cidr)
|
303
303
|
is_contained = false
|
304
304
|
|
305
|
-
if (
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
305
|
+
if (!cidr.kind_of?(IPAdmin::CIDR))
|
306
|
+
begin
|
307
|
+
cidr = IPAdmin::CIDR.new(:CIDR => cidr)
|
308
|
+
rescue Exception => error
|
309
|
+
raise ArgumentError, "Provided argument raised the following " +
|
310
|
+
"errors: #{error}"
|
311
|
+
end
|
312
312
|
end
|
313
|
+
|
314
|
+
network = cidr.packed_network
|
315
|
+
netmask = cidr.packed_netmask
|
313
316
|
|
314
317
|
|
315
|
-
if (
|
316
|
-
raise ArgumentError, "Attempted to compare a version #{
|
318
|
+
if (cidr.version != @version)
|
319
|
+
raise ArgumentError, "Attempted to compare a version #{cidr.version} CIDR " +
|
317
320
|
"with a version #{@version} CIDR."
|
318
321
|
end
|
319
322
|
|
@@ -349,11 +352,11 @@ class CIDR
|
|
349
352
|
# - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
|
350
353
|
#
|
351
354
|
# - Returns:
|
352
|
-
# * String
|
355
|
+
# * CIDR address as a String
|
353
356
|
#
|
354
|
-
#
|
355
|
-
# puts cidr4.desc()
|
356
|
-
# puts cidr4.desc(:IP => true)
|
357
|
+
# Examples:
|
358
|
+
# puts cidr4.desc()
|
359
|
+
# puts cidr4.desc(:IP => true)
|
357
360
|
#
|
358
361
|
def desc(options=nil)
|
359
362
|
short = false
|
@@ -404,10 +407,10 @@ class CIDR
|
|
404
407
|
# - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
|
405
408
|
#
|
406
409
|
# - Returns:
|
407
|
-
# * Array of Strings or CIDR objects
|
410
|
+
# * Array of IP address Strings or IPAdmin::CIDR objects
|
408
411
|
#
|
409
|
-
#
|
410
|
-
# ip_list = cidr4.enumerate(:Bitstep => 2, :Limit => 2)
|
412
|
+
# Examples:
|
413
|
+
# ip_list = cidr4.enumerate(:Bitstep => 2, :Limit => 2)
|
411
414
|
#
|
412
415
|
def enumerate(options=nil)
|
413
416
|
bitstep = 1
|
@@ -465,6 +468,127 @@ class CIDR
|
|
465
468
|
#======================================#
|
466
469
|
|
467
470
|
|
471
|
+
#==============================================================================#
|
472
|
+
# fill_in()
|
473
|
+
#==============================================================================#
|
474
|
+
|
475
|
+
# Given a list of subnets of the current CIDR, return a new list with any
|
476
|
+
# holes (missing subnets) filled in.
|
477
|
+
#
|
478
|
+
# - Arguments:
|
479
|
+
# * Array of CIDR addresses or IPAdmin::CIDR objects,
|
480
|
+
# or a Hash with the following fields:
|
481
|
+
# - :List -- Array of CIDR addresses or IPAdmin::CIDR objects
|
482
|
+
# - :Objectify -- if true, return IPAdmin::CIDR objects (optional)
|
483
|
+
# - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
|
484
|
+
#
|
485
|
+
# - Returns:
|
486
|
+
# * Array of CIDR address Strings or IPAdmin::CIDR objects
|
487
|
+
#
|
488
|
+
# Examples:
|
489
|
+
# subnets = cidr4.fill_in(['192.168.1.0/27','192.168.1.64/26','192.168.1.128/25'])
|
490
|
+
# subnets = cidr4.fill_in(:List => ['192.168.1.0/27','192.168.1.64/26'], :Objectify => true)
|
491
|
+
#
|
492
|
+
|
493
|
+
def fill_in(options)
|
494
|
+
short = false
|
495
|
+
objectify = false
|
496
|
+
|
497
|
+
# validate options
|
498
|
+
if ( options.kind_of?(Hash) )
|
499
|
+
if (!options.has_key?(:List))
|
500
|
+
raise ArgumentError, "Missing argument: List."
|
501
|
+
end
|
502
|
+
|
503
|
+
if (options.has_key?(:Short) && options[:Short] == true)
|
504
|
+
short = true
|
505
|
+
end
|
506
|
+
|
507
|
+
if (options.has_key?(:Objectify) && options[:Objectify] == true)
|
508
|
+
objectify = true
|
509
|
+
end
|
510
|
+
|
511
|
+
# make sure :List is an array
|
512
|
+
if ( !options[:List].kind_of?(Array) )
|
513
|
+
raise ArgumentError, "Expected Array for option :List, " +
|
514
|
+
"but #{list.class} provided."
|
515
|
+
end
|
516
|
+
list = options[:List]
|
517
|
+
|
518
|
+
elsif ( options.kind_of?(Array) )
|
519
|
+
list = options
|
520
|
+
else
|
521
|
+
raise ArgumentError, "Array or Hash expected but #{options.class} provided."
|
522
|
+
end
|
523
|
+
|
524
|
+
# validate each cidr and store in cidr_list
|
525
|
+
cidr_list = []
|
526
|
+
list.each do |obj|
|
527
|
+
if (!obj.kind_of?(IPAdmin::CIDR))
|
528
|
+
begin
|
529
|
+
obj = IPAdmin::CIDR.new(:CIDR => obj)
|
530
|
+
rescue Exception => error
|
531
|
+
aise ArgumentError, "A provided CIDR raised the following " +
|
532
|
+
"errors: #{error}"
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
if (!obj.version == self.version)
|
537
|
+
raise "#{obj.desc(:Short => true)} is not a version #{self.version} address."
|
538
|
+
end
|
539
|
+
|
540
|
+
# make sure we contain the cidr
|
541
|
+
if ( self.contains?(obj) == false )
|
542
|
+
raise "#{obj.desc(:Short => true)} does not fit " +
|
543
|
+
"within the bounds of #{self.desc(:Short => true)}."
|
544
|
+
end
|
545
|
+
cidr_list.push(obj)
|
546
|
+
end
|
547
|
+
|
548
|
+
# sort our cidr's and see what is missing
|
549
|
+
complete_list = []
|
550
|
+
expected = self.packed_network
|
551
|
+
IPAdmin.sort(cidr_list).each do |cidr|
|
552
|
+
network = cidr.packed_network
|
553
|
+
bitstep = (@all_f + 1) - cidr.packed_netmask
|
554
|
+
|
555
|
+
if (network > expected)
|
556
|
+
num_ips_missing = network - expected
|
557
|
+
sub_list = make_subnets_from_base_and_ip_count(expected,num_ips_missing)
|
558
|
+
complete_list.concat(sub_list)
|
559
|
+
elsif (network < expected)
|
560
|
+
next
|
561
|
+
end
|
562
|
+
complete_list.push(IPAdmin::CIDR.new(:PackedIP => network,
|
563
|
+
:PackedNetmask => cidr.packed_netmask,
|
564
|
+
:Version => self.version))
|
565
|
+
expected = network + bitstep
|
566
|
+
end
|
567
|
+
|
568
|
+
# if expected is not the next subnet, then we're missing subnets
|
569
|
+
# at the end of the cidr
|
570
|
+
next_sub = self.next_subnet(:Objectify => true).packed_network
|
571
|
+
if (expected != next_sub)
|
572
|
+
num_ips_missing = next_sub - expected
|
573
|
+
sub_list = make_subnets_from_base_and_ip_count(expected,num_ips_missing)
|
574
|
+
complete_list.concat(sub_list)
|
575
|
+
end
|
576
|
+
|
577
|
+
# decide what to return
|
578
|
+
if (!objectify)
|
579
|
+
subnets = []
|
580
|
+
complete_list.each {|entry| subnets.push(entry.desc(:Short => short))}
|
581
|
+
return(subnets)
|
582
|
+
else
|
583
|
+
return(complete_list)
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
#======================================#
|
588
|
+
#
|
589
|
+
#======================================#
|
590
|
+
|
591
|
+
|
468
592
|
#==============================================================================#
|
469
593
|
# hostmask_ext()
|
470
594
|
#==============================================================================#
|
@@ -477,8 +601,8 @@ class CIDR
|
|
477
601
|
# - Returns:
|
478
602
|
# * String
|
479
603
|
#
|
480
|
-
#
|
481
|
-
# puts cidr4.hostmask_ext()
|
604
|
+
# Examples:
|
605
|
+
# puts cidr4.hostmask_ext()
|
482
606
|
#
|
483
607
|
def hostmask_ext()
|
484
608
|
if (@version == 4)
|
@@ -507,10 +631,10 @@ class CIDR
|
|
507
631
|
# - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
|
508
632
|
#
|
509
633
|
# - Returns:
|
510
|
-
# * String or CIDR object.
|
634
|
+
# * IP address String or IPAdmin::CIDR object.
|
511
635
|
#
|
512
|
-
#
|
513
|
-
# puts cidr4.ip()
|
636
|
+
# Examples:
|
637
|
+
# puts cidr4.ip()
|
514
638
|
#
|
515
639
|
def ip(options=nil)
|
516
640
|
objectify = false
|
@@ -560,15 +684,15 @@ class CIDR
|
|
560
684
|
# - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
|
561
685
|
#
|
562
686
|
# - Returns:
|
563
|
-
# * String or CIDR object.
|
687
|
+
# * IP address String or IPAdmin::CIDR object.
|
564
688
|
#
|
565
689
|
# - Notes:
|
566
690
|
# * The broadcast() method is aliased to this method, and thus works for
|
567
691
|
# IPv6 despite the fact that the IPv6 protocol does not support IP
|
568
692
|
# broadcasting.
|
569
693
|
#
|
570
|
-
#
|
571
|
-
# puts cidr4.last()
|
694
|
+
# Examples:
|
695
|
+
# puts cidr4.last()
|
572
696
|
#
|
573
697
|
def last(options=nil)
|
574
698
|
objectify = false
|
@@ -620,14 +744,14 @@ class CIDR
|
|
620
744
|
# - :Objectify -- if true, return EUI objects (optional)
|
621
745
|
#
|
622
746
|
# - Returns:
|
623
|
-
# *
|
747
|
+
# * IPAdmin::EUI48 object
|
624
748
|
#
|
625
749
|
# - Note:
|
626
750
|
# * MAC address is based on original IP address passed during initialization.
|
627
751
|
#
|
628
|
-
#
|
752
|
+
# Examples:
|
629
753
|
# mcast = IPAdmin::CIDR.new(:CIDR => '224.0.0.6')
|
630
|
-
# puts mcast.multicast_mac.address
|
754
|
+
# puts mcast.multicast_mac.address
|
631
755
|
#
|
632
756
|
def multicast_mac(options=nil)
|
633
757
|
objectify = false
|
@@ -660,7 +784,7 @@ class CIDR
|
|
660
784
|
end
|
661
785
|
end
|
662
786
|
|
663
|
-
eui = IPAdmin::
|
787
|
+
eui = IPAdmin::EUI48.new(:PackedEUI => mac)
|
664
788
|
eui = eui.address if (!objectify)
|
665
789
|
|
666
790
|
return(eui)
|
@@ -683,8 +807,8 @@ class CIDR
|
|
683
807
|
# - Returns:
|
684
808
|
# * String
|
685
809
|
#
|
686
|
-
#
|
687
|
-
# puts cidr4.netmask()
|
810
|
+
# Examples:
|
811
|
+
# puts cidr4.netmask()
|
688
812
|
#
|
689
813
|
def netmask()
|
690
814
|
bits = IPAdmin.unpack_ip_netmask(:Integer => @netmask)
|
@@ -708,8 +832,8 @@ class CIDR
|
|
708
832
|
# - Returns:
|
709
833
|
# * String
|
710
834
|
#
|
711
|
-
#
|
712
|
-
# puts cidr4.netmask_ext()
|
835
|
+
# Examples:
|
836
|
+
# puts cidr4.netmask_ext()
|
713
837
|
#
|
714
838
|
def netmask_ext()
|
715
839
|
if (@version == 4)
|
@@ -739,10 +863,10 @@ class CIDR
|
|
739
863
|
# - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
|
740
864
|
#
|
741
865
|
# - Returns:
|
742
|
-
# * String or CIDR object.
|
866
|
+
# * CIDR address String or IPAdmin::CIDR object.
|
743
867
|
#
|
744
|
-
#
|
745
|
-
# puts cidr4.network()
|
868
|
+
# Examples:
|
869
|
+
# puts cidr4.network()
|
746
870
|
#
|
747
871
|
def network(options=nil)
|
748
872
|
objectify = false
|
@@ -796,10 +920,10 @@ class CIDR
|
|
796
920
|
# - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
|
797
921
|
#
|
798
922
|
# - Returns:
|
799
|
-
# * String or CIDR object.
|
923
|
+
# * IP address String or IPAdmin::CIDR object.
|
800
924
|
#
|
801
|
-
#
|
802
|
-
# puts cidr4.next_ip()
|
925
|
+
# Examples:
|
926
|
+
# puts cidr4.next_ip()
|
803
927
|
#
|
804
928
|
def next_ip(options=nil)
|
805
929
|
bitstep = 1
|
@@ -861,10 +985,10 @@ class CIDR
|
|
861
985
|
# - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
|
862
986
|
#
|
863
987
|
# - Returns:
|
864
|
-
# * String or CIDR object.
|
988
|
+
# * CIDR address String or IPAdmin::CIDR object.
|
865
989
|
#
|
866
|
-
#
|
867
|
-
# puts cidr4.next_subnet()
|
990
|
+
# Examples:
|
991
|
+
# puts cidr4.next_subnet()
|
868
992
|
#
|
869
993
|
def next_subnet(options=nil)
|
870
994
|
bitstep = 1
|
@@ -921,39 +1045,42 @@ class CIDR
|
|
921
1045
|
# Provide the nth IP within this object.
|
922
1046
|
#
|
923
1047
|
# - Arguments:
|
924
|
-
# * Hash with the following fields:
|
1048
|
+
# * Integer or a Hash with the following fields:
|
925
1049
|
# - :Index -- index number of the IP address to return - Integer
|
926
1050
|
# - :Objectify -- if true, return IPAdmin::CIDR objects (optional)
|
927
1051
|
# - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
|
928
1052
|
#
|
929
1053
|
# - Returns:
|
930
|
-
# * String or CIDR object.
|
1054
|
+
# * IP address String or IPAdmin::CIDR object.
|
931
1055
|
#
|
932
|
-
#
|
933
|
-
# puts cidr4.nth(
|
1056
|
+
# Examples:
|
1057
|
+
# puts cidr4.nth(1)
|
1058
|
+
# puts cidr4.nth(:Index => 1, :Objectify => true)
|
934
1059
|
#
|
935
1060
|
def nth(options)
|
936
1061
|
objectify = false
|
937
1062
|
short = false
|
938
1063
|
|
939
|
-
if (
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
if ( !options.has_key?(:Index) )
|
945
|
-
raise ArgumentError, "Missing argument: Index."
|
946
|
-
end
|
947
|
-
index = options[:Index]
|
1064
|
+
if (options.kind_of?(Hash))
|
1065
|
+
if ( !options.has_key?(:Index) )
|
1066
|
+
raise ArgumentError, "Missing argument: Index."
|
1067
|
+
end
|
1068
|
+
index = options[:Index]
|
948
1069
|
|
949
|
-
|
950
|
-
|
951
|
-
|
1070
|
+
if( options.has_key?(:Short) && options[:Short] == true )
|
1071
|
+
short = true
|
1072
|
+
end
|
952
1073
|
|
953
|
-
|
954
|
-
|
1074
|
+
if( options.has_key?(:Objectify) && options[:Objectify] == true )
|
1075
|
+
objectify = true
|
1076
|
+
end
|
1077
|
+
elsif (options.kind_of?(Integer))
|
1078
|
+
index = options
|
1079
|
+
else
|
1080
|
+
raise ArgumentError, "Integer or Hash expected, but " +
|
1081
|
+
"#{options.class} provided."
|
955
1082
|
end
|
956
|
-
|
1083
|
+
|
957
1084
|
my_ip = @network + index
|
958
1085
|
if ( (@hostmask | my_ip) == (@hostmask | @network) )
|
959
1086
|
|
@@ -989,8 +1116,8 @@ class CIDR
|
|
989
1116
|
# - Returns:
|
990
1117
|
# * Integer
|
991
1118
|
#
|
992
|
-
#
|
993
|
-
# puts cidr4.packed_hostmask().to_s(16)
|
1119
|
+
# Examples:
|
1120
|
+
# puts cidr4.packed_hostmask().to_s(16)
|
994
1121
|
#
|
995
1122
|
def packed_hostmask()
|
996
1123
|
return(@hostmask)
|
@@ -1013,8 +1140,8 @@ class CIDR
|
|
1013
1140
|
# - Returns:
|
1014
1141
|
# * Integer
|
1015
1142
|
#
|
1016
|
-
#
|
1017
|
-
# puts cidr4.packed_ip().to_s(16)
|
1143
|
+
# Examples:
|
1144
|
+
# puts cidr4.packed_ip().to_s(16)
|
1018
1145
|
#
|
1019
1146
|
def packed_ip()
|
1020
1147
|
return(@ip)
|
@@ -1037,8 +1164,8 @@ class CIDR
|
|
1037
1164
|
# - Returns:
|
1038
1165
|
# * Integer
|
1039
1166
|
#
|
1040
|
-
#
|
1041
|
-
# puts cidr4.packed_netmask().to_s(16)
|
1167
|
+
# Examples:
|
1168
|
+
# puts cidr4.packed_netmask().to_s(16)
|
1042
1169
|
#
|
1043
1170
|
def packed_netmask()
|
1044
1171
|
return(@netmask)
|
@@ -1061,8 +1188,8 @@ class CIDR
|
|
1061
1188
|
# - Returns:
|
1062
1189
|
# * Integer
|
1063
1190
|
#
|
1064
|
-
#
|
1065
|
-
# packed = cidr4.packed_network().to_s(16)
|
1191
|
+
# Examples:
|
1192
|
+
# packed = cidr4.packed_network().to_s(16)
|
1066
1193
|
#
|
1067
1194
|
def packed_network()
|
1068
1195
|
return(@network)
|
@@ -1081,37 +1208,53 @@ class CIDR
|
|
1081
1208
|
# between them (inclusive).
|
1082
1209
|
#
|
1083
1210
|
# - Arguments:
|
1084
|
-
# * Hash with the following fields:
|
1211
|
+
# * Array of (2) Integers, or a Hash with the following fields:
|
1085
1212
|
# - :Bitstep -- enumerate in X sized steps - Integer (optional)
|
1086
1213
|
# - :Indexes -- index numbers of the addresses to use as boundaries - Array of (2) Integers
|
1087
1214
|
# - :Objectify -- if true, return IPAdmin::CIDR objects (optional)
|
1088
1215
|
# - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
|
1089
1216
|
#
|
1090
1217
|
# - Returns:
|
1091
|
-
# * Array Strings or CIDR objects
|
1218
|
+
# * Array IP address Strings or IPAdmin::CIDR objects
|
1092
1219
|
#
|
1093
|
-
#
|
1094
|
-
# list = cidr4.range(
|
1220
|
+
# Examples:
|
1221
|
+
# list = cidr4.range([0,1])
|
1222
|
+
# list = cidr4.range(:Indexes => [0,1], :Objectify => true)
|
1095
1223
|
#
|
1096
1224
|
def range(options)
|
1097
1225
|
objectify = false
|
1098
1226
|
short = false
|
1099
1227
|
bitstep = 1
|
1100
1228
|
|
1101
|
-
if (
|
1102
|
-
|
1103
|
-
|
1229
|
+
if (options.kind_of?(Hash))
|
1230
|
+
if ( !options.has_key?(:Indexes) )
|
1231
|
+
raise ArgumentError, "Missing argument: Indexes."
|
1232
|
+
end
|
1233
|
+
indexes = options[:Indexes]
|
1234
|
+
raise "Array expected but #{indexes.class} provided for argument: Indexes" if (!indexes.kind_of?(Array))
|
1235
|
+
|
1236
|
+
if( options.has_key?(:Short) && options[:Short] == true )
|
1237
|
+
short = true
|
1238
|
+
end
|
1239
|
+
|
1240
|
+
if( options.has_key?(:Objectify) && options[:Objectify] == true )
|
1241
|
+
objectify = true
|
1242
|
+
end
|
1104
1243
|
|
1105
|
-
|
1106
|
-
|
1244
|
+
if( options.has_key?(:Bitstep) )
|
1245
|
+
bitstep = options[:Bitstep]
|
1246
|
+
end
|
1247
|
+
elsif (options.kind_of?(Array))
|
1248
|
+
indexes = options
|
1249
|
+
else
|
1250
|
+
raise Argumenterror, "Array or Hash expected, but #{options.class} provided."
|
1107
1251
|
end
|
1108
|
-
indexes = options[:Indexes]
|
1109
|
-
indexes.sort!
|
1110
1252
|
|
1111
|
-
|
1112
|
-
|
1253
|
+
# validate & sort indexes
|
1254
|
+
indexes.sort!
|
1255
|
+
if (indexes.length != 2)
|
1256
|
+
raise "(2) index numbers are required."
|
1113
1257
|
end
|
1114
|
-
|
1115
1258
|
if ( (indexes[0] < 0) || (indexes[0] > self.size) )
|
1116
1259
|
raise ArgumentError, "Index #{indexes[0]} is out of bounds for this CIDR."
|
1117
1260
|
end
|
@@ -1120,18 +1263,7 @@ class CIDR
|
|
1120
1263
|
raise ArgumentError, "Index #{indexes[1]} is out of bounds for this CIDR."
|
1121
1264
|
end
|
1122
1265
|
|
1123
|
-
|
1124
|
-
short = true
|
1125
|
-
end
|
1126
|
-
|
1127
|
-
if( options.has_key?(:Objectify) && options[:Objectify] == true )
|
1128
|
-
objectify = true
|
1129
|
-
end
|
1130
|
-
|
1131
|
-
if( options.has_key?(:Bitstep) )
|
1132
|
-
bitstep = options[:Bitstep]
|
1133
|
-
end
|
1134
|
-
|
1266
|
+
# make range
|
1135
1267
|
start_ip = @network + indexes[0]
|
1136
1268
|
end_ip = @network + indexes[1]
|
1137
1269
|
my_ip = start_ip
|
@@ -1160,51 +1292,59 @@ class CIDR
|
|
1160
1292
|
# remainder()
|
1161
1293
|
#==============================================================================#
|
1162
1294
|
|
1163
|
-
# Given a
|
1164
|
-
# the
|
1295
|
+
# Given a single subnet of the current CIDR, provide the remainder of
|
1296
|
+
# the subnets. For example if the original CIDR is 192.168.0.0/24 and you
|
1165
1297
|
# provide 192.168.0.64/26 as the portion to exclude, then 192.168.0.0/26,
|
1166
|
-
# and 192.168.0.128/25 will be returned as the
|
1298
|
+
# and 192.168.0.128/25 will be returned as the remainders.
|
1167
1299
|
#
|
1168
1300
|
# - Arguments:
|
1169
|
-
# *
|
1170
|
-
# - :Exclude -- CIDR
|
1301
|
+
# * CIDR address or IPAdmin::CIDR object, or a Hash with the following fields:
|
1302
|
+
# - :Exclude -- CIDR address or IPAdmin::CIDR object.
|
1171
1303
|
# - :Objectify -- if true, return IPAdmin::CIDR objects (optional)
|
1172
1304
|
# - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
|
1173
1305
|
#
|
1174
1306
|
# - Returns:
|
1175
|
-
# * Array of Strings or CIDR objects
|
1307
|
+
# * Array of CIDR address Strings or IPAdmin::CIDR objects
|
1176
1308
|
#
|
1177
1309
|
#
|
1178
|
-
#
|
1179
|
-
#
|
1180
|
-
# cidr4.remainder(:Exclude =>
|
1310
|
+
# Examples:
|
1311
|
+
# cidr4.remainder('192.168.1.32/27').each {|x| puts x}
|
1312
|
+
# cidr4.remainder(:Exclude => '192.168.1.32/27', :Objectify => true).each {|x| puts x.desc}
|
1181
1313
|
#
|
1182
1314
|
def remainder(options)
|
1183
1315
|
short = nil
|
1184
1316
|
objectify = nil
|
1185
1317
|
|
1186
|
-
if (
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
raise ArgumentError, "Missing argument: Exclude."
|
1192
|
-
end
|
1193
|
-
to_exclude = options[:Exclude]
|
1318
|
+
if (options.kind_of? Hash)
|
1319
|
+
if ( !options.has_key?(:Exclude) )
|
1320
|
+
raise ArgumentError, "Missing argument: Exclude."
|
1321
|
+
end
|
1322
|
+
to_exclude = options[:Exclude]
|
1194
1323
|
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
end
|
1324
|
+
if( options.has_key?(:Short) && options[:Short] == true )
|
1325
|
+
short = true
|
1326
|
+
end
|
1199
1327
|
|
1200
|
-
|
1201
|
-
|
1328
|
+
if( options.has_key?(:Objectify) && options[:Objectify] == true )
|
1329
|
+
objectify = true
|
1330
|
+
end
|
1331
|
+
|
1332
|
+
elsif
|
1333
|
+
to_exclude = options
|
1334
|
+
else
|
1335
|
+
raise ArgumentError, "CIDR address or Hash expected, but #{options.class} provided."
|
1202
1336
|
end
|
1203
1337
|
|
1204
|
-
if(
|
1205
|
-
|
1338
|
+
if ( !to_exclude.kind_of?(IPAdmin::CIDR) )
|
1339
|
+
begin
|
1340
|
+
to_exclude = IPAdmin::CIDR.new(:CIDR => to_exclude)
|
1341
|
+
rescue Exception => error
|
1342
|
+
raise ArgumentError, "Argument :Exclude raised the following " +
|
1343
|
+
"errors: #{error}"
|
1344
|
+
end
|
1206
1345
|
end
|
1207
1346
|
|
1347
|
+
|
1208
1348
|
# make sure 'to_exclude' is the same ip version
|
1209
1349
|
if ( to_exclude.version != @version )
|
1210
1350
|
raise "#{to_exclude.desc(:Short => true)} is of a different " +
|
@@ -1266,26 +1406,29 @@ class CIDR
|
|
1266
1406
|
# Return the resulting CIDR as a new object.
|
1267
1407
|
#
|
1268
1408
|
# - Arguments:
|
1269
|
-
# * Hash with the following fields:
|
1270
|
-
# - :
|
1409
|
+
# * Integer, or a Hash with the following fields:
|
1410
|
+
# - :Netmask -- Number of bits of new Netmask - Integer
|
1271
1411
|
#
|
1272
1412
|
# - Returns:
|
1273
|
-
# * CIDR object
|
1413
|
+
# * IPAdmin::CIDR object
|
1274
1414
|
#
|
1275
|
-
#
|
1276
|
-
# new_cidr = cidr4.resize(
|
1277
|
-
#
|
1415
|
+
# Examples:
|
1416
|
+
# new_cidr = cidr4.resize(23)
|
1417
|
+
# new_cidr = cidr4.resize(:Netmask => 23)
|
1418
|
+
# puts new_cidr.desc
|
1278
1419
|
#
|
1279
1420
|
def resize(options)
|
1280
|
-
if (
|
1281
|
-
|
1421
|
+
if (options.kind_of?(Hash))
|
1422
|
+
if ( !options.has_key?(:Netmask) )
|
1423
|
+
raise Argumenterror, "Missing argument: Netmask."
|
1424
|
+
end
|
1425
|
+
bits = options[:Netmask]
|
1426
|
+
elsif (options.kind_of?(Integer))
|
1427
|
+
bits = options
|
1428
|
+
else
|
1429
|
+
raise Argumenterror, "Integer or Hash expected, but " +
|
1282
1430
|
"#{options.class} provided."
|
1283
1431
|
end
|
1284
|
-
|
1285
|
-
if ( !options.has_key?(:Subnet) )
|
1286
|
-
raise Argumenterror, "Missing argument: Subnet."
|
1287
|
-
end
|
1288
|
-
bits = options[:Subnet]
|
1289
1432
|
|
1290
1433
|
IPAdmin.validate_ip_netmask(:Netmask => bits, :Version => @version)
|
1291
1434
|
netmask = IPAdmin.pack_ip_netmask(:Netmask => bits, :Version => @version)
|
@@ -1307,30 +1450,32 @@ class CIDR
|
|
1307
1450
|
# Resize this object by changing the size of the Netmask.
|
1308
1451
|
#
|
1309
1452
|
# - Arguments:
|
1310
|
-
# * Hash with the following fields:
|
1311
|
-
# - :
|
1453
|
+
# * Integer, or a Hash with the following fields:
|
1454
|
+
# - :Netmask -- Number of bits of new Netmask - Integer
|
1312
1455
|
#
|
1313
1456
|
# - Returns:
|
1314
|
-
# *
|
1457
|
+
# * True
|
1315
1458
|
#
|
1316
1459
|
# - Notes:
|
1317
1460
|
# * If CIDR is resized such that the original IP is no longer contained within,
|
1318
1461
|
# then that IP will be reset to the base network address.
|
1319
1462
|
#
|
1320
|
-
#
|
1321
|
-
# cidr4.resize!(
|
1322
|
-
# puts cidr4.desc
|
1463
|
+
# Examples:
|
1464
|
+
# cidr4.resize!(23)
|
1465
|
+
# puts cidr4.desc
|
1323
1466
|
#
|
1324
1467
|
def resize!(options)
|
1325
|
-
if (
|
1326
|
-
|
1468
|
+
if (options.kind_of?(Hash))
|
1469
|
+
if ( !options.has_key?(:Netmask) )
|
1470
|
+
raise Argumenterror, "Missing argument: Netmask."
|
1471
|
+
end
|
1472
|
+
bits = options[:Netmask]
|
1473
|
+
elsif (options.kind_of?(Integer))
|
1474
|
+
bits = options
|
1475
|
+
else
|
1476
|
+
raise Argumenterror, "Integer or Hash expected, but " +
|
1327
1477
|
"#{options.class} provided."
|
1328
1478
|
end
|
1329
|
-
|
1330
|
-
if ( !options.has_key?(:Subnet) )
|
1331
|
-
raise Argumenterror, "Missing argument: Subnet."
|
1332
|
-
end
|
1333
|
-
bits = options[:Subnet]
|
1334
1479
|
|
1335
1480
|
IPAdmin.validate_ip_netmask(:Netmask => bits, :Version => @version)
|
1336
1481
|
netmask = IPAdmin.pack_ip_netmask(:Netmask => bits, :Version => @version)
|
@@ -1344,7 +1489,7 @@ class CIDR
|
|
1344
1489
|
@ip = @network
|
1345
1490
|
end
|
1346
1491
|
|
1347
|
-
return(
|
1492
|
+
return(true)
|
1348
1493
|
end
|
1349
1494
|
|
1350
1495
|
#======================================#
|
@@ -1364,8 +1509,8 @@ class CIDR
|
|
1364
1509
|
# - Returns:
|
1365
1510
|
# * Integer
|
1366
1511
|
#
|
1367
|
-
#
|
1368
|
-
# puts cidr4.size()
|
1512
|
+
# Examples:
|
1513
|
+
# puts cidr4.size()
|
1369
1514
|
#
|
1370
1515
|
def size()
|
1371
1516
|
return(@hostmask + 1)
|
@@ -1380,11 +1525,14 @@ class CIDR
|
|
1380
1525
|
# subnet()
|
1381
1526
|
#==============================================================================#
|
1382
1527
|
|
1383
|
-
# Subnet this object.
|
1384
|
-
#
|
1385
|
-
#
|
1386
|
-
#
|
1387
|
-
# then the
|
1528
|
+
# Subnet this object. There are 2 ways to subnet:
|
1529
|
+
# * By providing the netmask of the new subnets in :Subnet.
|
1530
|
+
# * By providing the number of IP addresses needed in the new subnets in :IPCount
|
1531
|
+
#
|
1532
|
+
# If :Mincount is not provided, then the CIDR will be fully subnetted. Otherwise,
|
1533
|
+
# if provided then :Mincount number of subnets of requested size will be returned and
|
1534
|
+
# the remainder of the subnets will be summarized as much as possible. If neither :Subnet
|
1535
|
+
# or :IPCount is provided, then the current CIDR will be split in half.
|
1388
1536
|
#
|
1389
1537
|
# - Arguments:
|
1390
1538
|
# * Optional hash with the following fields:
|
@@ -1395,15 +1543,14 @@ class CIDR
|
|
1395
1543
|
# - :Subnet -- Netmask (in bits) of new subnets - Integer (optional)
|
1396
1544
|
#
|
1397
1545
|
# - Returns:
|
1398
|
-
# * Array of CIDR
|
1546
|
+
# * Array of CIDR address Strings or IPAdmin::CIDR objects
|
1399
1547
|
#
|
1400
1548
|
# - Notes:
|
1401
1549
|
# * :Subnet always takes precedence over :IPCount.
|
1402
1550
|
#
|
1403
|
-
#
|
1551
|
+
# Examples:
|
1404
1552
|
# cidr_list = cidr4.subnet(:Subnet => 28, :MinCount => 3)
|
1405
1553
|
# cidr_list = cidr4.subnet(:IPCount => 19)
|
1406
|
-
# puts cidr_list[0] --> 192.168.1.0/27
|
1407
1554
|
#
|
1408
1555
|
def subnet(options=nil)
|
1409
1556
|
my_network = self.packed_network
|
@@ -1516,6 +1663,61 @@ class CIDR
|
|
1516
1663
|
#
|
1517
1664
|
#======================================#
|
1518
1665
|
|
1666
|
+
|
1667
|
+
# PRIVATE INSTANCE METHODS
|
1668
|
+
private
|
1669
|
+
|
1670
|
+
|
1671
|
+
#==============================================================================#
|
1672
|
+
# make_subnets_from_base_and_ip_count()
|
1673
|
+
#==============================================================================#
|
1674
|
+
|
1675
|
+
# Make CIDR addresses from a base addr and an number of ip's to encapsulate.
|
1676
|
+
#
|
1677
|
+
# - Arguments:
|
1678
|
+
# * base ip as packed integer
|
1679
|
+
# * number of ip's required
|
1680
|
+
#
|
1681
|
+
# - Returns:
|
1682
|
+
# * array of IPAdmin::CIDR objects
|
1683
|
+
#
|
1684
|
+
def make_subnets_from_base_and_ip_count(base_addr,ip_count)
|
1685
|
+
list = []
|
1686
|
+
until (ip_count == 0)
|
1687
|
+
mask = @all_f
|
1688
|
+
multiplier = 0
|
1689
|
+
bitstep = 0
|
1690
|
+
last_addr = base_addr
|
1691
|
+
done = false
|
1692
|
+
until (done == true)
|
1693
|
+
if (bitstep < ip_count && (base_addr & mask == last_addr & mask) )
|
1694
|
+
multiplier += 1
|
1695
|
+
elsif (bitstep > ip_count || (base_addr & mask != last_addr & mask) )
|
1696
|
+
multiplier -= 1
|
1697
|
+
done = true
|
1698
|
+
else
|
1699
|
+
done = true
|
1700
|
+
end
|
1701
|
+
bitstep = 2**multiplier
|
1702
|
+
mask = @all_f << multiplier & @all_f
|
1703
|
+
last_addr = base_addr + bitstep - 1
|
1704
|
+
end
|
1705
|
+
|
1706
|
+
list.push(IPAdmin::CIDR.new(:PackedIP => base_addr,
|
1707
|
+
:PackedNetmask => mask,
|
1708
|
+
:Version => self.version))
|
1709
|
+
ip_count -= bitstep
|
1710
|
+
base_addr += bitstep
|
1711
|
+
end
|
1712
|
+
|
1713
|
+
return(list)
|
1714
|
+
end
|
1715
|
+
|
1716
|
+
#======================================#
|
1717
|
+
#
|
1718
|
+
#======================================#
|
1719
|
+
|
1720
|
+
|
1519
1721
|
end
|
1520
1722
|
|
1521
1723
|
end # module IPAdmin
|