netaddr 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of netaddr might be problematic. Click here for more details.

data/lib/methods.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  =begin rdoc
2
2
  Copyleft (c) 2006 Dustin Spinhirne (www.spinhirne.com)
3
-
3
+
4
4
  Licensed under the same terms as Ruby, No Warranty is provided.
5
5
  =end
6
6
 
@@ -11,7 +11,7 @@ module NetAddr
11
11
  #==============================================================================#
12
12
 
13
13
  #===Synopsis
14
- #Given a list of CIDR addresses or NetAddr::CIDR objects of the same version,
14
+ #Given a list of CIDR addresses or NetAddr::CIDR objects,
15
15
  #merge (summarize) them in the most efficient way possible. Summarization
16
16
  #will only occur when the newly created supernets will not result in the
17
17
  #'creation' of new IP space. For example the following blocks
@@ -23,155 +23,98 @@ module NetAddr
23
23
  #10.1.0.0/26, 10.1.0.64/26) and they will be merged properly (ie 192.168.1.0/25,
24
24
  #and 10.1.0.0/25 would be returned).
25
25
  #
26
+ #If the :Objectify option is enabled, then any summary addresses returned will
27
+ #contain the original CIDRs used to create them within the tag value :Subnets
28
+ #(ie. cidr_x.tag[:Subnets] would be an Array of the CIDRs used to create cidr_x)
29
+ #
26
30
  # Example:
27
- # supernets = NetAddr.merge(['192.168.1.0/27','192.168.1.32/27'])
28
- # supernets = NetAddr.merge([cidr1,cidr2])
29
- # supernets = NetAddr.merge(['192.168.1.0/27','192.168.1.32/27'], :Short => true)
31
+ # cidr1 = NetAddr::CIDR.create('192.168.1.0/27')
32
+ # cidr2 = NetAddr::CIDR.create('192.168.1.32/27')
33
+ # NetAddr.merge([cidr1,cidr2])
34
+ # ip_net_range = NetAddr.range('192.168.35.0','192.168.39.255',:Inclusive => true, :Objectify => true)
35
+ # NetAddr.merge(ip_net_range, :Objectify => true)
30
36
  #
31
37
  #===Arguments:
32
- #* Array of CIDR addresses as Strings, or an Array of NetAddr::CIDR objects
33
- #* Optional Hash with the following keys:
34
- # :Objectify -- if true, return NetAddr::CIDR objects (optional)
35
- # :Short -- if true, return IPv6 addresses in short-hand notation (optional)
38
+ #* list = Array of CIDR addresses as Strings, or an Array of NetAddr::CIDR objects
39
+ #* options = Hash with the following keys:
40
+ # :Objectify -- if true, return NetAddr::CIDR objects
41
+ # :Short -- if true, return IPv6 addresses in short-hand notation
36
42
  #
37
43
  #===Returns:
38
- #* Array of CIDR addresses as Strings, or an Array of NetAddr::CIDR objects
44
+ #* Array of CIDR addresses or NetAddr::CIDR objects
39
45
  #
40
46
  def merge(list,options=nil)
41
47
  known_args = [:Objectify, :Short]
42
- version = nil
43
- all_f = nil
44
48
  short = false
45
49
  objectify = false
50
+ verbose = false
46
51
 
47
52
  # validate list
48
53
  raise ArgumentError, "Array expected for argument 'list' but #{list.class} provided." if (!list.kind_of?(Array) )
49
-
54
+
50
55
  # validate options
51
- if (options)
56
+ if (options)
52
57
  raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash) )
53
58
  NetAddr.validate_args(options.keys,known_args)
54
-
59
+
55
60
  if (options.has_key?(:Objectify) && options[:Objectify] == true)
56
61
  objectify = true
57
62
  end
58
-
63
+
59
64
  if (options.has_key?(:Short) && options[:Short] == true)
60
65
  short = true
61
66
  end
62
67
  end
63
-
68
+
64
69
  # make sure all are valid types of the same IP version
65
- supernet_list = []
70
+ v4_list = []
71
+ v6_list = []
66
72
  list.each do |obj|
67
73
  if (!obj.kind_of?(NetAddr::CIDR))
68
74
  begin
69
75
  obj = NetAddr::CIDR.create(obj)
70
76
  rescue Exception => error
71
- raise ArgumentError, "An array element of :List raised the following " +
77
+ raise ArgumentError, "One of the provided CIDR addresses raised the following " +
72
78
  "errors: #{error}"
73
79
  end
74
80
  end
75
81
 
76
- version = obj.version if (!version)
77
- all_f = obj.all_f if (!all_f)
78
- if (!obj.version == version)
79
- raise VersionError, "Provided objects must be of the same IP version."
80
- end
81
- supernet_list.push(obj)
82
+ if (obj.version == 4)
83
+ v4_list.push(obj)
84
+ else
85
+ v6_list.push(obj)
86
+ end
82
87
  end
83
88
 
84
- # merge subnets by removing them from 'supernet_list',
85
- # and categorizing them into hash of arrays ({packed_netmask => [packed_network,packed_network,etc...] )
86
- # within each categorization we merge contiguous subnets
87
- # and then remove them from that category & put them back into
88
- # 'supernet_list'. we do this until supernet_list stops getting any shorter
89
- categories = {}
90
- supernet_list_length = 0
91
- until (supernet_list_length == supernet_list.length)
92
- supernet_list_length = supernet_list.length
93
-
94
- # categorize
95
- supernet_list.each do |cidr|
96
- netmask = cidr.packed_netmask
97
- network = cidr.packed_network
98
- if (categories.has_key?(netmask) )
99
- categories[netmask].push(network)
100
- else
101
- categories[netmask] = [network]
102
- end
103
- end
104
- supernet_list.clear
105
-
106
- ordered_cats = categories.keys.sort
107
- ordered_cats.each do |netmask|
108
- nets = categories[netmask].sort
109
- bitstep = (all_f + 1) - netmask
110
-
111
- until (nets.length == 0)
112
- # take the first network & create its supernet. this
113
- # supernet will have x number of subnets, so we'll look
114
- # & see if we have those subnets. if so, keep supernet & delete subnets.
115
- to_merge = []
116
- multiplier = 1
117
- network1 = nets[0]
118
- num_required = 2**multiplier
119
- supermask = (netmask << multiplier) & all_f
120
- supernet = supermask & network1
121
- if (network1 == supernet)
122
- # we have the first half of the new supernet
123
- expected = network1
124
- nets.each do |network|
125
- if (network == expected)
126
- to_merge.push(network)
127
- expected = expected + bitstep
128
- if ( (to_merge.length == num_required) && (nets.length > num_required) )
129
- # we have all of our subnets for this round, but still have
130
- # more to look at
131
- multiplier += 1
132
- num_required = 2**multiplier
133
- supermask = (netmask << multiplier) & all_f
134
- supernet = supermask & network1
135
- end
136
- else
137
- break
138
- end
139
- end
140
- else
141
- # we have the second half of the new supernet only
142
- to_merge.push(network1)
143
- end
89
+ # summarize
90
+ v4_summary = []
91
+ v6_summary = []
92
+ if (v4_list.length != 0)
93
+ v4_summary = NetAddr.cidr_summarize(v4_list)
94
+ end
144
95
 
