ipadmin 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +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
|