netaddr 1.2.0 → 1.3.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/changelog +14 -6
- data/lib/cidr.rb +497 -225
- data/lib/cidr_shortcuts.rb +21 -21
- data/lib/eui.rb +162 -133
- data/lib/ip_math.rb +45 -27
- data/lib/methods.rb +187 -178
- data/lib/{net_addr.rb → netaddr.rb} +3 -1
- data/lib/tree.rb +87 -52
- data/lib/validation_shortcuts.rb +10 -10
- data/tests/cidr_test.rb +253 -167
- data/tests/eui_test.rb +39 -25
- data/tests/methods_test.rb +100 -118
- data/tests/tree_test.rb +99 -56
- metadata +12 -12
data/changelog
CHANGED
@@ -1,16 +1,25 @@
|
|
1
1
|
|
2
2
|
==Version
|
3
|
-
|
3
|
+
====1.3.0
|
4
4
|
|
5
|
+
===New Features
|
6
|
+
* added CIDR#[]
|
7
|
+
* added CIDR#succ (CIDR objects may now be used as args for the standard Ruby Range class)
|
8
|
+
* added CIDR#allocate_rfc3531
|
9
|
+
* added CIDR#to_i
|
10
|
+
* added CIDRv6.unique_local
|
11
|
+
* added EUI48#to_eui64
|
12
|
+
* added EUI#to_i
|
13
|
+
* added EUI#to_s
|
5
14
|
|
6
|
-
===
|
15
|
+
===Changes
|
16
|
+
* deprecated 'packed' methods
|
7
17
|
|
8
|
-
* users may directly modify CIDR objects stored within a Tree,
|
9
|
-
essentially invalidating the structure of that Tree
|
10
18
|
|
19
|
+
==Version
|
20
|
+
====1.2.0
|
11
21
|
|
12
22
|
===Changes
|
13
|
-
|
14
23
|
* CIDRv4#new and CIDRv6#new methods have been changed for the sake of speed improvements.
|
15
24
|
Please use the CIDR#create method instead.
|
16
25
|
* changes to CIDR#wildcard_mask
|
@@ -20,7 +29,6 @@
|
|
20
29
|
|
21
30
|
|
22
31
|
===New Features
|
23
|
-
|
24
32
|
* speed improvements
|
25
33
|
* added CIDR#set_wildcard_mask
|
26
34
|
* added <=>, >, <, == methods to CIDR
|
data/lib/cidr.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin rdoc
|
2
|
-
Copyleft (c) 2006 Dustin Spinhirne
|
2
|
+
Copyleft (c) 2006 Dustin Spinhirne
|
3
3
|
|
4
4
|
Licensed under the same terms as Ruby, No Warranty is provided.
|
5
5
|
=end
|
@@ -10,21 +10,21 @@ module NetAddr
|
|
10
10
|
#
|
11
11
|
#A class & series of methods for creating and manipulating CIDR network
|
12
12
|
#addresses. Both IPv4 and IPv6 are supported.
|
13
|
-
#
|
13
|
+
#
|
14
14
|
#This class accepts a CIDR address, via the CIDR.create method,
|
15
15
|
#in (x.x.x.x/yy or xxxx::/yy) format for IPv4 and IPv6, or (x.x.x.x/y.y.y.y) for IPv4.
|
16
16
|
#CIDR.create then creates either a CIDRv4 or CIDRv6 object. An optional tag hash may be
|
17
17
|
#provided with each CIDR as a way of adding custom labels.
|
18
|
-
#
|
18
|
+
#
|
19
19
|
#Upon initialization, the IP version is auto-detected and assigned to the
|
20
20
|
#CIDR. The original IP/Netmask passed within the CIDR is stored and then
|
21
21
|
#used to determine the confines of the CIDR block. Various properties of the
|
22
22
|
#CIDR block are accessible via several different methods. There are also
|
23
23
|
#methods for modifying the CIDR or creating new derivative CIDR's.
|
24
|
-
#
|
24
|
+
#
|
25
25
|
#An example CIDR object is as follows:
|
26
26
|
# NetAddr::CIDR.create('192.168.1.20/24')
|
27
|
-
#
|
27
|
+
#
|
28
28
|
#This would create a CIDR object (192.168.1.0/24) with the following properties:
|
29
29
|
# version = 4
|
30
30
|
# base network = 192.168.1.0
|
@@ -32,7 +32,7 @@ module NetAddr
|
|
32
32
|
# netmask = /24 (255.255.255.0)
|
33
33
|
# size = 256 IP addresses
|
34
34
|
# broadcast = 192.168.1.255
|
35
|
-
#
|
35
|
+
#
|
36
36
|
#You can see how the CIDR object is based around the entire IP space
|
37
37
|
#defined by the provided IP/Netmask pair, and not necessarily the individual
|
38
38
|
#IP address itself.
|
@@ -70,52 +70,6 @@ private_class_method :new
|
|
70
70
|
@tag = new_tag
|
71
71
|
end
|
72
72
|
|
73
|
-
#==============================================================================#
|
74
|
-
# initialize()
|
75
|
-
#==============================================================================#
|
76
|
-
|
77
|
-
# This method performs absolutely no error checking, and is meant to be used only by
|
78
|
-
# other internal methods for the sake of the speedier creation of CIDR objects.
|
79
|
-
# Please consider using #create unless you know what you are doing with 100% certainty.
|
80
|
-
#
|
81
|
-
#===Arguments:
|
82
|
-
#* ip - Integer representing an ip address
|
83
|
-
#* netmask - Integer representing a binary mask
|
84
|
-
#* tag - Hash used to append custom tags to CIDR
|
85
|
-
#* wildcard_mask - Integer representing a binary mask
|
86
|
-
#* wildcard_mask_bit_flipped - indicates whether or not the wildcard_mask is bit-flipped or not
|
87
|
-
#
|
88
|
-
def initialize(ip, netmask=nil, tag={}, wildcard_mask=nil, wildcard_mask_bit_flipped=false)
|
89
|
-
@ip = ip
|
90
|
-
|
91
|
-
if ( self.kind_of?(NetAddr::CIDRv4) )
|
92
|
-
@version = 4
|
93
|
-
@address_len = 32
|
94
|
-
else
|
95
|
-
@version = 6
|
96
|
-
@address_len = 128
|
97
|
-
end
|
98
|
-
@all_f = 2**@address_len - 1
|
99
|
-
|
100
|
-
if (netmask)
|
101
|
-
@netmask = netmask
|
102
|
-
else
|
103
|
-
@netmask = 2**@address_len - 1
|
104
|
-
end
|
105
|
-
|
106
|
-
@network = (@ip & @netmask)
|
107
|
-
@hostmask = @netmask ^ @all_f
|
108
|
-
@tag = tag
|
109
|
-
|
110
|
-
if (!wildcard_mask)
|
111
|
-
@wildcard_mask = @netmask
|
112
|
-
else
|
113
|
-
@wildcard_mask = wildcard_mask
|
114
|
-
@wildcard_mask = ~@wildcard_mask if (wildcard_mask_bit_flipped)
|
115
|
-
end
|
116
|
-
|
117
|
-
end
|
118
|
-
|
119
73
|
#==============================================================================#
|
120
74
|
# create()
|
121
75
|
#==============================================================================#
|
@@ -124,13 +78,13 @@ private_class_method :new
|
|
124
78
|
#Create a new CIDRv4 or CIDRv6 object.
|
125
79
|
#CIDR formatted netmasks take precedence over extended formatted ones.
|
126
80
|
#CIDR address defaults to a host network (/32 or /128) if netmask not provided.
|
127
|
-
#:
|
81
|
+
#:Mask takes precedence over netmask given within CIDR addresses.
|
128
82
|
#Version will be auto-detected if not specified.
|
129
83
|
#
|
130
84
|
# NetAddr::CIDR.create('192.168.1.1/24')
|
131
85
|
# NetAddr::CIDR.create('192.168.1.1 255.255.255.0')
|
132
86
|
# NetAddr::CIDR.create(0x0a010001,
|
133
|
-
# :
|
87
|
+
# :Mask => 0xffffff00
|
134
88
|
# :Version => 4)
|
135
89
|
# NetAddr::CIDR.create('192.168.1.1',
|
136
90
|
# :WildcardMask => ['0.7.0.255', true])
|
@@ -144,9 +98,9 @@ private_class_method :new
|
|
144
98
|
# NetAddr::CIDR.create('::ffff:192.168.1.1/96')
|
145
99
|
#
|
146
100
|
#===Arguments:
|
147
|
-
#* addr = CIDR address as a String, or
|
101
|
+
#* addr = CIDR address as a String, or an IP address as an Integer
|
148
102
|
#* options = Hash with the following keys:
|
149
|
-
# :
|
103
|
+
# :Mask -- Integer representing a binary IP Netmask
|
150
104
|
# :Version -- IP version - Integer
|
151
105
|
# :Tag -- Custom descriptor tag - Hash, tag => value.
|
152
106
|
# :WildcardMask -- 2 element Array. First element contains a special bit mask used for
|
@@ -154,10 +108,10 @@ private_class_method :new
|
|
154
108
|
# bit mask is bit flipped.
|
155
109
|
#
|
156
110
|
def CIDR.create(addr, options=nil)
|
157
|
-
known_args = [:
|
111
|
+
known_args = [:Mask, :Version, :Tag, :WildcardMask]
|
158
112
|
ip, netmask, tag = nil, nil, {}
|
159
113
|
version, wildcard_mask ,wildcard_mask_bit_flipped = nil, nil, false
|
160
|
-
|
114
|
+
netmask_int, all_f = nil, nil
|
161
115
|
|
162
116
|
# validate options
|
163
117
|
if (options)
|
@@ -165,10 +119,10 @@ private_class_method :new
|
|
165
119
|
"#{options.class} provided." if (!options.kind_of?(Hash) )
|
166
120
|
NetAddr.validate_args(options.keys,known_args)
|
167
121
|
|
168
|
-
if (options.has_key?(:
|
169
|
-
|
170
|
-
raise ArgumentError, "Expected Integer, but #{
|
171
|
-
"provided for option :
|
122
|
+
if (options.has_key?(:Mask))
|
123
|
+
netmask_int = options[:Mask]
|
124
|
+
raise ArgumentError, "Expected Integer, but #{netmask_int.class} " +
|
125
|
+
"provided for option :Mask." if (!netmask_int.kind_of?(Integer))
|
172
126
|
end
|
173
127
|
|
174
128
|
if (options.has_key?(:Tag))
|
@@ -239,10 +193,10 @@ private_class_method :new
|
|
239
193
|
all_f = 2**32-1
|
240
194
|
all_f = 2**128-1 if (version == 6)
|
241
195
|
|
242
|
-
# set netmask.
|
243
|
-
if (
|
244
|
-
NetAddr.validate_netmask_int(
|
245
|
-
netmask =
|
196
|
+
# set netmask. netmask_int takes precedence. set to all_f if no netmask provided
|
197
|
+
if (netmask_int)
|
198
|
+
NetAddr.validate_netmask_int(netmask_int,version,true)
|
199
|
+
netmask = netmask_int
|
246
200
|
elsif (netmask)
|
247
201
|
NetAddr.validate_netmask_str(netmask,version)
|
248
202
|
netmask = NetAddr.netmask_str_to_int(netmask, version)
|
@@ -268,22 +222,70 @@ private_class_method :new
|
|
268
222
|
end
|
269
223
|
|
270
224
|
#==============================================================================#
|
271
|
-
#
|
225
|
+
# initialize()
|
226
|
+
#==============================================================================#
|
227
|
+
|
228
|
+
# This method performs absolutely no error checking, and is meant to be used only by
|
229
|
+
# other internal methods for the sake of the speedier creation of CIDR objects.
|
230
|
+
# Please consider using #create unless you know what you are doing with 100% certainty.
|
231
|
+
#
|
232
|
+
#===Arguments:
|
233
|
+
#* ip - Integer representing an ip address
|
234
|
+
#* netmask - Integer representing a binary netmask
|
235
|
+
#* tag - Hash used to append custom tags to CIDR
|
236
|
+
#* wildcard_mask - Integer representing a binary mask
|
237
|
+
#* wildcard_mask_bit_flipped - indicates whether or not the wildcard_mask is bit-flipped or not
|
238
|
+
#
|
239
|
+
def initialize(ip, netmask=nil, tag={}, wildcard_mask=nil, wildcard_mask_bit_flipped=false)
|
240
|
+
@ip = ip
|
241
|
+
|
242
|
+
if ( self.kind_of?(NetAddr::CIDRv4) )
|
243
|
+
@version = 4
|
244
|
+
@address_len = 32
|
245
|
+
else
|
246
|
+
@version = 6
|
247
|
+
@address_len = 128
|
248
|
+
end
|
249
|
+
@all_f = 2**@address_len - 1
|
250
|
+
|
251
|
+
if (netmask)
|
252
|
+
@netmask = netmask
|
253
|
+
else
|
254
|
+
@netmask = 2**@address_len - 1
|
255
|
+
end
|
256
|
+
|
257
|
+
@network = (@ip & @netmask)
|
258
|
+
@hostmask = @netmask ^ @all_f
|
259
|
+
@tag = tag
|
260
|
+
|
261
|
+
if (!wildcard_mask)
|
262
|
+
@wildcard_mask = @netmask
|
263
|
+
else
|
264
|
+
@wildcard_mask = wildcard_mask
|
265
|
+
@wildcard_mask = ~@wildcard_mask if (wildcard_mask_bit_flipped)
|
266
|
+
end
|
267
|
+
|
268
|
+
end
|
269
|
+
|
270
|
+
#==============================================================================#
|
271
|
+
# <()
|
272
272
|
#==============================================================================#
|
273
273
|
|
274
274
|
#===Synopsis
|
275
|
-
#Compare the sort order of the current CIDR with a provided CIDR and return
|
276
|
-
|
277
|
-
|
278
|
-
|
275
|
+
#Compare the sort order of the current CIDR with a provided CIDR and return true
|
276
|
+
#if current CIDR is less than provided CIDR.
|
277
|
+
#
|
278
|
+
# Example:
|
279
|
+
# cidr = NetAddr::CIDR.create('192.168.1.0/24')
|
280
|
+
# cidr < '192.168.2.0/24' => true
|
279
281
|
#
|
280
282
|
#===Arguments:
|
281
283
|
#* CIDR address or NetAddr::CIDR object
|
282
284
|
#
|
283
285
|
#===Returns:
|
284
|
-
#*
|
286
|
+
#* true or false
|
285
287
|
#
|
286
|
-
def
|
288
|
+
def <(cidr)
|
287
289
|
if (!cidr.kind_of?(NetAddr::CIDR))
|
288
290
|
begin
|
289
291
|
cidr = NetAddr::CIDR.create(cidr)
|
@@ -299,26 +301,35 @@ private_class_method :new
|
|
299
301
|
end
|
300
302
|
|
301
303
|
# compare
|
302
|
-
|
304
|
+
lt = false
|
305
|
+
lt = true if ( NetAddr.cidr_gt_lt(self,cidr) == -1)
|
303
306
|
|
304
|
-
return(
|
307
|
+
return(lt)
|
305
308
|
end
|
306
309
|
|
307
310
|
#==============================================================================#
|
308
|
-
#
|
311
|
+
# <=>()
|
309
312
|
#==============================================================================#
|
310
313
|
|
311
314
|
#===Synopsis
|
312
|
-
#Compare the sort order of the current CIDR with a provided CIDR and return
|
313
|
-
|
315
|
+
#Compare the sort order of the current CIDR with a provided CIDR and return:
|
316
|
+
#* 1 if the current CIDR is greater than the provided CIDR
|
317
|
+
#* 0 if the current CIDR and the provided CIDR are equal (base address and netmask are equal)
|
318
|
+
#* -1 if the current CIDR is less than the provided CIDR
|
319
|
+
#
|
320
|
+
# Example:
|
321
|
+
# cidr = NetAddr::CIDR.create('192.168.1.0/24')
|
322
|
+
# cidr <=> '192.168.2.0/24' => -1
|
323
|
+
# cidr <=> '192.168.0.0/24' => 1
|
324
|
+
# cidr <=> '192.168.1.0/24' => 0
|
314
325
|
#
|
315
326
|
#===Arguments:
|
316
327
|
#* CIDR address or NetAddr::CIDR object
|
317
328
|
#
|
318
329
|
#===Returns:
|
319
|
-
#*
|
330
|
+
#* Integer
|
320
331
|
#
|
321
|
-
def
|
332
|
+
def <=>(cidr)
|
322
333
|
if (!cidr.kind_of?(NetAddr::CIDR))
|
323
334
|
begin
|
324
335
|
cidr = NetAddr::CIDR.create(cidr)
|
@@ -334,19 +345,22 @@ private_class_method :new
|
|
334
345
|
end
|
335
346
|
|
336
347
|
# compare
|
337
|
-
|
338
|
-
gt = true if ( NetAddr.cidr_gt_lt(self,cidr) == 1)
|
348
|
+
comparasin = NetAddr.cidr_gt_lt(self,cidr)
|
339
349
|
|
340
|
-
return(
|
350
|
+
return(comparasin)
|
341
351
|
end
|
342
352
|
|
343
353
|
#==============================================================================#
|
344
|
-
#
|
354
|
+
# ==()
|
345
355
|
#==============================================================================#
|
346
356
|
|
347
357
|
#===Synopsis
|
348
358
|
#Compare the sort order of the current CIDR with a provided CIDR and return true
|
349
|
-
#if current CIDR is
|
359
|
+
#if current CIDR is equal to the provided CIDR.
|
360
|
+
#
|
361
|
+
# Example:
|
362
|
+
# cidr = NetAddr::CIDR.create('192.168.1.0/24')
|
363
|
+
# cidr == '192.168.1.0/24' => true
|
350
364
|
#
|
351
365
|
#===Arguments:
|
352
366
|
#* CIDR address or NetAddr::CIDR object
|
@@ -354,7 +368,7 @@ private_class_method :new
|
|
354
368
|
#===Returns:
|
355
369
|
#* true or false
|
356
370
|
#
|
357
|
-
def
|
371
|
+
def ==(cidr)
|
358
372
|
if (!cidr.kind_of?(NetAddr::CIDR))
|
359
373
|
begin
|
360
374
|
cidr = NetAddr::CIDR.create(cidr)
|
@@ -370,19 +384,24 @@ private_class_method :new
|
|
370
384
|
end
|
371
385
|
|
372
386
|
# compare
|
373
|
-
|
374
|
-
|
387
|
+
eq = false
|
388
|
+
eq = true if ( NetAddr.cidr_gt_lt(self,cidr) == 0)
|
375
389
|
|
376
|
-
return(
|
390
|
+
return(eq)
|
377
391
|
end
|
392
|
+
alias :eql? :==
|
378
393
|
|
379
394
|
#==============================================================================#
|
380
|
-
#
|
395
|
+
# >()
|
381
396
|
#==============================================================================#
|
382
397
|
|
383
398
|
#===Synopsis
|
384
399
|
#Compare the sort order of the current CIDR with a provided CIDR and return true
|
385
|
-
#if current CIDR is
|
400
|
+
#if current CIDR is greater than provided CIDR.
|
401
|
+
#
|
402
|
+
# Example:
|
403
|
+
# cidr = NetAddr::CIDR.create('192.168.1.0/24')
|
404
|
+
# cidr > '192.168.0.0/24' => true
|
386
405
|
#
|
387
406
|
#===Arguments:
|
388
407
|
#* CIDR address or NetAddr::CIDR object
|
@@ -390,7 +409,7 @@ private_class_method :new
|
|
390
409
|
#===Returns:
|
391
410
|
#* true or false
|
392
411
|
#
|
393
|
-
def
|
412
|
+
def >(cidr)
|
394
413
|
if (!cidr.kind_of?(NetAddr::CIDR))
|
395
414
|
begin
|
396
415
|
cidr = NetAddr::CIDR.create(cidr)
|
@@ -406,21 +425,156 @@ private_class_method :new
|
|
406
425
|
end
|
407
426
|
|
408
427
|
# compare
|
409
|
-
|
410
|
-
|
428
|
+
gt = false
|
429
|
+
gt = true if ( NetAddr.cidr_gt_lt(self,cidr) == 1)
|
411
430
|
|
412
|
-
return(
|
431
|
+
return(gt)
|
432
|
+
end
|
433
|
+
|
434
|
+
#==============================================================================#
|
435
|
+
# []
|
436
|
+
#==============================================================================#
|
437
|
+
|
438
|
+
#===Synopsis
|
439
|
+
#Provide the IP at the given index of the CIDR.
|
440
|
+
#
|
441
|
+
# Example:
|
442
|
+
# cidr4 = NetAddr::CIDR.create('192.168.1.0/24')
|
443
|
+
# cidr4[1] => 192.168.1.1/32
|
444
|
+
#
|
445
|
+
#===Arguments:
|
446
|
+
#* index = Index number as an Integer
|
447
|
+
#
|
448
|
+
#===Returns:
|
449
|
+
#* NetAddr::CIDR object.
|
450
|
+
#
|
451
|
+
def [](index)
|
452
|
+
raise ArgumentError, "Integer expected for argument 'index' but " +
|
453
|
+
"#{index.class} provided." if (!index.kind_of?(Integer) )
|
454
|
+
|
455
|
+
addr = @network + index
|
456
|
+
if ( (@hostmask | addr) == (@hostmask | @network) )
|
457
|
+
addr = NetAddr.cidr_build(@version, addr)
|
458
|
+
else
|
459
|
+
raise BoundaryError, "Index of #{index} returns IP that is out of " +
|
460
|
+
"bounds of CIDR network."
|
461
|
+
end
|
462
|
+
|
463
|
+
return(addr)
|
464
|
+
end
|
465
|
+
|
466
|
+
#==============================================================================#
|
467
|
+
# allocate_rfc3531()
|
468
|
+
#==============================================================================#
|
469
|
+
|
470
|
+
#===Synopsis
|
471
|
+
#RFC 3531 describes a flexible method for IP subnet allocation from
|
472
|
+
#a larger parent network. Given the new netmask for subnet allocations from this CIDR,
|
473
|
+
#provide a list of those subnets arranged by the order in which they should be allocated.
|
474
|
+
#
|
475
|
+
# Example:
|
476
|
+
# cidr = NetAddr::CIDR.create('192.168.0.0/16')
|
477
|
+
# cidr.allocate_rfc3531(21, :Strategy => :centermost) => ["192.168.0.0/21"... "192.168.248.0/21"]
|
478
|
+
#
|
479
|
+
#===Arguments:
|
480
|
+
#* netmask (in bits) for all new subnet allocations
|
481
|
+
#* options = Hash with the following keys:
|
482
|
+
# :Objectify -- if true, return NetAddr::CIDR objects
|
483
|
+
# :Short -- if true, return IPv6 addresses in short-hand notation
|
484
|
+
# :Strategy -- allocation strategy to use. must be either :centermost or :leftmost (default)
|
485
|
+
#
|
486
|
+
#===Returns:
|
487
|
+
#* Array of Strings or CIDR objects
|
488
|
+
#
|
489
|
+
def allocate_rfc3531(netmask, options=nil)
|
490
|
+
short = false
|
491
|
+
objectify = false
|
492
|
+
strategy = :leftmost
|
493
|
+
|
494
|
+
# validate args
|
495
|
+
raise ArgumentError, "Expected Integer for argument (netmask), but #{max.class} received." if ( !netmask.kind_of?(Integer) )
|
496
|
+
raise BoundaryError, "Netmask (#{netmask}) is invalid for a version #{self.version} address." if (netmask > @address_len)
|
497
|
+
raise BoundaryError, "Netmask (#{netmask}) cannot be less than #{self.bits}." if (netmask < self.bits)
|
498
|
+
known_args = [:Objectify, :Short, :Strategy]
|
499
|
+
if (options)
|
500
|
+
if (!options.kind_of? Hash)
|
501
|
+
raise ArgumentError, "Expected Hash, but #{options.class} provided."
|
502
|
+
end
|
503
|
+
NetAddr.validate_args(options.keys,known_args)
|
504
|
+
|
505
|
+
if( options.has_key?(:Objectify) && options[:Objectify] == true )
|
506
|
+
objectify = true
|
507
|
+
end
|
508
|
+
|
509
|
+
if( options.has_key?(:Short) && options[:Short] == true )
|
510
|
+
short = true
|
511
|
+
end
|
512
|
+
|
513
|
+
if( options.has_key?(:Strategy))
|
514
|
+
strategy = options[:Strategy]
|
515
|
+
raise ArgumentError, "Argument :Strategy must be either :leftmost or :centermost." if (strategy != :leftmost && strategy != :centermost)
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
subnet_bits = netmask - self.bits
|
520
|
+
net_lshift = @address_len - netmask
|
521
|
+
new_mask = NetAddr.bits_to_mask(netmask,self.version)
|
522
|
+
cidr_list = []
|
523
|
+
if (strategy == :leftmost)
|
524
|
+
(0..(2**subnet_bits)-1).each do |num|
|
525
|
+
mirror = NetAddr.binary_mirror(num, subnet_bits)
|
526
|
+
|
527
|
+
if (!objectify)
|
528
|
+
my_ip_s = NetAddr.ip_int_to_str(@network | (mirror << net_lshift), @version)
|
529
|
+
my_ip_s = NetAddr.shorten(my_ip_s) if (short && @version == 6)
|
530
|
+
cidr_list.push( my_ip_s << '/' << netmask.to_s )
|
531
|
+
else
|
532
|
+
cidr_list.push( NetAddr.cidr_build(@version, @network | (mirror << net_lshift), new_mask ) )
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
else # :centermost
|
537
|
+
round = 1
|
538
|
+
bit_count = 1
|
539
|
+
lshift = subnet_bits/2
|
540
|
+
lshift -= 1 if (subnet_bits & 1 == 0) # if subnet_bits is even number
|
541
|
+
|
542
|
+
unique = {}
|
543
|
+
until (bit_count > subnet_bits)
|
544
|
+
(0..2**bit_count-1).each do |num|
|
545
|
+
shifted = num << lshift
|
546
|
+
if ( !unique.has_key?(shifted) )
|
547
|
+
if (!objectify)
|
548
|
+
my_ip_s = NetAddr.ip_int_to_str(@network | (shifted << net_lshift), @version)
|
549
|
+
my_ip_s = NetAddr.shorten(my_ip_s) if (short && @version == 6)
|
550
|
+
cidr_list.push( my_ip_s << '/' << netmask.to_s )
|
551
|
+
else
|
552
|
+
cidr_list.push( NetAddr.cidr_build(@version, @network | (shifted << net_lshift), new_mask ) )
|
553
|
+
end
|
554
|
+
unique[shifted] = true
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
lshift -= 1 if (round & 1 == 0) # if even round
|
559
|
+
round += 1
|
560
|
+
bit_count += 1
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
564
|
+
return(cidr_list)
|
413
565
|
end
|
414
|
-
alias :eql? :==
|
415
566
|
|
416
567
|
#==============================================================================#
|
417
568
|
# arpa()
|
418
569
|
#==============================================================================#
|
419
570
|
|
420
571
|
#===Synopsis
|
421
|
-
#Depending on the IP version of the current CIDR,
|
572
|
+
#Depending on the IP version of the current CIDR,
|
422
573
|
#return either an in-addr.arpa. or ip6.arpa. string. The netmask will be used
|
423
574
|
#to determine the length of the returned string.
|
575
|
+
# Example:
|
576
|
+
# cidr = NetAddr::CIDR.create('192.168.1.1/24')
|
577
|
+
# cidr.arpa => "1.168.192.in-addr.arpa."
|
424
578
|
#
|
425
579
|
#===Arguments:
|
426
580
|
#* none
|
@@ -476,6 +630,9 @@ private_class_method :new
|
|
476
630
|
|
477
631
|
#===Synopsis
|
478
632
|
#Provide number of bits in Netmask.
|
633
|
+
# Example:
|
634
|
+
# cidr = NetAddr::CIDR.create('192.168.1.1/24')
|
635
|
+
# cidr.bits => 24
|
479
636
|
#
|
480
637
|
#===Arguments:
|
481
638
|
#* none
|
@@ -498,10 +655,12 @@ private_class_method :new
|
|
498
655
|
#* -1 if the current CIDR is contained by (is subnet of) the provided CIDR
|
499
656
|
#* nil if the two CIDR addresses are unrelated
|
500
657
|
#
|
501
|
-
#
|
502
|
-
#
|
503
|
-
#
|
504
|
-
#
|
658
|
+
# Example:
|
659
|
+
# cidr = NetAddr::CIDR.create('192.168.1.0/24')
|
660
|
+
# cidr.cmp('192.168.1.0/25') => 1
|
661
|
+
# cidr.cmp('192.168.1.0/24') => 0
|
662
|
+
# cidr.cmp('192.168.0.0/23') => -1
|
663
|
+
# cidr.cmp('10.0.0.0/24') => nil
|
505
664
|
#
|
506
665
|
#===Arguments:
|
507
666
|
#* CIDR address or NetAddr::CIDR object
|
@@ -538,11 +697,12 @@ end
|
|
538
697
|
#Determines if this CIDR contains (is supernet of)
|
539
698
|
#the provided CIDR address or NetAddr::CIDR object.
|
540
699
|
#
|
541
|
-
#
|
700
|
+
# Example:
|
701
|
+
# cidr4 = NetAddr::CIDR.create('192.168.1.0/24')
|
542
702
|
# cidr6 = NetAddr::CIDR.create('fec0::/64')
|
543
703
|
# cidr6_2 = NetAddr::CIDR.create('fec0::/96')
|
544
|
-
# cidr4.contains?('192.168.1.2')
|
545
|
-
# cidr6.contains?(cidr6_2)
|
704
|
+
# cidr4.contains?('192.168.1.2') => true
|
705
|
+
# cidr6.contains?(cidr6_2) => true
|
546
706
|
#
|
547
707
|
#===Arguments:
|
548
708
|
#* cidr = CIDR address or NetAddr::CIDR object
|
@@ -579,11 +739,12 @@ end
|
|
579
739
|
#===Synopsis
|
580
740
|
#Returns network/netmask in CIDR format.
|
581
741
|
#
|
742
|
+
# Example:
|
582
743
|
# cidr4 = NetAddr::CIDR.create('192.168.1.1/24')
|
583
744
|
# cidr6 = NetAddr::CIDR.create('fec0::/64')
|
584
|
-
# cidr4.desc(:IP => true)
|
585
|
-
# cidr4.desc()
|
586
|
-
# cidr6.desc(:Short => true)
|
745
|
+
# cidr4.desc(:IP => true) => "192.168.1.1/24"
|
746
|
+
# cidr4.desc() => "192.168.1.0/24"
|
747
|
+
# cidr6.desc(:Short => true) => "fec0::/64"
|
587
748
|
#
|
588
749
|
#===Arguments:
|
589
750
|
#* options = Optional hash with the following keys:
|
@@ -631,10 +792,11 @@ end
|
|
631
792
|
#===Synopsis
|
632
793
|
#Provide all IP addresses contained within the IP space of this CIDR.
|
633
794
|
#
|
634
|
-
#
|
635
|
-
#
|
636
|
-
#
|
637
|
-
#
|
795
|
+
# Example:
|
796
|
+
# cidr4 = NetAddr::CIDR.create('192.168.1.1/24')
|
797
|
+
# cidr6 = NetAddr::CIDR.create('fec0::/64')
|
798
|
+
# cidr4.enumerate(:Limit => 4, :Bitstep => 32)
|
799
|
+
# cidr6.enumerate(:Limit => 4, :Bitstep => 32, :Objectify => true)
|
638
800
|
#
|
639
801
|
#===Arguments:
|
640
802
|
#* options = Hash with the following keys:
|
@@ -707,6 +869,7 @@ end
|
|
707
869
|
#Given a list of subnets of the current CIDR, return a new list with any
|
708
870
|
#holes (missing subnets) filled in.
|
709
871
|
#
|
872
|
+
# Example:
|
710
873
|
# cidr4 = NetAddr::CIDR.create('192.168.1.0/24')
|
711
874
|
# cidr4.fill_in(['192.168.1.0/27','192.168.1.64/26','192.168.1.128/25'])
|
712
875
|
#
|
@@ -784,6 +947,10 @@ end
|
|
784
947
|
#===Synopsis
|
785
948
|
#Provide original IP address passed during initialization.
|
786
949
|
#
|
950
|
+
# Example:
|
951
|
+
# cidr = NetAddr::CIDR.create('192.168.1.1/24')
|
952
|
+
# cidr.ip => "192.168.1.1"
|
953
|
+
#
|
787
954
|
#===Arguments:
|
788
955
|
#* options = Hash with the following keys:
|
789
956
|
# :Objectify -- if true, return NetAddr::CIDR object
|
@@ -832,6 +999,7 @@ end
|
|
832
999
|
#Determines if this CIDR is contained within (is subnet of)
|
833
1000
|
#the provided CIDR address or NetAddr::CIDR object.
|
834
1001
|
#
|
1002
|
+
# Example:
|
835
1003
|
# cidr4 = NetAddr::CIDR.create('192.168.1.1/24')
|
836
1004
|
# cidr4.is_contained?('192.168.0.0/23')
|
837
1005
|
#
|
@@ -858,9 +1026,9 @@ end
|
|
858
1026
|
"with a version #{@version} CIDR."
|
859
1027
|
end
|
860
1028
|
|
861
|
-
network = cidr.
|
862
|
-
netmask = cidr.
|
863
|
-
hostmask = cidr.
|
1029
|
+
network = cidr.to_i(:network)
|
1030
|
+
netmask = cidr.to_i(:netmask)
|
1031
|
+
hostmask = cidr.to_i(:hostmask)
|
864
1032
|
|
865
1033
|
is_contained = true if ( NetAddr.cidr_compare(self,cidr) == -1 )
|
866
1034
|
|
@@ -874,6 +1042,10 @@ end
|
|
874
1042
|
#===Synopsis
|
875
1043
|
#Provide last IP address in this CIDR object.
|
876
1044
|
#
|
1045
|
+
# Example:
|
1046
|
+
# cidr = NetAddr::CIDR.create('192.168.1.0/24')
|
1047
|
+
# cidr.last => "192.168.1.255"
|
1048
|
+
#
|
877
1049
|
#===Arguments:
|
878
1050
|
#* options = Hash with the following keys:
|
879
1051
|
# :Objectify -- if true, return NetAddr::CIDR object
|
@@ -904,16 +1076,16 @@ end
|
|
904
1076
|
|
905
1077
|
end
|
906
1078
|
|
907
|
-
|
1079
|
+
ip_int = @network | @hostmask
|
908
1080
|
if (!objectify)
|
909
|
-
ip = NetAddr.ip_int_to_str(
|
1081
|
+
ip = NetAddr.ip_int_to_str(ip_int, @version)
|
910
1082
|
ip = NetAddr.shorten(ip) if (short && !objectify && @version == 6)
|
911
1083
|
else
|
912
|
-
ip = NetAddr.cidr_build(@version,
|
1084
|
+
ip = NetAddr.cidr_build(@version,ip_int)
|
913
1085
|
end
|
914
1086
|
|
915
1087
|
return(ip)
|
916
|
-
end
|
1088
|
+
end
|
917
1089
|
|
918
1090
|
#==============================================================================#
|
919
1091
|
# matches?()
|
@@ -924,6 +1096,7 @@ end
|
|
924
1096
|
#if it falls within the range of addresses resulting from the combination of the
|
925
1097
|
#IP and Wildcard Mask of this CIDR.
|
926
1098
|
#
|
1099
|
+
# Example:
|
927
1100
|
# cidr4 = NetAddr.CIDRv4.create('10.0.0.0', :WildcardMask => ['0.7.0.255', true])
|
928
1101
|
# cidr4.matches?('10.0.0.22') -> true
|
929
1102
|
# cidr4.matches?('10.8.0.1') -> false
|
@@ -937,19 +1110,19 @@ end
|
|
937
1110
|
#* True or False
|
938
1111
|
#
|
939
1112
|
def matches?(ip)
|
940
|
-
|
1113
|
+
ip_int = nil
|
941
1114
|
if (!ip.kind_of?(NetAddr::CIDR))
|
942
1115
|
begin
|
943
|
-
|
1116
|
+
ip_int = NetAddr.ip_to_i(ip, :Version => @version)
|
944
1117
|
rescue NetAddr::ValidationError
|
945
1118
|
raise NetAddr::ValidationError, "Provided IP must be a valid IPv#{@version} address."
|
946
1119
|
end
|
947
1120
|
else
|
948
1121
|
raise NetAddr::ValidationError, "Provided CIDR must be of type #{self.class}" if (ip.class != self.class)
|
949
|
-
|
1122
|
+
ip_int = ip.to_i(:ip)
|
950
1123
|
end
|
951
1124
|
|
952
|
-
return(true) if (@ip & @wildcard_mask ==
|
1125
|
+
return(true) if (@ip & @wildcard_mask == ip_int & @wildcard_mask)
|
953
1126
|
return(false)
|
954
1127
|
end
|
955
1128
|
|
@@ -962,6 +1135,7 @@ end
|
|
962
1135
|
#and ff00::/8 for IPv6), return its ethernet MAC address (EUI-48) mapping.
|
963
1136
|
#MAC address is based on original IP address passed during initialization.
|
964
1137
|
#
|
1138
|
+
# Example:
|
965
1139
|
# mcast = NetAddr::CIDR.create('224.0.0.6')
|
966
1140
|
# mcast.multicast_mac.address
|
967
1141
|
#
|
@@ -1018,6 +1192,10 @@ end
|
|
1018
1192
|
#===Synopsis
|
1019
1193
|
#Provide netmask in CIDR format (/yy).
|
1020
1194
|
#
|
1195
|
+
# Example:
|
1196
|
+
# cidr = NetAddr::CIDR.create('192.168.1.0/24')
|
1197
|
+
# cidr.netmask => "/24"
|
1198
|
+
#
|
1021
1199
|
#===Arguments:
|
1022
1200
|
#* none
|
1023
1201
|
#
|
@@ -1036,6 +1214,10 @@ end
|
|
1036
1214
|
#===Synopsis
|
1037
1215
|
#Provide base network address.
|
1038
1216
|
#
|
1217
|
+
# Example:
|
1218
|
+
# cidr = NetAddr::CIDR.create('192.168.1.0/24')
|
1219
|
+
# cidr.network => "192.168.1.0"
|
1220
|
+
#
|
1039
1221
|
#===Arguments:
|
1040
1222
|
#* options = Hash with the following fields:
|
1041
1223
|
# :Objectify -- if true, return NetAddr::CIDR object
|
@@ -1086,6 +1268,7 @@ end
|
|
1086
1268
|
#===Synopsis
|
1087
1269
|
#Provide the next IP following the last available IP within this CIDR object.
|
1088
1270
|
#
|
1271
|
+
# Example:
|
1089
1272
|
# cidr4 = NetAddr::CIDR.create('192.168.1.1/24')
|
1090
1273
|
# cidr6 = NetAddr::CIDR.create('fec0::/64')
|
1091
1274
|
# cidr4.next_subnet()
|
@@ -1151,10 +1334,11 @@ end
|
|
1151
1334
|
#Provide the next subnet following this CIDR object. The next subnet will
|
1152
1335
|
#be of the same size as the current CIDR object.
|
1153
1336
|
#
|
1154
|
-
#
|
1155
|
-
#
|
1156
|
-
#
|
1157
|
-
#
|
1337
|
+
# Example:
|
1338
|
+
# cidr4 = NetAddr::CIDR.create('192.168.1.1/24')
|
1339
|
+
# cidr6 = NetAddr::CIDR.create('fec0::/64')
|
1340
|
+
# cidr4.next_subnet()
|
1341
|
+
# cidr6.next_subnet(:Short => true)
|
1158
1342
|
#
|
1159
1343
|
#===Arguments:
|
1160
1344
|
#* options = Hash with the following keys:
|
@@ -1203,7 +1387,7 @@ end
|
|
1203
1387
|
next_sub = NetAddr.shorten(next_sub) if (short && @version == 6)
|
1204
1388
|
next_sub = next_sub << "/" << self.bits.to_s
|
1205
1389
|
else
|
1206
|
-
next_sub = NetAddr.cidr_build(@version,next_sub,self.
|
1390
|
+
next_sub = NetAddr.cidr_build(@version,next_sub,self.to_i(:netmask))
|
1207
1391
|
end
|
1208
1392
|
|
1209
1393
|
return(next_sub)
|
@@ -1216,6 +1400,7 @@ end
|
|
1216
1400
|
#===Synopsis
|
1217
1401
|
#Provide the nth IP within this object.
|
1218
1402
|
#
|
1403
|
+
# Example:
|
1219
1404
|
# cidr4 = NetAddr::CIDR.create('192.168.1.1/24')
|
1220
1405
|
# cidr4.nth(1)
|
1221
1406
|
# cidr4.nth(1, :Objectify => true)
|
@@ -1270,100 +1455,16 @@ end
|
|
1270
1455
|
return(my_ip)
|
1271
1456
|
end
|
1272
1457
|
|
1273
|
-
#==============================================================================#
|
1274
|
-
# packed_hostmask()
|
1275
|
-
#==============================================================================#
|
1276
|
-
|
1277
|
-
#===Synopsis
|
1278
|
-
#Provide an Integer representation of the Hostmask of this object.
|
1279
|
-
#
|
1280
|
-
#===Arguments:
|
1281
|
-
#* none
|
1282
|
-
#
|
1283
|
-
#===Returns:
|
1284
|
-
#* Integer
|
1285
|
-
#
|
1286
|
-
def packed_hostmask()
|
1287
|
-
return(@hostmask)
|
1288
|
-
end
|
1289
|
-
|
1290
|
-
#==============================================================================#
|
1291
|
-
# packed_ip()
|
1292
|
-
#==============================================================================#
|
1293
|
-
|
1294
|
-
#===Synopsis
|
1295
|
-
#Provide an Integer representation of the IP address of this object.
|
1296
|
-
#
|
1297
|
-
#===Arguments:
|
1298
|
-
#* none
|
1299
|
-
#
|
1300
|
-
#===Returns:
|
1301
|
-
#* Integer
|
1302
|
-
#
|
1303
|
-
def packed_ip()
|
1304
|
-
return(@ip)
|
1305
|
-
end
|
1306
|
-
|
1307
|
-
#==============================================================================#
|
1308
|
-
# packed_netmask()
|
1309
|
-
#==============================================================================#
|
1310
|
-
|
1311
|
-
#===Synopsis
|
1312
|
-
#Provide an Integer representation of the Netmask of this object.
|
1313
|
-
#
|
1314
|
-
#===Arguments:
|
1315
|
-
#* none
|
1316
|
-
#
|
1317
|
-
#===Returns:
|
1318
|
-
#* Integer
|
1319
|
-
#
|
1320
|
-
def packed_netmask()
|
1321
|
-
return(@netmask)
|
1322
|
-
end
|
1323
|
-
|
1324
|
-
#==============================================================================#
|
1325
|
-
# packed_network()
|
1326
|
-
#==============================================================================#
|
1327
|
-
|
1328
|
-
#===Synopsis
|
1329
|
-
#Provide an Integer representation of the Network address of this object.
|
1330
|
-
#
|
1331
|
-
#===Arguments:
|
1332
|
-
#* none
|
1333
|
-
#
|
1334
|
-
#===Returns:
|
1335
|
-
#* Integer
|
1336
|
-
#
|
1337
|
-
def packed_network()
|
1338
|
-
return(@network)
|
1339
|
-
end
|
1340
|
-
|
1341
|
-
#==============================================================================#
|
1342
|
-
# packed_wildcard_mask()
|
1343
|
-
#==============================================================================#
|
1344
|
-
|
1345
|
-
#===Synopsis
|
1346
|
-
#Provide an Integer representation of the IPv4 Wildcard Mask.
|
1347
|
-
#
|
1348
|
-
#===Arguments:
|
1349
|
-
#* none
|
1350
|
-
#
|
1351
|
-
#===Returns:
|
1352
|
-
#* Integer
|
1353
|
-
#
|
1354
|
-
def packed_wildcard_mask()
|
1355
|
-
return(@wildcard_mask)
|
1356
|
-
end
|
1357
|
-
|
1358
1458
|
#==============================================================================#
|
1359
1459
|
# range()
|
1360
1460
|
#==============================================================================#
|
1361
1461
|
|
1362
1462
|
#===Synopsis
|
1363
|
-
#Given a set of index numbers for this CIDR, return all IP addresses within the
|
1463
|
+
#Given a set of index numbers for this CIDR, return all IP addresses within the
|
1364
1464
|
#CIDR that are between them (inclusive). If an upper bound is not provided, then
|
1365
|
-
#all addresses from the lower bound up will be returned.
|
1465
|
+
#all addresses from the lower bound up will be returned.
|
1366
1466
|
#
|
1467
|
+
# Example:
|
1367
1468
|
# cidr4 = NetAddr::CIDR.create('192.168.1.1/24')
|
1368
1469
|
# cidr4.range(0, 1)
|
1369
1470
|
# cidr4.range(0, 1, :Objectify => true)
|
@@ -1379,6 +1480,15 @@ end
|
|
1379
1480
|
#
|
1380
1481
|
#===Returns:
|
1381
1482
|
#* Array of Strings, or Array of NetAddr::CIDR objects
|
1483
|
+
#
|
1484
|
+
#===Note:
|
1485
|
+
#If you do not need all of the fancy options in this method, then please consider
|
1486
|
+
#using the standard Ruby Range class as shown below.
|
1487
|
+
#
|
1488
|
+
# Example:
|
1489
|
+
# start = NetAddr::CIDR.create('192.168.1.0')
|
1490
|
+
# fin = NetAddr::CIDR.create('192.168.2.3')
|
1491
|
+
# (start..fin).each {|addr| puts addr.desc}
|
1382
1492
|
#
|
1383
1493
|
def range(lower, upper=nil, options=nil)
|
1384
1494
|
known_args = [:Bitstep, :Objectify, :Short]
|
@@ -1511,12 +1621,12 @@ end
|
|
1511
1621
|
# belongs in. take that half & repeat the process. every time
|
1512
1622
|
# we repeat, store the non-matching half
|
1513
1623
|
new_mask = self.bits + 1
|
1514
|
-
lower_network = self.
|
1515
|
-
upper_network = self.
|
1624
|
+
lower_network = self.to_i(:network)
|
1625
|
+
upper_network = self.to_i(:network) + 2**(@address_len - new_mask)
|
1516
1626
|
|
1517
1627
|
new_subnets = []
|
1518
1628
|
until(new_mask > addr.bits)
|
1519
|
-
if (addr.
|
1629
|
+
if (addr.to_i(:network) < upper_network)
|
1520
1630
|
match = lower_network
|
1521
1631
|
non_match = upper_network
|
1522
1632
|
else
|
@@ -1548,6 +1658,7 @@ end
|
|
1548
1658
|
#Resize the CIDR by changing the size of the Netmask.
|
1549
1659
|
#Return the resulting CIDR as a new object.
|
1550
1660
|
#
|
1661
|
+
# Example:
|
1551
1662
|
# cidr4 = NetAddr::CIDR.create('192.168.1.1/24')
|
1552
1663
|
# new_cidr = cidr4.resize(23)
|
1553
1664
|
#
|
@@ -1577,6 +1688,7 @@ end
|
|
1577
1688
|
#passed during initialization will be set to the base network address if
|
1578
1689
|
#it no longer falls within the bounds of the CIDR.
|
1579
1690
|
#
|
1691
|
+
# Example:
|
1580
1692
|
# cidr4 = NetAddr::CIDR.create('192.168.1.1/24')
|
1581
1693
|
# cidr4.resize!(23)
|
1582
1694
|
#
|
@@ -1591,7 +1703,7 @@ end
|
|
1591
1703
|
"#{bits.class} provided." if (!bits.kind_of?(Integer))
|
1592
1704
|
|
1593
1705
|
NetAddr.validate_ip_netmask(bits, :Version => @version)
|
1594
|
-
netmask = NetAddr.
|
1706
|
+
netmask = NetAddr.netmask_to_i(bits, :Version => @version)
|
1595
1707
|
|
1596
1708
|
@netmask = netmask
|
1597
1709
|
@network = @network & netmask
|
@@ -1613,6 +1725,7 @@ end
|
|
1613
1725
|
#Set the wildcard mask. Wildcard masks are typically used for matching
|
1614
1726
|
#entries in an access-list.
|
1615
1727
|
#
|
1728
|
+
# Example:
|
1616
1729
|
# cidr4 = NetAddr::CIDR.create('192.168.1.0/24')
|
1617
1730
|
# cidr4.set_wildcard_mask('0.0.0.255', true)
|
1618
1731
|
# cidr4.set_wildcard_mask('255.255.255.0')
|
@@ -1625,20 +1738,20 @@ end
|
|
1625
1738
|
#* nil
|
1626
1739
|
#
|
1627
1740
|
def set_wildcard_mask(mask, bit_flipped=false)
|
1628
|
-
|
1741
|
+
netmask_int = nil
|
1629
1742
|
if (mask.kind_of?(Integer))
|
1630
1743
|
NetAddr.validate_ip_int(mask,@version)
|
1631
|
-
|
1744
|
+
netmask_int = mask
|
1632
1745
|
else
|
1633
1746
|
begin
|
1634
1747
|
NetAddr.validate_ip_str(mask,@version)
|
1635
|
-
|
1748
|
+
netmask_int = NetAddr.ip_str_to_int(mask, @version)
|
1636
1749
|
rescue NetAddr::ValidationError
|
1637
1750
|
raise NetAddr::ValidationError, "Wildcard Mask must be a valid IPv#{@version} address."
|
1638
1751
|
end
|
1639
1752
|
end
|
1640
|
-
|
1641
|
-
@wildcard_mask =
|
1753
|
+
netmask_int = ~netmask_int if (bit_flipped)
|
1754
|
+
@wildcard_mask = netmask_int
|
1642
1755
|
|
1643
1756
|
return(nil)
|
1644
1757
|
end
|
@@ -1650,6 +1763,10 @@ end
|
|
1650
1763
|
#===Synopsis
|
1651
1764
|
#Provide number of IP addresses within this CIDR.
|
1652
1765
|
#
|
1766
|
+
# Example:
|
1767
|
+
# cidr = NetAddr::CIDR.create('192.168.1.0/24')
|
1768
|
+
# cidr.size => 256
|
1769
|
+
#
|
1653
1770
|
#===Arguments:
|
1654
1771
|
#* none
|
1655
1772
|
#
|
@@ -1683,6 +1800,7 @@ end
|
|
1683
1800
|
#If neither :Bits nor :IPCount is provided, then the current CIDR will be split in half.
|
1684
1801
|
#If both :Bits and :IPCount are provided, then :Bits takes precedence.
|
1685
1802
|
#
|
1803
|
+
# Example:
|
1686
1804
|
# cidr4 = NetAddr::CIDR.create('192.168.1.0/24')
|
1687
1805
|
# cidr6 = NetAddr::CIDR.create('fec0::/64')
|
1688
1806
|
# cidr4.subnet(:Bits => 28, :NumSubnets => 3)
|
@@ -1703,7 +1821,7 @@ end
|
|
1703
1821
|
#
|
1704
1822
|
def subnet(options=nil)
|
1705
1823
|
known_args = [:Bits, :IPCount, :NumSubnets, :Objectify, :Short]
|
1706
|
-
my_network = self.
|
1824
|
+
my_network = self.to_i(:network)
|
1707
1825
|
my_mask = self.bits
|
1708
1826
|
subnet_bits = my_mask + 1
|
1709
1827
|
min_count = nil
|
@@ -1785,7 +1903,7 @@ end
|
|
1785
1903
|
new_subnets.push("#{subnet.network}/#{subnet_bits}")
|
1786
1904
|
end
|
1787
1905
|
else
|
1788
|
-
new_subnets.push( NetAddr.cidr_build(@version, subnet.
|
1906
|
+
new_subnets.push( NetAddr.cidr_build(@version, subnet.to_i(:network), NetAddr.bits_to_mask(subnet_bits,version) ) )
|
1789
1907
|
end
|
1790
1908
|
end
|
1791
1909
|
|
@@ -1810,6 +1928,73 @@ end
|
|
1810
1928
|
return(new_subnets)
|
1811
1929
|
end
|
1812
1930
|
|
1931
|
+
#==============================================================================#
|
1932
|
+
# succ()
|
1933
|
+
#==============================================================================#
|
1934
|
+
|
1935
|
+
#===Synopsis
|
1936
|
+
#Provide the next subnet following this CIDR object. The next subnet will
|
1937
|
+
#be of the same size as the current CIDR object.
|
1938
|
+
#
|
1939
|
+
# Example:
|
1940
|
+
# cidr = NetAddr::CIDR.create('192.168.1.0/24')
|
1941
|
+
# cidr.succ => 192.168.2.0/24
|
1942
|
+
#
|
1943
|
+
#===Arguments:
|
1944
|
+
#* none
|
1945
|
+
#
|
1946
|
+
#===Returns:
|
1947
|
+
#* NetAddr::CIDR object.
|
1948
|
+
#
|
1949
|
+
def succ()
|
1950
|
+
bitstep = 2**(@address_len - self.bits)
|
1951
|
+
next_sub = @network + bitstep
|
1952
|
+
|
1953
|
+
if (next_sub > @all_f)
|
1954
|
+
raise BoundaryError, "Returned subnet is out of bounds for IPv#{@version}."
|
1955
|
+
end
|
1956
|
+
|
1957
|
+
next_sub = NetAddr.cidr_build(@version,next_sub,self.to_i(:netmask))
|
1958
|
+
|
1959
|
+
return(next_sub)
|
1960
|
+
end
|
1961
|
+
|
1962
|
+
#==============================================================================#
|
1963
|
+
# to_i()
|
1964
|
+
#==============================================================================#
|
1965
|
+
|
1966
|
+
#===Synopsis
|
1967
|
+
#Convert the requested attribute of the CIDR to an Integer.
|
1968
|
+
# Example:
|
1969
|
+
# cidr = NetAddr::CIDR.create('192.168.1.1/24')
|
1970
|
+
# cidr.to_i => 3232235776
|
1971
|
+
# cidr.to_i(:hostmask) => 255
|
1972
|
+
# cidr.to_i(:ip) => 3232235777
|
1973
|
+
# cidr.to_i(:netmask) => 4294967040
|
1974
|
+
# cidr.to_i(:wildcard_mask) => 4294967040
|
1975
|
+
#
|
1976
|
+
#===Arguments:
|
1977
|
+
#* attribute -- attribute of the CIDR to convert to an Integer (:hostmask, :ip, :netmask, :network, or :wildcard_mask).
|
1978
|
+
#
|
1979
|
+
#===Returns:
|
1980
|
+
#* Integer
|
1981
|
+
#
|
1982
|
+
def to_i(attribute=:network)
|
1983
|
+
if(attribute == :network)
|
1984
|
+
return(@network)
|
1985
|
+
elsif(attribute == :hostmask)
|
1986
|
+
return(@hostmask)
|
1987
|
+
elsif(attribute == :ip)
|
1988
|
+
return(@ip)
|
1989
|
+
elsif(attribute == :netmask)
|
1990
|
+
return(@netmask)
|
1991
|
+
elsif(attribute == :wildcard_mask)
|
1992
|
+
return(@wildcard_mask)
|
1993
|
+
else
|
1994
|
+
raise ArgumentError, "Attribute is unrecognized. Must be :hostmask, :ip, :netmask, :network, or :wildcard_mask."
|
1995
|
+
end
|
1996
|
+
end
|
1997
|
+
|
1813
1998
|
#==============================================================================#
|
1814
1999
|
# wildcard_mask()
|
1815
2000
|
#==============================================================================#
|
@@ -1817,6 +2002,11 @@ end
|
|
1817
2002
|
#===Synopsis
|
1818
2003
|
#Return the wildcard mask.
|
1819
2004
|
#
|
2005
|
+
# Example:
|
2006
|
+
# cidr = NetAddr::CIDR.create('10.1.0.0/24', :WildcardMask => ['0.7.0.255', true])
|
2007
|
+
# cidr.wildcard_mask => "255.248.255.0"
|
2008
|
+
# cidr.wildcard_mask(true) => "0.7.0.255"
|
2009
|
+
#
|
1820
2010
|
#===Arguments:
|
1821
2011
|
#* bit_flipped = if set True then returned the bit-flipped version of the wildcard mask.
|
1822
2012
|
#
|
@@ -1860,6 +2050,10 @@ class CIDRv4 < CIDR
|
|
1860
2050
|
#===Synopsis
|
1861
2051
|
#Provide IPv4 Hostmask in extended format (y.y.y.y).
|
1862
2052
|
#
|
2053
|
+
# Example:
|
2054
|
+
# cidr = NetAddr::CIDR.create('10.1.0.0/24')
|
2055
|
+
# cidr.hostmask_ext => "0.0.0.255"
|
2056
|
+
#
|
1863
2057
|
#===Arguments:
|
1864
2058
|
#* none
|
1865
2059
|
#
|
@@ -1877,6 +2071,10 @@ class CIDRv4 < CIDR
|
|
1877
2071
|
#===Synopsis
|
1878
2072
|
#Provide IPv4 netmask in extended format (y.y.y.y).
|
1879
2073
|
#
|
2074
|
+
# Example:
|
2075
|
+
# cidr = NetAddr::CIDR.create('10.1.0.0/24')
|
2076
|
+
# cidr.netmask_ext => "255.255.255.0"
|
2077
|
+
#
|
1880
2078
|
#===Arguments:
|
1881
2079
|
#* none
|
1882
2080
|
#
|
@@ -1900,6 +2098,80 @@ end # end class CIDRv4
|
|
1900
2098
|
# Addresses of this class are composed of a 128-bit address space.
|
1901
2099
|
class CIDRv6 < CIDR
|
1902
2100
|
public_class_method :new
|
2101
|
+
|
2102
|
+
#==============================================================================#
|
2103
|
+
# unique_local()
|
2104
|
+
#==============================================================================#
|
2105
|
+
|
2106
|
+
#===Synopsis
|
2107
|
+
#Generate an IPv6 Unique Local CIDR address based on the algorithm described
|
2108
|
+
#in RFC 4193.
|
2109
|
+
#
|
2110
|
+
#From the RFC:
|
2111
|
+
#
|
2112
|
+
# 1) Obtain the current time of day in 64-bit NTP format [NTP].
|
2113
|
+
#
|
2114
|
+
# 2) Obtain an EUI-64 identifier from the system running this
|
2115
|
+
# algorithm. If an EUI-64 does not exist, one can be created from
|
2116
|
+
# a 48-bit MAC address as specified in [ADDARCH]. If an EUI-64
|
2117
|
+
# cannot be obtained or created, a suitably unique identifier,
|
2118
|
+
# local to the node, should be used (e.g., system serial number).
|
2119
|
+
#
|
2120
|
+
# 3) Concatenate the time of day with the system-specific identifier
|
2121
|
+
# in order to create a key.
|
2122
|
+
#
|
2123
|
+
# 4) Compute an SHA-1 digest on the key as specified in [FIPS, SHA1];
|
2124
|
+
# the resulting value is 160 bits.
|
2125
|
+
#
|
2126
|
+
# 5) Use the least significant 40 bits as the Global ID.
|
2127
|
+
#
|
2128
|
+
# 6) Concatenate FC00::/7, the L bit set to 1, and the 40-bit Global
|
2129
|
+
# ID to create a Local IPv6 address prefix.
|
2130
|
+
#
|
2131
|
+
# Example:
|
2132
|
+
# eui = NetAddr::EUI.create('aabb.ccdd.eeff')
|
2133
|
+
# NetAddr::CIDRv6.unique_local(eui) => fdb4:3014:e277:0000:0000:0000:0000:0000/48
|
2134
|
+
#
|
2135
|
+
#===Arguments:
|
2136
|
+
#* NetAddr::EUI object
|
2137
|
+
#
|
2138
|
+
#===Returns:
|
2139
|
+
#* CIDRv6 object
|
2140
|
+
#
|
2141
|
+
def CIDRv6.unique_local(eui)
|
2142
|
+
|
2143
|
+
if (eui.kind_of?(NetAddr::EUI48) )
|
2144
|
+
eui = eui.to_eui64.to_s
|
2145
|
+
elsif (eui.kind_of?(NetAddr::EUI64) )
|
2146
|
+
eui = eui.to_s
|
2147
|
+
else
|
2148
|
+
raise ArgumentError, "Expected NetAddr::EUI object but #{eui.class} received."
|
2149
|
+
end
|
2150
|
+
|
2151
|
+
ntp_time = ''
|
2152
|
+
|
2153
|
+
# get current time (32-bits), convert to 4-byte string, and append to ntp_time
|
2154
|
+
time = Time.now.to_i
|
2155
|
+
4.times do
|
2156
|
+
ntp_time.insert(0, (time & 0xff).chr )
|
2157
|
+
time = time >> 8
|
2158
|
+
end
|
2159
|
+
|
2160
|
+
# create 32-bit fractional, convert to 4-byte string, and append to ntp_time
|
2161
|
+
fract = rand(2**32-1)
|
2162
|
+
4.times do
|
2163
|
+
ntp_time.insert(0, (fract & 0xff).chr )
|
2164
|
+
fract = fract >> 8
|
2165
|
+
end
|
2166
|
+
|
2167
|
+
# create sha1 hash
|
2168
|
+
pre_hash = ntp_time << eui
|
2169
|
+
gid = Digest::SHA1.hexdigest(pre_hash).slice!(30..39)
|
2170
|
+
addr = 'fd' << gid << '00000000000000000000'
|
2171
|
+
|
2172
|
+
return( NetAddr::CIDRv6.new(addr.to_i(16), 0xffffffffffff00000000000000000000 ) )
|
2173
|
+
end
|
2174
|
+
|
1903
2175
|
end # end class CIDRv6
|
1904
2176
|
|
1905
2177
|
end # module NetAddr
|