145
-
146
- if (to_merge.length != num_required)
147
- # we dont have all of our subnets, so backstep 1 bit
148
- multiplier -= 1
149
- supermask = (netmask << multiplier) & all_f
150
- supernet = supermask & network1
151
- end
152
-
153
- # save new supernet
154
- supernet_list.push(NetAddr::CIDR.create(supernet,
155
- :PackedNetmask => supermask,
156
- :Version => version))
157
-
158
- # delete the subnets of the new supernet
159
- (2**multiplier).times {nets.delete(to_merge.shift)}
160
- end
161
- end
162
- categories.clear
163
- supernet_list = NetAddr.sort(supernet_list)
96
+ if (v6_list.length != 0)
97
+ v6_summary = NetAddr.cidr_summarize(v6_list)
164
98
  end
165
99
 
166
100
  # decide what to return
101
+ summarized_list = []
167
102
  if (!objectify)
168
- supernets = []
169
- supernet_list.each {|entry| supernets.push(entry.desc(:Short => short))}
170
- return(supernets)
103
+ summarized_list = []
104
+ if (v4_summary.length != 0)
105
+ v4_summary.each {|x| summarized_list.push(x.desc())}
106
+ end
107
+
108
+ if (v6_summary.length != 0)
109
+ v6_summary.each {|x| summarized_list.push(x.desc(:Short => short))}
110
+ end
111
+
171
112
  else
172
- return(supernet_list)
113
+ summarized_list.concat(v4_summary) if (v4_summary.length != 0)
114
+ summarized_list.concat(v6_summary) if (v6_summary.length != 0)
173
115
  end
174
116
 
117
+ return(summarized_list)
175
118
  end
176
119
  module_function :merge
177
120
 
@@ -184,14 +127,14 @@ module_function :merge
184
127
  #netmask (bits by default) required for that subnet. IP version is assumed to be 4 unless specified otherwise.
185
128
  #
186
129
  # Example:
187
- # netmask = NetAddr.minumum_size(14)
188
- # netmask = NetAddr.minumum_size(65536, :Version => 6)
130
+ # NetAddr.minumum_size(14)
131
+ # NetAddr.minumum_size(65536, :Version => 6)
189
132
  #
190
133
  #===Arguments:
191
- #* IP count as an Integer
192
- #* Optional Hash with the following keys:
193
- # :Extended -- If true, then return the netmask in extended format (y.y.y.y) for IPv4
194
- # :Version -- IP version - Integer(optional)
134
+ #* ipcount = IP count as an Integer
135
+ #* options = Hash with the following keys:
136
+ # :Extended -- If true, then return the netmask, as a String, in extended format (IPv4 only y.y.y.y)
137
+ # :Version -- IP version - Integer
195
138
  #
196
139
  #===Returns:
197
140
  #* Integer or String
@@ -203,43 +146,23 @@ def minimum_size(ipcount, options=nil)
203
146
 
204
147
  # validate ipcount
205
148
  raise ArgumentError, "Integer expected for argument 'ipcount' but #{ipcount.class} provided." if (!ipcount.kind_of?(Integer))
206
-
149
+
207
150
  # validate options
208
151
  if (options)
209
152
  raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
210
-
153
+
211
154
  NetAddr.validate_args(options.keys,known_args)
212
-
155
+
213
156
  if (options.has_key?(:Version))
214
157
  version = options[:Version]
215
158
  end
216
-
159
+
217
160
  if (options.has_key?(:Extended) && options[:Extended] == true)
218
161
  extended = true
219
162
  end
220
163
  end
221
-
222
- if (version == 4)
223
- max_bits = 32
224
- else
225
- max_bits = 128
226
- end
227
-
228
-
229
- if (ipcount > 2**max_bits)
230
- raise BoundaryError, "Required IP count exceeds number of IP addresses available " +
231
- "for IPv#{version}."
232
- end
233
164
 
234
-
235
- bits_needed = 0
236
- until (2**bits_needed >= ipcount)
237
- bits_needed += 1
238
- end
239
- subnet_bits = max_bits - bits_needed
240
-
241
- return(NetAddr.unpack_ip_addr(NetAddr.pack_ip_netmask(subnet_bits))) if (extended && version == 4)
242
- return(subnet_bits)
165
+ return( ip_count_to_size(ipcount,version,extended) )
243
166
  end
244
167
  module_function :minimum_size
245
168
 
@@ -248,7 +171,8 @@ module_function :minimum_size
248
171
  #==============================================================================#
249
172
 
250
173
  #===Synopsis
251
- #Convert IP addresses into an Integer. Will attempt to auto-detect IP version if not provided.
174
+ #Convert IP addresses into an Integer. This method will attempt to auto-detect the IP version
175
+ #if not provided, however a slight speed increase is realized if version is provided.
252
176
  #
253
177
  # Example:
254
178
  # pack_ip_addr('192.168.1.1')
@@ -256,8 +180,8 @@ module_function :minimum_size
256
180
  # pack_ip_addr(::192.168.1.1')
257
181
  #
258
182
  #===Arguments:
259
- #* IP address as a String
260
- #* Optional Hash with the following keys:
183
+ #* ip = IP address as a String
184
+ #* options = Hash with the following keys:
261
185
  # :Version -- IP version - Integer
262
186
  #
263
187
  #===Returns:
@@ -266,11 +190,12 @@ module_function :minimum_size
266
190
  def pack_ip_addr(ip, options=nil)
267
191
  known_args = [:Version]
268
192
  to_validate = {}
269
-
193
+ version = nil
194
+
270
195
  # validate options
271
196
  if (options)
272
197
  raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
273
- NetAddr.validate_args(options.keys,known_args)
198
+ validate_args(options.keys,known_args)
274
199
 
275
200
  if (options.has_key?(:Version))
276
201
  version = options[:Version]
@@ -279,82 +204,15 @@ def pack_ip_addr(ip, options=nil)
279
204
  raise VersionError, ":Version should be 4 or 6, but was '#{version}'."
280
205
  end
281
206
  end
282
- end
283
-
284
- if ( ip.kind_of?(String) )
285
-
286
- # validate
287
- NetAddr.validate_ip_addr(ip, to_validate)
288
-
289
- # determine version if not provided
290
- if (!version)
291
- if ( ip =~ /\./ && ip !~ /:/ )
292
- version = 4
293
- else
294
- version = 6
295
- end
296
- end
297
-
298
- packed_ip = 0
299
- if ( version == 4)
300
- octets = ip.split('.')
301
- (0..3).each do |x|
302
- octet = octets.pop.to_i
303
- octet = octet << 8*x
304
- packed_ip = packed_ip | octet
305
- end
306
-
307
- else
308
- # if ipv4-mapped ipv6 addr
309
- if (ip =~ /\./)
310
- dotted_dec = true
311
- end
312
-
313
- # split up by ':'
314
- fields = []
315
- if (ip =~ /::/)
316
- shrthnd = ip.split( /::/ )
317
- if (shrthnd.length == 0)
318
- return(0)
319
- else
320
- first_half = shrthnd[0].split( /:/ ) if (shrthnd[0])
321
- sec_half = shrthnd[1].split( /:/ ) if (shrthnd[1])
322
- first_half = [] if (!first_half)
323
- sec_half = [] if (!sec_half)
324
- end
325
- missing_fields = 8 - first_half.length - sec_half.length
326
- missing_fields -= 1 if dotted_dec
327
- fields = fields.concat(first_half)
328
- missing_fields.times {fields.push('0')}
329
- fields = fields.concat(sec_half)
330
-
331
- else
332
- fields = ip.split(':')
333
- end
334
-
335
- if (dotted_dec)
336
- ipv4_addr = fields.pop
337
- packed_v4 = NetAddr.pack_ip_addr(ipv4_addr, :Version => 4)
338
- octets = []
339
- 2.times do
340
- octet = packed_v4 & 0xFFFF
341
- octets.unshift(octet.to_s(16))
342
- packed_v4 = packed_v4 >> 16
343
- end
344
- fields.concat(octets)
345
- end
207
+ end
346
208
 
347
- # pack
348
- (0..7).each do |x|
349
- field = fields.pop.to_i(16)
350
- field = field << 16*x
351
- packed_ip = packed_ip | field
352
- end
353
-
354
- end
209
+ if ( ip.kind_of?(String) )
210
+ version = detect_ip_version(ip) if (!version)
211
+ validate_ip_str(ip,version)
212
+ packed_ip = ip_str_to_int(ip,version)
355
213
 
356
214
  else
357
- raise ArgumentError, "String expected for argument 'ip' but #{ip.class} provided."
215
+ raise ArgumentError, "String expected for argument 'ip' but #{ip.class} provided."
358
216
  end
359
217
 
360
218
  return(packed_ip)
@@ -372,69 +230,51 @@ module_function :pack_ip_addr
372
230
  #to specify the version if an IPv6 netmask of /32 or smaller is provided.
373
231
  #
374
232
  # Example:
375
- # packed = NetAddr.pack_ip_netmask('255.255.255.0')
376
- # packed = NetAddr.pack_ip_netmask('24')
377
- # packed = NetAddr.pack_ip_netmask(24)
378
- # packed = NetAddr.pack_ip_netmask('/24')
379
- # packed = NetAddr.pack_ip_netmask('32', :Version => 6)
233
+ # NetAddr.pack_ip_netmask('255.255.255.0')
234
+ # NetAddr.pack_ip_netmask('24')
235
+ # NetAddr.pack_ip_netmask(24)
236
+ # NetAddr.pack_ip_netmask('/24')
237
+ # NetAddr.pack_ip_netmask('32', :Version => 6)
380
238
  #
381
239
  #===Arguments
382
- #* Netmask as a String or Integer
383
- #* Optional Hash with the following keys:
384
- # :Version -- IP version - Integer (optional)
240
+ #* netmask = Netmask as a String or Integer
241
+ #* options = Hash with the following keys:
242
+ # :Version -- IP version - Integer
385
243
  #
386
244
  #===Returns:
387
245
  #* Integer
388
246
  #
389
247
  def pack_ip_netmask(netmask, options=nil)
390
248
  known_args = [:Version]
391
- all_f = 2**32-1
392
- to_validate = {}
393
-
249
+ version = 4
250
+ packed_netmask = nil
251
+
394
252
  # validate options
395
253
  if (options)
396
254
  raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
397
255
  NetAddr.validate_args(options.keys,known_args)
398
-
256
+
399
257
  if (options.has_key?(:Version))
400
258
  version = options[:Version]
401
259
  if (version != 4 && version != 6)
402
260
  raise VersionError, ":Version should be 4 or 6, but was '#{version}'."
403
- elsif (version == 6)
404
- all_f = 2**128-1
405
- else
406
- all_f = 2**32-1
407
261
  end
408
- to_validate[:Version] = version
409
262
  end
410
263
  end
411
-
264
+
412
265
  if (netmask.kind_of?(String))
413
- NetAddr.validate_ip_netmask(netmask, to_validate)
414
-
415
- if(netmask =~ /\./)
416
- packed_netmask = NetAddr.pack_ip_addr(netmask)
266
+ validate_netmask_str(netmask, version)
267
+ packed_netmask = netmask_str_to_int(netmask,version)
417
268
 
418
- else
419
- # remove '/' if present
420
- if (netmask =~ /^\// )
421
- netmask[0] = " "
422
- netmask.lstrip!
423
- end
424
- netmask = netmask.to_i
425
- packed_netmask = all_f ^ (all_f >> netmask)
426
- end
427
-
428
269
  elsif (netmask.kind_of?(Integer))
429
- to_validate[:Packed] = true
430
- NetAddr.validate_ip_netmask(netmask, to_validate)
431
- packed_netmask = all_f ^ (all_f >> netmask)
432
-
270
+ validate_netmask_int(netmask, version, true)
271
+ packed_netmask = bits_to_mask(netmask,version)
272
+
433
273
  else
434
274
  raise ArgumentError, "String or Integer expected for argument 'netmask', " +
435
275
  "but #{netmask.class} provided." if (!netmask.kind_of?(Integer) && !netmask.kind_of?(String))
436
276
  end
437
-
277
+
438
278
  return(packed_netmask)
439
279
  end
440
280
  module_function :pack_ip_netmask
@@ -447,55 +287,60 @@ module_function :pack_ip_netmask
447
287
  #Given two CIDR addresses or NetAddr::CIDR objects of the same version,
448
288
  #return all IP addresses between them. NetAddr.range will use the original IP
449
289
  #address passed during the initialization of the NetAddr::CIDR objects, or the
450
- #ip address of any CIDR addresses passed. The default behavior is to be
451
- #non-inclusive (don't include boundaries as part of returned data)
290
+ #IP address portion of any CIDR addresses passed. The default behavior is to be
291
+ #non-inclusive (don't include boundaries as part of returned data).
452
292
  #
453
293
  # Example:
454
- # list = NetAddr.range(cidr1,cidr2, :Limit => 10)
455
- # list = NetAddr.range('192.168.1.0','192.168.1.10', :Inclusive => true)
294
+ # lower = NetAddr::CIDR.create('192.168.35.0')
295
+ # upper = NetAddr::CIDR.create('192.168.39.255')
296
+ # NetAddr.range(lower,upper, :Limit => 10, :Bitstep => 32)
297
+ # NetAddr.range('192.168.35.0','192.168.39.255', :Inclusive => true)
298
+ # NetAddr.range('192.168.35.0','192.168.39.255', :Inclusive => true, :Size => true)
456
299
  #
457
300
  #===Arguments:
458
- #* Lower boundary CIDR as a String or NetAddr::CIDR object
459
- #* Upper boundary CIDR as a String or NetAddr::CIDR object
460
- #* Optional Hash with the following keys:
461
- # :Bitstep -- enumerate in X sized steps - Integer (optional)
301
+ #* lower = Lower boundary CIDR as a String or NetAddr::CIDR object
302
+ #* upper = Upper boundary CIDR as a String or NetAddr::CIDR object
303
+ #* options = Hash with the following keys:
304
+ # :Bitstep -- enumerate in X sized steps - Integer
462
305
  # :Inclusive -- if true, include boundaries in returned data
463
- # :Limit -- limit returned list to X number of items - Integer (optional)
464
- # :Objectify -- if true, return CIDR objects (optional)
465
- # :Short -- if true, return IPv6 addresses in short-hand notation (optional)
306
+ # :Limit -- limit returned list to X number of items - Integer
307
+ # :Objectify -- if true, return CIDR objects
308
+ # :Short -- if true, return IPv6 addresses in short-hand notation
309
+ # :Size -- if true, return the number of addresses in this range, but not the addresses themselves
466
310
  #
467
311
  #===Returns:
468
- #* Array of Strings, or Array of NetAddr::CIDR objects
312
+ #* Array of Strings or NetAddr::CIDR objects, or an Integer
469
313
  #
470
- def range(cidr1, cidr2, options=nil)
471
- known_args = [:Bitstep, :Inclusive, :Limit, :Objectify, :Short]
314
+ def range(lower, upper, options=nil)
315
+ known_args = [:Bitstep, :Inclusive, :Limit, :Objectify, :Short, :Size]
472
316
  list = []
473
317
  bitstep = 1
474
318
  objectify = false
475
319
  short = false
320
+ size_only = false
476
321
  inclusive = false
477
322
  limit = nil
478
323
 
479
- # if cidr1/cidr2 are not CIDR objects, then attempt to create
324
+ # if lower/upper are not CIDR objects, then attempt to create
480
325
  # cidr objects from them
481
- if ( !cidr1.kind_of?(NetAddr::CIDR) )
326
+ if ( !lower.kind_of?(NetAddr::CIDR) )
482
327
  begin
483
- cidr1 = NetAddr::CIDR.create(cidr1)
328
+ lower = NetAddr::CIDR.create(lower)
484
329
  rescue Exception => error
485
- raise ArgumentError, "Argument 'cidr1' raised the following " +
330
+ raise ArgumentError, "Argument 'lower' raised the following " +
486
331
  "errors: #{error}"
487
332
  end
488
333
  end
489
-
490
- if ( !cidr2.kind_of?(NetAddr::CIDR))
334
+
335
+ if ( !upper.kind_of?(NetAddr::CIDR))
491
336
  begin
492
- cidr2 = NetAddr::CIDR.create(cidr2)
337
+ upper = NetAddr::CIDR.create(upper)
493
338
  rescue Exception => error
494
- raise ArgumentError, "Argument 'cidr2' raised the following " +
339
+ raise ArgumentError, "Argument 'upper' raised the following " +
495
340
  "errors: #{error}"
496
341
  end
497
342
  end
498
-
343
+
499
344
  # validate options
500
345
  if (options)
501
346
  raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
@@ -508,11 +353,15 @@ def range(cidr1, cidr2, options=nil)
508
353
  if( options.has_key?(:Objectify) && options[:Objectify] == true )
509
354
  objectify = true
510
355
  end
511
-
356
+
512
357
  if( options.has_key?(:Short) && options[:Short] == true )
513
358
  short = true
514
359
  end
515
-
360
+
361
+ if( options.has_key?(:Size) && options[:Size] == true )
362
+ size_only = true
363
+ end
364
+
516
365
  if( options.has_key?(:Inclusive) && options[:Inclusive] == true )
517
366
  inclusive = true
518
367
  end
@@ -523,9 +372,9 @@ def range(cidr1, cidr2, options=nil)
523
372
  end
524
373
 
525
374
  # check version, store & sort
526
- if (cidr1.version == cidr2.version)
527
- version = cidr1.version
528
- boundaries = [cidr1.packed_ip, cidr2.packed_ip]
375
+ if (lower.version == upper.version)
376
+ version = lower.version
377
+ boundaries = [lower.packed_ip, upper.packed_ip]
529
378
  boundaries.sort
530
379
  else
531
380
  raise VersionError, "Provided NetAddr::CIDR objects are of different IP versions."
@@ -539,21 +388,25 @@ def range(cidr1, cidr2, options=nil)
539
388
  my_ip = boundaries[0]
540
389
  end_ip = boundaries[1] + 1
541
390
  end
542
-
543
- until (my_ip >= end_ip)
544
- if (!objectify)
545
- my_ip_s = NetAddr.unpack_ip_addr(my_ip, :Version => version)
546
- my_ips = NetAddr.shorten(my_ips) if (short && version == 6)
547
- list.push(my_ip_s)
548
- else
549
- list.push( NetAddr::CIDR.create(my_ip, :Version => version) )
550
- end
551
391
 
552
- my_ip = my_ip + bitstep
553
- if (limit)
554
- limit = limit -1
555
- break if (limit == 0)
392
+ if (!size_only)
393
+ until (my_ip >= end_ip)
394
+ if (!objectify)
395
+ my_ip_s = ip_int_to_str(my_ip, version)
396
+ my_ips = shorten(my_ips) if (short && version == 6)
397
+ list.push(my_ip_s)
398
+ else
399
+ list.push( cidr_build(version,my_ip) )
400
+ end
401
+
402
+ my_ip = my_ip + bitstep
403
+ if (limit)
404
+ limit = limit -1
405
+ break if (limit == 0)
406
+ end
556
407
  end
408
+ else
409
+ list = end_ip - my_ip
557
410
  end
558
411
 
559
412
  return(list)
@@ -565,14 +418,14 @@ module_function :range
565
418
  #==============================================================================#
566
419
 
567
420
  #===Synopsis
568
- #Take a standard IPv6 address, and format it in short-hand notation.
421
+ #Take a standard IPv6 address and format it in short-hand notation.
569
422
  #The address should not contain a netmask.
570
423
  #
571
424
  # Example:
572
- # short = NetAddr.shorten('fec0:0000:0000:0000:0000:0000:0000:0001')
425
+ # NetAddr.shorten('fec0:0000:0000:0000:0000:0000:0000:0001')
573
426
  #
574
427
  #===Arguments:
575
- #* String
428
+ #* addr = String
576
429
  #
577
430
  #===Returns:
578
431
  #* String
@@ -584,7 +437,7 @@ def shorten(addr)
584
437
  raise ArgumentError, "Expected String, but #{addr.class} provided."
585
438
  end
586
439
 
587
- validate_ip_addr(addr, :Version => 6)
440
+ validate_ip_str(addr, 6)
588
441
 
589
442
  # make sure this isnt already shorthand
590
443
  if (addr =~ /::/)
@@ -593,17 +446,17 @@ def shorten(addr)
593
446
 
594
447
  # split into fields
595
448
  fields = addr.split(":")
596
-
449
+
597
450
  # check last field for ipv4-mapped addr
598
451
  if (fields.last() =~ /\./ )
599
452
  ipv4_mapped = fields.pop()
600
453
  end
601
-
454
+
602
455
  # look for most consecutive '0' fields
603
456
  start_field,end_field = nil,nil
604
457
  start_end = []
605
458
  consecutive,longest = 0,0
606
-
459
+
607
460
  (0..(fields.length-1)).each do |x|
608
461
  fields[x] = fields[x].to_i(16)
609
462
 
@@ -620,7 +473,7 @@ def shorten(addr)
620
473
  if (consecutive > longest)
621
474
  longest = consecutive
622
475
  start_end = [start_field,end_field]
623
- start_field,end_field = nil,nil
476
+ start_field,end_field = nil,nil
624
477
  end
625
478
  consecutive = 0
626
479
  end
@@ -628,7 +481,7 @@ def shorten(addr)
628
481
 
629
482
  fields[x] = fields[x].to_s(16)
630
483
  end
631
-
484
+
632
485
  # if our longest set of 0's is at the end, then start & end fields
633
486
  # are already set. if not, then make start & end fields the ones we've
634
487
  # stored away in start_end
@@ -639,15 +492,15 @@ def shorten(addr)
639
492
  end_field = start_end[1]
640
493
  end
641
494
 
642
- if (longest > 1)
495
+ if (longest > 1)
643
496
  fields[start_field] = ''
644
497
  start_field += 1
645
498
  fields.slice!(start_field..end_field)
646
499
  end
647
- fields.push(ipv4_mapped) if (ipv4_mapped)
648
- short = fields.join(':')
500
+ fields.push(ipv4_mapped) if (ipv4_mapped)
501
+ short = fields.join(':')
649
502
  short << ':' if (short =~ /:$/)
650
-
503
+
651
504
  return(short)
652
505
  end
653
506
  module_function :shorten
@@ -658,16 +511,18 @@ module_function :shorten
658
511
 
659
512
  #===Synopsis
660
513
  #Given a list of CIDR addresses or NetAddr::CIDR objects,
661
- #sort them from lowest to highest by Network/Netmask. NetAddr.sort will use the
514
+ #sort them from lowest to highest by Network/Netmask. This method will use the
662
515
  #base address passed during the initialization of any NetAddr::CIDR
663
516
  #objects, or the base address of any CIDR addresses passed
664
517
  #
665
518
  # Example:
666
- # sorted = NetAddr.sort([cidr1,cidr2])
667
- # sorted = NetAddr.sort(['192.168.1.32/27','192.168.1.0/27','192.168.2.0/24'])
519
+ # cidr1 = NetAddr::CIDR.create('192.168.1.32/27')
520
+ # cidr2 = NetAddr::CIDR.create('192.168.1.0/27')
521
+ # NetAddr.sort([cidr1,cidr2])
522
+ # NetAddr.sort(['192.168.1.32/27','192.168.1.0/27','192.168.2.0/24'])
668
523
  #
669
524
  #===Arguments:
670
- #* Array of CIDR addresses as Strings, or Array of NetAddr::CIDR objects
525
+ #* list = Array of CIDR addresses as Strings, or Array of NetAddr::CIDR objects
671
526
  #
672
527
  #===Returns:
673
528
  #* Array of Strings, or Array of NetAddr::CIDR objects
@@ -695,7 +550,7 @@ def sort(list)
695
550
  new_cidr = cidr
696
551
  end
697
552
  cidr_hash[new_cidr] = cidr
698
-
553
+
699
554
  version = new_cidr.version if (!version)
700
555
  unless (new_cidr.version == version)
701
556
  raise VersionError, "Provided CIDR addresses must all be of the same IP version."
@@ -703,22 +558,8 @@ def sort(list)
703
558
  end
704
559
 
705
560
  # sort by network. if networks are equal, sort by netmask.
706
- sorted_list = []
707
- cidr_hash.each_key do |entry|
708
- index = 0
709
- sorted_list.each do
710
- if(entry.packed_network < (sorted_list[index]).packed_network)
711
- break
712
- elsif (entry.packed_network == (sorted_list[index]).packed_network)
713
- if (entry.packed_netmask < (sorted_list[index]).packed_netmask)
714
- break
715
- end
716
- end
717
- index += 1
718
- end
719
- sorted_list.insert(index, entry)
720
- end
721
-
561
+ sorted_list = cidr_sort(cidr_hash.keys)
562
+
722
563
  # return original values passed
723
564
  ret_list = []
724
565
  sorted_list.each {|x| ret_list.push(cidr_hash[x])}
@@ -732,16 +573,16 @@ module_function :sort
732
573
  #==============================================================================#
733
574
 
734
575
  #===Synopsis
735
- #Unack a packed IP address back into a printable string. Will attempt
736
- #to auto-detect IP version if not provided.
576
+ #Unack a packed IP address back into a printable string. This method will attempt to auto-detect the IP version
577
+ #if not provided, however a slight speed increase is realized if version is provided.
737
578
  #
738
579
  # Example:
739
- # unpacked = NetAddr.unpack_ip_addr(3232235906)
740
- # unpacked = NetAddr.unpack_ip_addr(packed, :Version => 6)
580
+ # NetAddr.unpack_ip_addr(3232235906)
581
+ # NetAddr.unpack_ip_addr(packed, :Version => 6)
741
582
  #
742
583
  #===Arguments:
743
- #* Packed IP address as an Integer
744
- #* Optional Hash with the following keys:
584
+ #* packed_ip = Packed IP address as an Integer
585
+ #* options = Hash with the following keys:
745
586
  # :Version -- IP version - Integer (optional)
746
587
  # :IPv4Mapped -- if true, unpack IPv6 as an IPv4 mapped address (optional)
747
588
  #
@@ -751,74 +592,30 @@ module_function :sort
751
592
  def unpack_ip_addr(packed_ip, options=nil)
752
593
  known_args = [:Version, :IPv4Mapped]
753
594
  ipv4_mapped = false
754
- to_validate = {}
755
-
595
+ version = nil
596
+
756
597
  # validate options
757
598
  if (options)
758
599
  raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
759
600
  NetAddr.validate_args(options.keys,known_args)
760
-
601
+
761
602
  if (options.has_key?(:Version))
762
603
  version = options[:Version]
763
- to_validate[:Version] = version
764
604
  if (version != 4 && version != 6)
765
605
  raise VersionError, ":Version should be 4 or 6, but was '#{version}'."
766
606
  end
767
607
  end
768
-
608
+
769
609
  if (options.has_key?(:IPv4Mapped) && options[:IPv4Mapped] == true)
770
610
  ipv4_mapped = true
771
611
  end
772
612
  end
773
-
774
- # validate
613
+
614
+ # validate & unpack
775
615
  raise ArgumentError, "Integer expected for argument 'packed_ip', " +
776
616
  "but #{packed_ip.class} provided." if (!packed_ip.kind_of?(Integer))
777
- NetAddr.validate_ip_addr(packed_ip, to_validate)
778
-
779
- # set version if not set
780
- if (!version)
781
- if (packed_ip < 2**32)
782
- version = 4
783
- else
784
- version = 6
785
- end
786
- end
787
-
788
- if (version == 4)
789
- octets = []
790
- 4.times do
791
- octet = packed_ip & 0xFF
792
- octets.unshift(octet.to_s)
793
- packed_ip = packed_ip >> 8
794
- end
795
- ip = octets.join('.')
796
- else
797
- fields = []
798
- if (!ipv4_mapped)
799
- loop_count = 8
800
- else
801
- loop_count = 6
802
- packed_v4 = packed_ip & 0xffffffff
803
- ipv4_addr = NetAddr.unpack_ip_addr(packed_v4, :Version => 4)
804
- fields.unshift(ipv4_addr)
805
- packed_ip = packed_ip >> 32
806
- end
807
-
808
- loop_count.times do
809
- octet = packed_ip & 0xFFFF
810
- octet = octet.to_s(16)
811
- packed_ip = packed_ip >> 16
812
-
813
- # if octet < 4 characters, then pad with 0's
814
- (4 - octet.length).times do
815
- octet = '0' << octet
816
- end
817
- fields.unshift(octet)
818
- end
819
- ip = fields.join(':')
820
- end
821
-
617
+ version = validate_ip_int(packed_ip, version)
618
+ ip = ip_int_to_str(packed_ip, version, ipv4_mapped)
822
619
 
823
620
  return(ip)
824
621
  end
@@ -833,40 +630,24 @@ module_function :unpack_ip_addr
833
630
  #bits in the CIDR mask.
834
631
  #
835
632
  # Example:
836
- # unpacked = NetAddr.unpack_ip_netmask(0xfffffffe)
633
+ # NetAddr.unpack_ip_netmask(0xfffffffe)
837
634
  #
838
635
  #===Arguments:
839
- #* Packed netmask as an Integer
636
+ #* packed_netmask = Packed netmask as an Integer
840
637
  #
841
638
  #===Returns:
842
639
  #* Integer
843
640
  #
844
641
  def unpack_ip_netmask(packed_netmask)
845
-
642
+
846
643
  # validate packed_netmask
847
644
  raise ArgumentError, "Integer expected for argument 'packed_netmask', " +
848
645
  "but #{packed_netmask.class} provided." if (!packed_netmask.kind_of?(Integer))
849
-
850
- if (packed_netmask < 2**32)
851
- mask = 32
852
- NetAddr.validate_ip_netmask(packed_netmask, :Packed => true, :Version => 4)
853
- else
854
- NetAddr.validate_ip_netmask(packed_netmask, :Packed => true, :Version => 6)
855
- mask = 128
856
- end
857
-
858
-
859
- mask.times do
860
- if ( (packed_netmask & 1) == 1)
861
- break
862
- end
863
- packed_netmask = packed_netmask >> 1
864
- mask = mask - 1
865
- end
866
646
 
867
- return(mask)
647
+
648
+ return( mask_to_bits(packed_netmask) )
868
649
  end
869
- module_function :unpack_ip_netmask
650
+ module_function :unpack_ip_netmask
870
651
 
871
652
  #==============================================================================#
872
653
  # unshorten()
@@ -877,10 +658,10 @@ module_function :unpack_ip_netmask
877
658
  #notation. The address should not contain a netmask.
878
659
  #
879
660
  # Example:
880
- # long = NetAddr.unshorten('fec0::1')
661
+ # NetAddr.unshorten('fec0::1')
881
662
  #
882
663
  #===Arguments:
883
- #* CIDR address as a String
664
+ #* ip = CIDR address as a String
884
665
  #
885
666
  #===Returns:
886
667
  #* String
@@ -892,16 +673,16 @@ def unshorten(ip)
892
673
  raise ArgumentError, "Expected String, but #{ip.class} provided."
893
674
  end
894
675
 
895
- validate_ip_addr(ip, :Version => 6)
676
+ validate_ip_str(ip, 6)
896
677
  ipv4_mapped = true if (ip =~ /\./)
897
-
898
- packed = pack_ip_addr(ip, :Version => 6)
678
+
679
+ packed = pack_ip_addr(ip, :Version => 6)
899
680
  if (!ipv4_mapped)
900
- long = unpack_ip_addr(packed, :Version => 6)
681
+ long = ip_int_to_str(packed, 6)
901
682
  else
902
- long = unpack_ip_addr(packed, :Version => 6, :IPv4Mapped => true)
683
+ long = ip_int_to_str(packed, 6, true)
903
684
  end
904
-
685
+
905
686
  return(long)
906
687
  end
907
688
  module_function :unshorten
@@ -917,7 +698,7 @@ module_function :unshorten
917
698
  # NetAddr.validate_eui('01-00-5e-12-34-56')
918
699
  #
919
700
  # - Arguments
920
- #* EUI address as a String
701
+ #* eui = EUI address as a String
921
702
  #
922
703
  #===Returns:
923
704
  #* True
@@ -925,10 +706,10 @@ module_function :unshorten
925
706
  def validate_eui(eui)
926
707
  if (eui.kind_of?(String))
927
708
  # check for invalid characters
928
- if (eui =~ /[^0-9a-fA-f\.\-\:]/)
709
+ if (eui =~ /[^0-9a-fA-F\.\-\:]/)
929
710
  raise ValidationError, "#{eui} is invalid (contains invalid characters)."
930
711
  end
931
-
712
+
932
713
  # split on formatting characters & check lengths
933
714
  if (eui =~ /\-/)
934
715
  fields = eui.split('-')
@@ -965,7 +746,8 @@ module_function :validate_eui
965
746
 
966
747
  #===Synopsis
967
748
  #Validate an IP address. The address should not contain a netmask.
968
- #IP version will attempt to be auto-detected if not provided.
749
+ #This method will attempt to auto-detect the IP version
750
+ #if not provided, however a slight speed increase is realized if version is provided.
969
751
  #Raises NetAddr::ValidationError on validation failure.
970
752
  #
971
753
  # Example:
@@ -977,8 +759,8 @@ module_function :validate_eui
977
759
  # NetAddr.validate_ip_addr(2**32-1, :Version => 4)
978
760
  #
979
761
  #===Arguments
980
- #* IP address as a String or Integer
981
- #* Optional Hash with the following keys:
762
+ #* ip = IP address as a String or Integer
763
+ #* options = Hash with the following keys:
982
764
  # :Version -- IP version - Integer (optional)
983
765
  #
984
766
  #===Returns:
@@ -986,12 +768,13 @@ module_function :validate_eui
986
768
  #
987
769
  def validate_ip_addr(ip, options=nil)
988
770
  known_args = [:Version]
989
-
771
+ version = nil
772
+
990
773
  # validate options
991
774
  if (options)
992
775
  raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
993
776
  NetAddr.validate_args(options.keys,known_args)
994
-
777
+
995
778
  if (options.has_key?(:Version))
996
779
  version = options[:Version]
997
780
  if (version != 4 && version != 6)
@@ -999,121 +782,19 @@ def validate_ip_addr(ip, options=nil)
999
782
  end
1000
783
  end
1001
784
  end
1002
-
785
+
1003
786
  if ( ip.kind_of?(String) )
1004
-
1005
- # check validity of charaters
1006
- if (ip =~ /[^0-9a-fA-F\.:]/)
1007
- raise ValidationError, "#{ip} is invalid (contains invalid characters)."
1008
- end
1009
-
1010
- # determine version if not specified
1011
- if (!version && (ip =~ /\./ && ip !~ /:/ ) )
1012
- version = 4
1013
- elsif (!version && ip =~ /:/)
1014
- version = 6
1015
- end
1016
-
1017
- if (version == 4)
1018
- octets = ip.split('.')
1019
- raise ValidationError, "#{ip} is invalid (IPv4 requires (4) octets)." if (octets.length != 4)
1020
-
1021
- # are octets in range 0..255?
1022
- octets.each do |octet|
1023
- raise ValidationError, "#{ip} is invalid (IPv4 dotted-decimal format " +
1024
- "should not contain non-numeric characters)." if (octet =~ /[^0-9]/ )
1025
- octet = octet.to_i()
1026
- if ( (octet < 0) || (octet >= 256) )
1027
- raise ValidationError, "#{ip} is invalid (IPv4 octets should be between 0 and 255)."
1028
- end
1029
- end
1030
-
1031
- elsif (version == 6)
1032
- # make sure we only have at most (2) colons in a row, and then only
1033
- # (1) instance of that
1034
- if ( (ip =~ /:{3,}/) || (ip.split("::").length > 2) )
1035
- raise ValidationError, "#{ip} is invalid (IPv6 field separators (:) are bad)."
1036
- end
1037
-
1038
- # set flags
1039
- shorthand = false
1040
- if (ip =~ /\./)
1041
- dotted_dec = true
1042
- else
1043
- dotted_dec = false
1044
- end
1045
-
1046
- # split up by ':'
1047
- fields = []
1048
- if (ip =~ /::/)
1049
- shorthand = true
1050
- ip.split('::').each do |x|
1051
- fields.concat( x.split(':') )
1052
- end
1053
- else
1054
- fields.concat( ip.split(':') )
1055
- end
1056
-
1057
- # make sure we have the correct number of fields
1058
- if (shorthand)
1059
- if ( (dotted_dec && fields.length > 6) || (!dotted_dec && fields.length > 7) )
1060
- raise ValidationError, "#{ip} is invalid (IPv6 shorthand notation has " +
1061
- "incorrect number of fields)."
1062
- end
1063
- else
1064
- if ( (dotted_dec && fields.length != 7 ) || (!dotted_dec && fields.length != 8) )
1065
- raise ValidationError, "#{ip} is invalid (IPv6 address has " +
1066
- "incorrect number of fields)."
1067
- end
1068
- end
1069
-
1070
- # if dotted_dec then validate the last field
1071
- if (dotted_dec)
1072
- dotted = fields.pop()
1073
- octets = dotted.split('.')
1074
- raise ValidationError, "#{ip} is invalid (Legacy IPv4 portion of IPv6 " +
1075
- "address should contain (4) octets)." if (octets.length != 4)
1076
- octets.each do |x|
1077
- raise ValidationError, "#{ip} is invalid (egacy IPv4 portion of IPv6 " +
1078
- "address should not contain non-numeric characters)." if (x =~ /[^0-9]/ )
1079
- x = x.to_i
1080
- if ( (x < 0) || (x >= 256) )
1081
- raise ValidationError, "#{ip} is invalid (Octets of a legacy IPv4 portion of IPv6 " +
1082
- "address should be between 0 and 255)."
1083
- end
1084
- end
1085
- end
1086
-
1087
- # validate hex fields
1088
- fields.each do |x|
1089
- if (x =~ /[^0-9a-fA-F]/)
1090
- raise ValidationError, "#{ip} is invalid (IPv6 address contains invalid hex characters)."
1091
- else
1092
- x = x.to_i(16)
1093
- if ( (x < 0) || (x >= 2**16) )
1094
- raise ValidationError, "#{ip} is invalid (Fields of an IPv6 address " +
1095
- "should be between 0x0 and 0xFFFF)."
1096
- end
1097
- end
1098
- end
1099
-
1100
- else
1101
- raise ValidationError, "#{ip} is invalid (Did you mean to pass an Integer instead of a String?)."
1102
- end
787
+ version = NetAddr.detect_ip_version(ip) if (!version)
788
+ NetAddr.validate_ip_str(ip,version)
1103
789
 
1104
790
  elsif ( ip.kind_of?(Integer) )
1105
- if (version && version == 4)
1106
- raise ValidationError, "#{ip} is invalid for IPv4 (Integer is out of bounds)." if ( (ip < 0) || (ip > 2**32-1) )
1107
- else
1108
- raise ValidationError, "#{ip} is invalid for IPv6 (Integer is out of bounds)." if ( (ip < 0) || (ip > 2**128-1) )
1109
- end
1110
-
791
+ NetAddr.validate_ip_int(ip,version)
792
+
1111
793
  else
1112
794
  raise ArgumentError, "Integer or String expected for argument 'ip' but " +
1113
795
  "#{ip.class} provided." if (!ip.kind_of?(String) && !ip.kind_of?(Integer))
1114
796
  end
1115
797
 
1116
-
1117
798
  return(true)
1118
799
  end
1119
800
  module_function :validate_ip_addr
@@ -1132,8 +813,8 @@ module_function :validate_ip_addr
1132
813
  # NetAddr.validate_ip_netmask(0xffffffff, :Packed => true)
1133
814
  #
1134
815
  #===Arguments:
1135
- #* Netmask as a String or Integer
1136
- #* Optional Hash with the following keys:
816
+ #* netmask = Netmask as a String or Integer
817
+ #* options = Hash with the following keys:
1137
818
  # :Packed -- if true, the provided Netmask is a packed Integer
1138
819
  # :Version -- IP version - Integer (optional)
1139
820
  #
@@ -1144,93 +825,29 @@ def validate_ip_netmask(netmask, options=nil)
1144
825
  known_args = [:Packed, :Version]
1145
826
  packed = false
1146
827
  version = 4
1147
- max_bits = 32
1148
-
828
+
1149
829
  # validate options
1150
830
  if (options)
1151
831
  raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
1152
832
  NetAddr.validate_args(options.keys,known_args)
1153
-
833
+
1154
834
  if (options.has_key?(:Packed) && options[:Packed] == true)
1155
835
  packed = true
1156
836
  end
1157
-
837
+
1158
838
  if (options.has_key?(:Version))
1159
839
  version = options[:Version]
1160
840
  if (version != 4 && version != 6)
1161
841
  raise ArgumentError, ":Version should be 4 or 6, but was '#{version}'."
1162
- elsif (version == 6)
1163
- max_bits = 128
1164
- else
1165
- max_bits = 32
1166
842
  end
1167
- end
843
+ end
1168
844
  end
1169
-
1170
- if (netmask.kind_of?(String))
1171
- if(netmask =~ /\./)
1172
- all_f = 2**32-1
1173
- packed_netmask = 0
1174
-
1175
- # validate & pack extended mask
1176
- begin
1177
- validate_ip_addr(netmask)
1178
- packed_netmask = pack_ip_addr(netmask)
1179
- rescue Exception
1180
- raise ValidationError, "#{netmask} is an improperly formed IPv4 address."
1181
- end
1182
-
1183
- # cycle through the bits of hostmask and compare
1184
- # with packed_mask. when we hit the firt '1' within
1185
- # packed_mask (our netmask boundary), xor hostmask and
1186
- # packed_mask. the result should be all 1's. this whole
1187
- # process is in place to make sure that we dont have
1188
- # and crazy masks such as 255.254.255.0
1189
- hostmask = 1
1190
- 32.times do
1191
- check = packed_netmask & hostmask
1192
- if ( check != 0)
1193
- hostmask = hostmask >> 1
1194
- unless ( (packed_netmask ^ hostmask) == all_f)
1195
- raise ValidationError, "#{netmask} contains '1' bits within the host portion of the netmask."
1196
- end
1197
- break
1198
- else
1199
- hostmask = hostmask << 1
1200
- hostmask = hostmask | 1
1201
- end
1202
- end
1203
-
1204
- else
1205
- # remove '/' if present
1206
- if (netmask =~ /^\// )
1207
- netmask[0] = " "
1208
- netmask.lstrip!
1209
- end
1210
-
1211
- # check if we have any non numeric characters
1212
- if (netmask =~ /\D/)
1213
- raise ValidationError, "#{netmask} contains invalid characters."
1214
- end
1215
-
1216
- netmask = netmask.to_i
1217
- if (netmask > max_bits || netmask == 0 )
1218
- raise ValidationError, "Netmask, #{netmask}, is out of bounds for IPv#{version}."
1219
- end
1220
845
 
1221
- end
1222
-
846
+ # validate netmask
847
+ if (netmask.kind_of?(String))
848
+ validate_netmask_str(netmask,version)
1223
849
  elsif (netmask.kind_of?(Integer) )
1224
- if (!packed)
1225
- if (netmask > max_bits || netmask == 0 )
1226
- raise ValidationError, "Netmask, #{netmask}, is out of bounds for IPv#{version}."
1227
- end
1228
- else
1229
- if (netmask >= 2**max_bits || netmask == 0 )
1230
- raise ValidationError, "Packed netmask, #{netmask}, is out of bounds for IPv#{version}."
1231
- end
1232
- end
1233
-
850
+ validate_netmask_int(netmask,version,packed)
1234
851
  else
1235
852
  raise ArgumentError, "Integer or String expected for argument 'netmask' but " +
1236
853
  "#{netmask.class} provided." if (!netmask.kind_of?(String) && !netmask.kind_of?(Integer))
@@ -1257,7 +874,7 @@ module_function :validate_ip_netmask
1257
874
  # NetAddr.wildcard('fec0:1:*')
1258
875
  #
1259
876
  #===Arguments:
1260
- #* Wildcard IP address as a String
877
+ #* ip = Wildcard IP address as a String
1261
878
  #
1262
879
  #===Returns:
1263
880
  #* CIDR object
@@ -1276,18 +893,18 @@ def wildcard(ip)
1276
893
  end
1277
894
  octets.push(x)
1278
895
  end
1279
-
896
+
1280
897
  octets.length.times do
1281
898
  mask = mask << 8
1282
899
  mask = mask | 0xff
1283
900
  end
1284
-
901
+
1285
902
  until (octets.length == 4)
1286
903
  octets.push('0')
1287
904
  mask = mask << 8
1288
905
  end
1289
906
  ip = octets.join('.')
1290
-
907
+
1291
908
  elsif (ip =~ /:/)
1292
909
  version = 6
1293
910
  fields = []
@@ -1314,46 +931,16 @@ def wildcard(ip)
1314
931
  end
1315
932
  ip = fields.join(':')
1316
933
  end
1317
-
934
+
1318
935
  # make & return cidr
1319
- cidr = NetAddr::CIDR.create(ip, :PackedNetmask => mask, :Version => version)
936
+ cidr = cidr_build( version, ip_str_to_int(ip,version), mask )
937
+
1320
938
  return(cidr)
1321
939
  end
1322
940
  module_function :wildcard
1323
941
 
1324
- #==============================================================================#
1325
- # NetStruct
1326
- #==============================================================================#
1327
-
1328
- #===NetStruct
1329
- # Struct object used internally by NetAddr. It is not likely directly useful
1330
- # to anyone.
1331
- #
1332
- # Description of fields:
1333
- # * cidr - NetAddr::CIDR object
1334
- # * parent - parent NetStruct in tree
1335
- # * children - Array of children NetStruct objects
1336
- #
1337
- NetStruct = Struct.new(:cidr, :parent, :children) #:nodoc:
1338
-
1339
-
1340
- # PRIVATE METHODS
1341
- private
1342
942
 
1343
943
 
1344
- #==============================================================================#
1345
- # validate_args()
1346
- #==============================================================================#
1347
-
1348
- # validate options hash
1349
- #
1350
- def validate_args(to_validate,known_args)
1351
- to_validate.each do |x|
1352
- raise ArgumentError, "Unrecognized argument #{x}. Valid arguments are " +
1353
- "#{known_args.join(',')}" if (!known_args.include?(x))
1354
- end
1355
- end
1356
- module_function :validate_args
1357
944
 
1358
945
  end # module NetAddr
1359
946