netaddr 1.5.3 → 2.0.1
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.
- checksums.yaml +5 -5
- data/LICENSE +201 -0
- data/README.md +28 -8
- data/lib/eui48.rb +65 -0
- data/lib/eui64.rb +77 -0
- data/lib/ipv4.rb +77 -0
- data/lib/ipv4net.rb +245 -0
- data/lib/ipv6.rb +110 -0
- data/lib/ipv6net.rb +246 -0
- data/lib/mask128.rb +68 -0
- data/lib/mask32.rb +99 -0
- data/lib/netaddr.rb +104 -20
- data/lib/util.rb +310 -0
- data/test/eui48_test.rb +30 -0
- data/test/eui64_test.rb +32 -0
- data/test/examples.rb +137 -0
- data/test/ipv4_test.rb +54 -0
- data/test/ipv4net_test.rb +166 -0
- data/test/ipv6_test.rb +90 -0
- data/test/ipv6net_test.rb +146 -0
- data/test/mask128_test.rb +45 -0
- data/test/mask32_test.rb +51 -0
- data/test/netaddr_test.rb +127 -0
- data/test/run_all.rb +10 -0
- metadata +28 -22
- data/Errors +0 -7
- data/changelog +0 -52
- data/lib/cidr.rb +0 -2014
- data/lib/cidr_shortcuts.rb +0 -401
- data/lib/eui.rb +0 -402
- data/lib/ip_math.rb +0 -227
- data/lib/methods.rb +0 -1013
- data/lib/tree.rb +0 -816
- data/lib/validation_shortcuts.rb +0 -201
- data/license +0 -13
- data/test/cidr_test.rb +0 -545
- data/test/eui_test.rb +0 -101
- data/test/methods_test.rb +0 -331
- data/test/tree_test.rb +0 -347
data/lib/methods.rb
DELETED
@@ -1,1013 +0,0 @@
|
|
1
|
-
module NetAddr
|
2
|
-
|
3
|
-
#===Synopsis
|
4
|
-
#Convert an Integer representing a binary netmask into an Integer representing
|
5
|
-
#the number of bits in that netmask.
|
6
|
-
#
|
7
|
-
# Example:
|
8
|
-
# NetAddr.i_to_bits(0xfffffffe) => 31
|
9
|
-
# NetAddr.i_to_bits(0xffffffffffffffff0000000000000000) => 64
|
10
|
-
#
|
11
|
-
#===Arguments:
|
12
|
-
#* netmask_int = Integer representing a binary netmask
|
13
|
-
#
|
14
|
-
#===Returns:
|
15
|
-
#* Integer
|
16
|
-
#
|
17
|
-
def i_to_bits(netmask_int)
|
18
|
-
|
19
|
-
# validate netmask_int
|
20
|
-
raise ArgumentError, "Integer expected for argument 'netmask_int', " +
|
21
|
-
"but #{netmask_int.class} provided." if (!netmask_int.kind_of?(Integer))
|
22
|
-
|
23
|
-
|
24
|
-
return( mask_to_bits(netmask_int) )
|
25
|
-
end
|
26
|
-
module_function :i_to_bits
|
27
|
-
|
28
|
-
#===Synopsis
|
29
|
-
#Convert an Integer into an IP address. This method will attempt to auto-detect the IP version
|
30
|
-
#if not provided, however, a slight speed increase is realized if version is provided.
|
31
|
-
#
|
32
|
-
# Example:
|
33
|
-
# NetAddr.i_to_ip(3232235906) => "192.168.1.130"
|
34
|
-
# NetAddr.i_to_ip(0xffff0000000000000000000000000001, :Version => 6) => "ffff:0000:0000:0000:0000:0000:0000:0001"
|
35
|
-
#
|
36
|
-
#===Arguments:
|
37
|
-
#* ip_int = IP address as an Integer
|
38
|
-
#* options = Hash with the following keys:
|
39
|
-
# :Version -- IP version - Integer (optional)
|
40
|
-
# :IPv4Mapped -- if true, unpack IPv6 as an IPv4 mapped address (optional)
|
41
|
-
#
|
42
|
-
#===Returns:
|
43
|
-
#* String
|
44
|
-
#
|
45
|
-
def i_to_ip(ip_int, options=nil)
|
46
|
-
known_args = [:Version, :IPv4Mapped]
|
47
|
-
ipv4_mapped = false
|
48
|
-
version = nil
|
49
|
-
|
50
|
-
# validate options
|
51
|
-
if (options)
|
52
|
-
raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
|
53
|
-
NetAddr.validate_args(options.keys,known_args)
|
54
|
-
|
55
|
-
if (options.has_key?(:Version))
|
56
|
-
version = options[:Version]
|
57
|
-
if (version != 4 && version != 6)
|
58
|
-
raise VersionError, ":Version should be 4 or 6, but was '#{version}'."
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
if (options.has_key?(:IPv4Mapped) && options[:IPv4Mapped] == true)
|
63
|
-
ipv4_mapped = true
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# validate & unpack
|
68
|
-
raise ArgumentError, "Integer expected for argument 'ip_int', " +
|
69
|
-
"but #{ip_int.class} provided." if (!ip_int.kind_of?(Integer))
|
70
|
-
version = validate_ip_int(ip_int, version)
|
71
|
-
ip = ip_int_to_str(ip_int, version, ipv4_mapped)
|
72
|
-
|
73
|
-
return(ip)
|
74
|
-
end
|
75
|
-
module_function :i_to_ip
|
76
|
-
|
77
|
-
#===Synopsis
|
78
|
-
#Convert IP addresses into an Integer. This method will attempt to auto-detect the IP version
|
79
|
-
#if not provided, however a slight speed increase is realized if version is provided.
|
80
|
-
#
|
81
|
-
# Example:
|
82
|
-
# NetAddr.ip_to_i('192.168.1.1') => 3232235777
|
83
|
-
# NetAddr.ip_to_i('ffff::1', :Version => 6) => 340277174624079928635746076935438991361
|
84
|
-
# NetAddr.ip_to_i('::192.168.1.1') => 3232235777
|
85
|
-
#
|
86
|
-
#===Arguments:
|
87
|
-
#* ip = IP address as a String
|
88
|
-
#* options = Hash with the following keys:
|
89
|
-
# :Version -- IP version - Integer
|
90
|
-
#
|
91
|
-
#===Returns:
|
92
|
-
#* Integer
|
93
|
-
#
|
94
|
-
def ip_to_i(ip, options=nil)
|
95
|
-
known_args = [:Version]
|
96
|
-
to_validate = {}
|
97
|
-
version = nil
|
98
|
-
|
99
|
-
# validate options
|
100
|
-
if (options)
|
101
|
-
raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
|
102
|
-
validate_args(options.keys,known_args)
|
103
|
-
|
104
|
-
if (options.has_key?(:Version))
|
105
|
-
version = options[:Version]
|
106
|
-
to_validate[:Version] = version
|
107
|
-
if (version != 4 && version != 6)
|
108
|
-
raise VersionError, ":Version should be 4 or 6, but was '#{version}'."
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
if ( ip.kind_of?(String) )
|
114
|
-
version = detect_ip_version(ip) if (!version)
|
115
|
-
validate_ip_str(ip,version)
|
116
|
-
ip_int = ip_str_to_int(ip,version)
|
117
|
-
|
118
|
-
else
|
119
|
-
raise ArgumentError, "String expected for argument 'ip' but #{ip.class} provided."
|
120
|
-
end
|
121
|
-
|
122
|
-
return(ip_int)
|
123
|
-
end
|
124
|
-
module_function :ip_to_i
|
125
|
-
|
126
|
-
#===Synopsis
|
127
|
-
#Given a list of CIDR addresses or NetAddr::CIDR objects,
|
128
|
-
#merge (summarize) them in the most efficient way possible. Summarization
|
129
|
-
#will only occur when the newly created supernets will not result in the
|
130
|
-
#'creation' of new IP space. For example the following blocks
|
131
|
-
#(192.168.0.0/24, 192.168.1.0/24, and 192.168.2.0/24) would be summarized into
|
132
|
-
#192.168.0.0/23 and 192.168.2.0/24 rather than into 192.168.0.0/22
|
133
|
-
#
|
134
|
-
#I have designed this with enough flexibility so that you can pass in CIDR
|
135
|
-
#addresses that arent even related (ex. 192.168.1.0/26, 192.168.1.64/27, 192.168.1.96/27
|
136
|
-
#10.1.0.0/26, 10.1.0.64/26) and they will be merged properly (ie 192.168.1.0/25,
|
137
|
-
#and 10.1.0.0/25 would be returned).
|
138
|
-
#
|
139
|
-
#If the :Objectify option is enabled, then any summary addresses returned will
|
140
|
-
#contain the original CIDRs used to create them within the tag value :Subnets
|
141
|
-
#(ie. cidr_x.tag[:Subnets] would be an Array of the CIDRs used to create cidr_x)
|
142
|
-
#
|
143
|
-
# Example:
|
144
|
-
# cidr1 = NetAddr::CIDR.create('192.168.1.0/27')
|
145
|
-
# cidr2 = NetAddr::CIDR.create('192.168.1.32/27')
|
146
|
-
# NetAddr.merge([cidr1,cidr2])
|
147
|
-
# ip_net_range = NetAddr.range('192.168.35.0','192.168.39.255',:Inclusive => true, :Objectify => true)
|
148
|
-
# NetAddr.merge(ip_net_range, :Objectify => true)
|
149
|
-
#
|
150
|
-
#===Arguments:
|
151
|
-
#* list = Array of CIDR addresses as Strings, or an Array of NetAddr::CIDR objects
|
152
|
-
#* options = Hash with the following keys:
|
153
|
-
# :Objectify -- if true, return NetAddr::CIDR objects
|
154
|
-
# :Short -- if true, return IPv6 addresses in short-hand notation
|
155
|
-
#
|
156
|
-
#===Returns:
|
157
|
-
#* Array of CIDR addresses or NetAddr::CIDR objects
|
158
|
-
#
|
159
|
-
def merge(list,options=nil)
|
160
|
-
known_args = [:Objectify, :Short]
|
161
|
-
short = false
|
162
|
-
objectify = false
|
163
|
-
verbose = false
|
164
|
-
|
165
|
-
# validate list
|
166
|
-
raise ArgumentError, "Array expected for argument 'list' but #{list.class} provided." if (!list.kind_of?(Array) )
|
167
|
-
|
168
|
-
# validate options
|
169
|
-
if (options)
|
170
|
-
raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash) )
|
171
|
-
NetAddr.validate_args(options.keys,known_args)
|
172
|
-
|
173
|
-
if (options.has_key?(:Objectify) && options[:Objectify] == true)
|
174
|
-
objectify = true
|
175
|
-
end
|
176
|
-
|
177
|
-
if (options.has_key?(:Short) && options[:Short] == true)
|
178
|
-
short = true
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
# make sure all are valid types of the same IP version
|
183
|
-
v4_list = []
|
184
|
-
v6_list = []
|
185
|
-
list.each do |obj|
|
186
|
-
if (!obj.kind_of?(NetAddr::CIDR))
|
187
|
-
begin
|
188
|
-
obj = NetAddr::CIDR.create(obj)
|
189
|
-
rescue Exception => error
|
190
|
-
raise ArgumentError, "One of the provided CIDR addresses raised the following " +
|
191
|
-
"errors: #{error}"
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
if (obj.version == 4)
|
196
|
-
v4_list.push(obj)
|
197
|
-
else
|
198
|
-
v6_list.push(obj)
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
# summarize
|
203
|
-
v4_summary = []
|
204
|
-
v6_summary = []
|
205
|
-
if (v4_list.length != 0)
|
206
|
-
v4_summary = NetAddr.cidr_summarize(v4_list)
|
207
|
-
end
|
208
|
-
|
209
|
-
if (v6_list.length != 0)
|
210
|
-
v6_summary = NetAddr.cidr_summarize(v6_list)
|
211
|
-
end
|
212
|
-
|
213
|
-
# decide what to return
|
214
|
-
summarized_list = []
|
215
|
-
if (!objectify)
|
216
|
-
summarized_list = []
|
217
|
-
if (v4_summary.length != 0)
|
218
|
-
v4_summary.each {|x| summarized_list.push(x.desc())}
|
219
|
-
end
|
220
|
-
|
221
|
-
if (v6_summary.length != 0)
|
222
|
-
v6_summary.each {|x| summarized_list.push(x.desc(:Short => short))}
|
223
|
-
end
|
224
|
-
|
225
|
-
else
|
226
|
-
summarized_list.concat(v4_summary) if (v4_summary.length != 0)
|
227
|
-
summarized_list.concat(v6_summary) if (v6_summary.length != 0)
|
228
|
-
end
|
229
|
-
|
230
|
-
return(summarized_list)
|
231
|
-
end
|
232
|
-
module_function :merge
|
233
|
-
|
234
|
-
#===Synopsis
|
235
|
-
#Given the number of IP addresses required in a subnet, return the minimum
|
236
|
-
#netmask (bits by default) required for that subnet. IP version is assumed to be 4 unless specified otherwise.
|
237
|
-
#
|
238
|
-
# Example:
|
239
|
-
# NetAddr.minimum_size(14) => 28
|
240
|
-
# NetAddr.minimum_size(65536, :Version => 6) => 112
|
241
|
-
#
|
242
|
-
#===Arguments:
|
243
|
-
#* ipcount = IP count as an Integer
|
244
|
-
#* options = Hash with the following keys:
|
245
|
-
# :Extended -- If true, then return the netmask, as a String, in extended format (IPv4 only y.y.y.y)
|
246
|
-
# :Version -- IP version - Integer
|
247
|
-
#
|
248
|
-
#===Returns:
|
249
|
-
#* Integer or String
|
250
|
-
#
|
251
|
-
def minimum_size(ipcount, options=nil)
|
252
|
-
version = 4
|
253
|
-
extended = false
|
254
|
-
known_args = [:Version, :Extended]
|
255
|
-
|
256
|
-
# validate ipcount
|
257
|
-
raise ArgumentError, "Integer expected for argument 'ipcount' but #{ipcount.class} provided." if (!ipcount.kind_of?(Integer))
|
258
|
-
|
259
|
-
# validate options
|
260
|
-
if (options)
|
261
|
-
raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
|
262
|
-
|
263
|
-
NetAddr.validate_args(options.keys,known_args)
|
264
|
-
|
265
|
-
if (options.has_key?(:Version))
|
266
|
-
version = options[:Version]
|
267
|
-
end
|
268
|
-
|
269
|
-
if (options.has_key?(:Extended) && options[:Extended] == true)
|
270
|
-
extended = true
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
return( ip_count_to_size(ipcount,version,extended) )
|
275
|
-
end
|
276
|
-
module_function :minimum_size
|
277
|
-
|
278
|
-
#===Synopsis
|
279
|
-
#Convert IP netmask into an Integer. Netmask may be in either CIDR (/yy) or
|
280
|
-
#extended (y.y.y.y) format. CIDR formatted netmasks may either
|
281
|
-
#be a String or an Integer. IP version defaults to 4. It may be necessary
|
282
|
-
#to specify the version if an IPv6 netmask of /32 or smaller is provided.
|
283
|
-
#
|
284
|
-
# Example:
|
285
|
-
# NetAddr.netmask_to_i('255.255.255.0') => 4294967040
|
286
|
-
# NetAddr.netmask_to_i('24') => 4294967040
|
287
|
-
# NetAddr.netmask_to_i(24) => 4294967040
|
288
|
-
# NetAddr.netmask_to_i('/24') => 4294967040
|
289
|
-
# NetAddr.netmask_to_i('32', :Version => 6) => 340282366841710300949110269838224261120
|
290
|
-
#
|
291
|
-
#===Arguments
|
292
|
-
#* netmask = Netmask as a String or Integer
|
293
|
-
#* options = Hash with the following keys:
|
294
|
-
# :Version -- IP version - Integer
|
295
|
-
#
|
296
|
-
#===Returns:
|
297
|
-
#* Integer
|
298
|
-
#
|
299
|
-
def netmask_to_i(netmask, options=nil)
|
300
|
-
known_args = [:Version]
|
301
|
-
version = 4
|
302
|
-
netmask_int = nil
|
303
|
-
|
304
|
-
# validate options
|
305
|
-
if (options)
|
306
|
-
raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
|
307
|
-
NetAddr.validate_args(options.keys,known_args)
|
308
|
-
|
309
|
-
if (options.has_key?(:Version))
|
310
|
-
version = options[:Version]
|
311
|
-
if (version != 4 && version != 6)
|
312
|
-
raise VersionError, ":Version should be 4 or 6, but was '#{version}'."
|
313
|
-
end
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
if (netmask.kind_of?(String))
|
318
|
-
validate_netmask_str(netmask, version)
|
319
|
-
netmask_int = netmask_str_to_int(netmask,version)
|
320
|
-
|
321
|
-
elsif (netmask.kind_of?(Integer))
|
322
|
-
validate_netmask_int(netmask, version, true)
|
323
|
-
netmask_int = bits_to_mask(netmask,version)
|
324
|
-
|
325
|
-
else
|
326
|
-
raise ArgumentError, "String or Integer expected for argument 'netmask', " +
|
327
|
-
"but #{netmask.class} provided." if (!netmask.kind_of?(Integer) && !netmask.kind_of?(String))
|
328
|
-
end
|
329
|
-
|
330
|
-
return(netmask_int)
|
331
|
-
end
|
332
|
-
module_function :netmask_to_i
|
333
|
-
|
334
|
-
#===Synopsis
|
335
|
-
#Given two CIDR addresses or NetAddr::CIDR objects of the same version,
|
336
|
-
#return all IP addresses between them. NetAddr.range will use the original IP
|
337
|
-
#address passed during the initialization of the NetAddr::CIDR objects, or the
|
338
|
-
#IP address portion of any CIDR addresses passed. The default behavior is to be
|
339
|
-
#non-inclusive (don't include boundaries as part of returned data).
|
340
|
-
#
|
341
|
-
# Example:
|
342
|
-
# lower = NetAddr::CIDR.create('192.168.35.0')
|
343
|
-
# upper = NetAddr::CIDR.create('192.168.39.255')
|
344
|
-
# NetAddr.range(lower,upper, :Limit => 10, :Bitstep => 32)
|
345
|
-
# NetAddr.range('192.168.35.0','192.168.39.255', :Inclusive => true)
|
346
|
-
# NetAddr.range('192.168.35.0','192.168.39.255', :Inclusive => true, :Size => true)
|
347
|
-
#
|
348
|
-
#===Arguments:
|
349
|
-
#* lower = Lower boundary CIDR as a String or NetAddr::CIDR object
|
350
|
-
#* upper = Upper boundary CIDR as a String or NetAddr::CIDR object
|
351
|
-
#* options = Hash with the following keys:
|
352
|
-
# :Bitstep -- enumerate in X sized steps - Integer
|
353
|
-
# :Inclusive -- if true, include boundaries in returned data
|
354
|
-
# :Limit -- limit returned list to X number of items - Integer
|
355
|
-
# :Objectify -- if true, return CIDR objects
|
356
|
-
# :Short -- if true, return IPv6 addresses in short-hand notation
|
357
|
-
# :Size -- if true, return the number of addresses in this range, but not the addresses themselves
|
358
|
-
#
|
359
|
-
#===Returns:
|
360
|
-
#* Array of Strings or NetAddr::CIDR objects, or an Integer
|
361
|
-
#
|
362
|
-
#===Note:
|
363
|
-
#If you do not need all of the fancy options in this method, then please consider
|
364
|
-
#using the standard Ruby Range class as shown below.
|
365
|
-
#
|
366
|
-
# Example:
|
367
|
-
# start = NetAddr::CIDR.create('192.168.1.0')
|
368
|
-
# fin = NetAddr::CIDR.create('192.168.2.3')
|
369
|
-
# (start..fin).each {|addr| puts addr.desc}
|
370
|
-
#
|
371
|
-
def range(lower, upper, options=nil)
|
372
|
-
known_args = [:Bitstep, :Inclusive, :Limit, :Objectify, :Short, :Size]
|
373
|
-
list = []
|
374
|
-
bitstep = 1
|
375
|
-
objectify = false
|
376
|
-
short = false
|
377
|
-
size_only = false
|
378
|
-
inclusive = false
|
379
|
-
limit = nil
|
380
|
-
|
381
|
-
# if lower/upper are not CIDR objects, then attempt to create
|
382
|
-
# cidr objects from them
|
383
|
-
if ( !lower.kind_of?(NetAddr::CIDR) )
|
384
|
-
begin
|
385
|
-
lower = NetAddr::CIDR.create(lower)
|
386
|
-
rescue Exception => error
|
387
|
-
raise ArgumentError, "Argument 'lower' raised the following " +
|
388
|
-
"errors: #{error}"
|
389
|
-
end
|
390
|
-
end
|
391
|
-
|
392
|
-
if ( !upper.kind_of?(NetAddr::CIDR))
|
393
|
-
begin
|
394
|
-
upper = NetAddr::CIDR.create(upper)
|
395
|
-
rescue Exception => error
|
396
|
-
raise ArgumentError, "Argument 'upper' raised the following " +
|
397
|
-
"errors: #{error}"
|
398
|
-
end
|
399
|
-
end
|
400
|
-
|
401
|
-
# validate options
|
402
|
-
if (options)
|
403
|
-
raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
|
404
|
-
NetAddr.validate_args(options.keys,known_args)
|
405
|
-
|
406
|
-
if( options.has_key?(:Bitstep) )
|
407
|
-
bitstep = options[:Bitstep]
|
408
|
-
end
|
409
|
-
|
410
|
-
if( options.has_key?(:Objectify) && options[:Objectify] == true )
|
411
|
-
objectify = true
|
412
|
-
end
|
413
|
-
|
414
|
-
if( options.has_key?(:Short) && options[:Short] == true )
|
415
|
-
short = true
|
416
|
-
end
|
417
|
-
|
418
|
-
if( options.has_key?(:Size) && options[:Size] == true )
|
419
|
-
size_only = true
|
420
|
-
end
|
421
|
-
|
422
|
-
if( options.has_key?(:Inclusive) && options[:Inclusive] == true )
|
423
|
-
inclusive = true
|
424
|
-
end
|
425
|
-
|
426
|
-
if( options.has_key?(:Limit) )
|
427
|
-
limit = options[:Limit]
|
428
|
-
end
|
429
|
-
end
|
430
|
-
|
431
|
-
# check version, store & sort
|
432
|
-
if (lower.version == upper.version)
|
433
|
-
version = lower.version
|
434
|
-
boundaries = [lower.to_i(:ip), upper.to_i(:ip)]
|
435
|
-
boundaries.sort
|
436
|
-
else
|
437
|
-
raise VersionError, "Provided NetAddr::CIDR objects are of different IP versions."
|
438
|
-
end
|
439
|
-
|
440
|
-
# dump our range
|
441
|
-
if (!inclusive)
|
442
|
-
my_ip = boundaries[0] + 1
|
443
|
-
end_ip = boundaries[1]
|
444
|
-
else
|
445
|
-
my_ip = boundaries[0]
|
446
|
-
end_ip = boundaries[1] + 1
|
447
|
-
end
|
448
|
-
|
449
|
-
if (!size_only)
|
450
|
-
until (my_ip >= end_ip)
|
451
|
-
if (!objectify)
|
452
|
-
my_ip_s = ip_int_to_str(my_ip, version)
|
453
|
-
my_ips = shorten(my_ips) if (short && version == 6)
|
454
|
-
list.push(my_ip_s)
|
455
|
-
else
|
456
|
-
list.push( cidr_build(version,my_ip) )
|
457
|
-
end
|
458
|
-
|
459
|
-
my_ip = my_ip + bitstep
|
460
|
-
if (limit)
|
461
|
-
limit = limit - 1
|
462
|
-
break if (limit == 0)
|
463
|
-
end
|
464
|
-
end
|
465
|
-
else
|
466
|
-
list = end_ip - my_ip
|
467
|
-
end
|
468
|
-
|
469
|
-
return(list)
|
470
|
-
end
|
471
|
-
module_function :range
|
472
|
-
|
473
|
-
#===Synopsis
|
474
|
-
#Take a standard IPv6 address and format it in short-hand notation.
|
475
|
-
#The address should not contain a netmask.
|
476
|
-
#
|
477
|
-
# Example:
|
478
|
-
# NetAddr.shorten('fec0:0000:0000:0000:0000:0000:0000:0001') => "fec0::1"
|
479
|
-
#
|
480
|
-
#===Arguments:
|
481
|
-
#* addr = String
|
482
|
-
#
|
483
|
-
#===Returns:
|
484
|
-
#* String
|
485
|
-
#
|
486
|
-
def shorten(addr)
|
487
|
-
|
488
|
-
# is this a string?
|
489
|
-
if (!addr.kind_of? String)
|
490
|
-
raise ArgumentError, "Expected String, but #{addr.class} provided."
|
491
|
-
end
|
492
|
-
|
493
|
-
validate_ip_str(addr, 6)
|
494
|
-
|
495
|
-
# make sure this isnt already shorthand
|
496
|
-
if (addr =~ /::/)
|
497
|
-
return(addr)
|
498
|
-
end
|
499
|
-
|
500
|
-
# split into fields
|
501
|
-
fields = addr.split(":")
|
502
|
-
|
503
|
-
# check last field for ipv4-mapped addr
|
504
|
-
if (fields.last() =~ /\./ )
|
505
|
-
ipv4_mapped = fields.pop()
|
506
|
-
end
|
507
|
-
|
508
|
-
# look for most consecutive '0' fields
|
509
|
-
start_field,end_field = nil,nil
|
510
|
-
start_end = []
|
511
|
-
consecutive,longest = 0,0
|
512
|
-
|
513
|
-
(0..(fields.length-1)).each do |x|
|
514
|
-
fields[x] = fields[x].to_i(16)
|
515
|
-
|
516
|
-
if (fields[x] == 0)
|
517
|
-
if (!start_field)
|
518
|
-
start_field = x
|
519
|
-
end_field = x
|
520
|
-
else
|
521
|
-
end_field = x
|
522
|
-
end
|
523
|
-
consecutive += 1
|
524
|
-
else
|
525
|
-
if (start_field)
|
526
|
-
if (consecutive > longest)
|
527
|
-
longest = consecutive
|
528
|
-
start_end = [start_field,end_field]
|
529
|
-
start_field,end_field = nil,nil
|
530
|
-
end
|
531
|
-
consecutive = 0
|
532
|
-
end
|
533
|
-
end
|
534
|
-
|
535
|
-
fields[x] = fields[x].to_s(16)
|
536
|
-
end
|
537
|
-
|
538
|
-
# if our longest set of 0's is at the end, then start & end fields
|
539
|
-
# are already set. if not, then make start & end fields the ones we've
|
540
|
-
# stored away in start_end
|
541
|
-
if (consecutive > longest)
|
542
|
-
longest = consecutive
|
543
|
-
else
|
544
|
-
start_field = start_end[0]
|
545
|
-
end_field = start_end[1]
|
546
|
-
end
|
547
|
-
|
548
|
-
if (longest > 1)
|
549
|
-
fields[start_field] = ''
|
550
|
-
start_field += 1
|
551
|
-
fields.slice!(start_field..end_field)
|
552
|
-
end
|
553
|
-
fields.push(ipv4_mapped) if (ipv4_mapped)
|
554
|
-
short = fields.join(':')
|
555
|
-
short << ':' if (short =~ /:$/)
|
556
|
-
|
557
|
-
return(short)
|
558
|
-
end
|
559
|
-
module_function :shorten
|
560
|
-
|
561
|
-
#===Synopsis
|
562
|
-
#Sort a list of CIDR addresses or NetAddr::CIDR objects,
|
563
|
-
#
|
564
|
-
# Example:
|
565
|
-
# cidr1 = NetAddr::CIDR.create('192.168.1.32/27')
|
566
|
-
# cidr2 = NetAddr::CIDR.create('192.168.1.0/27')
|
567
|
-
# NetAddr.sort([cidr1,cidr2])
|
568
|
-
# NetAddr.sort(['192.168.1.32/27','192.168.1.0/27','192.168.2.0/24'], :Desc => true)
|
569
|
-
#
|
570
|
-
#===Arguments:
|
571
|
-
#* list = Array of CIDR addresses as Strings, or Array of NetAddr::CIDR objects
|
572
|
-
#* options = Hash with the following keys:
|
573
|
-
# :ByMask -- if true, sorts based on the netmask length
|
574
|
-
# :Desc -- if true, return results in descending order
|
575
|
-
#
|
576
|
-
#===Returns:
|
577
|
-
#* Array of Strings, or Array of NetAddr::CIDR objects
|
578
|
-
#
|
579
|
-
def sort(list, options=nil)
|
580
|
-
# make sure list is an array
|
581
|
-
if ( !list.kind_of?(Array) )
|
582
|
-
raise ArgumentError, "Array of NetAddr::CIDR or NetStruct " +
|
583
|
-
"objects expected, but #{list.class} provided."
|
584
|
-
end
|
585
|
-
|
586
|
-
desc = false
|
587
|
-
by_mask = false
|
588
|
-
# validate options
|
589
|
-
if (options)
|
590
|
-
known_args = [:Desc, :ByMask]
|
591
|
-
raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
|
592
|
-
NetAddr.validate_args(options.keys,known_args)
|
593
|
-
|
594
|
-
if( options.has_key?(:Desc) && options[:Desc] == true )
|
595
|
-
desc = true
|
596
|
-
end
|
597
|
-
|
598
|
-
if( options.has_key?(:ByMask) && options[:ByMask] == true )
|
599
|
-
by_mask = true
|
600
|
-
end
|
601
|
-
|
602
|
-
end
|
603
|
-
|
604
|
-
# make sure all are valid types of the same IP version
|
605
|
-
version = nil
|
606
|
-
cidr_hash = {}
|
607
|
-
list.each do |cidr|
|
608
|
-
if (!cidr.kind_of?(NetAddr::CIDR))
|
609
|
-
begin
|
610
|
-
new_cidr = NetAddr::CIDR.create(cidr)
|
611
|
-
rescue Exception => error
|
612
|
-
raise ArgumentError, "An element of the provided Array " +
|
613
|
-
"raised the following errors: #{error}"
|
614
|
-
end
|
615
|
-
else
|
616
|
-
new_cidr = cidr
|
617
|
-
end
|
618
|
-
cidr_hash[new_cidr] = cidr
|
619
|
-
|
620
|
-
version = new_cidr.version if (!version)
|
621
|
-
unless (new_cidr.version == version)
|
622
|
-
raise VersionError, "Provided CIDR addresses must all be of the same IP version."
|
623
|
-
end
|
624
|
-
end
|
625
|
-
|
626
|
-
# perform sort
|
627
|
-
if (by_mask)
|
628
|
-
sorted_list = netmask_sort(cidr_hash.keys, desc)
|
629
|
-
else
|
630
|
-
sorted_list = cidr_sort(cidr_hash.keys, desc)
|
631
|
-
end
|
632
|
-
|
633
|
-
# return original values passed
|
634
|
-
ret_list = []
|
635
|
-
sorted_list.each {|x| ret_list.push(cidr_hash[x])}
|
636
|
-
|
637
|
-
return(ret_list)
|
638
|
-
end
|
639
|
-
module_function :sort
|
640
|
-
|
641
|
-
#===Synopsis
|
642
|
-
#Given a list of CIDR addresses or NetAddr::CIDR objects,
|
643
|
-
#return only the top-level supernet CIDR addresses.
|
644
|
-
#
|
645
|
-
#
|
646
|
-
#If the :Objectify option is enabled, then returned CIDR objects will
|
647
|
-
#store the more specific CIDRs (i.e. subnets of those CIDRs) within the tag value :Subnets
|
648
|
-
#For example, cidr_x.tag[:Subnets] would be an Array of CIDR subnets of cidr_x.
|
649
|
-
#
|
650
|
-
# Example:
|
651
|
-
# NetAddr.supernets(['192.168.0.0', '192.168.0.1', '192.168.0.0/31'])
|
652
|
-
#
|
653
|
-
#===Arguments:
|
654
|
-
#* list = Array of CIDR addresses as Strings, or an Array of NetAddr::CIDR objects
|
655
|
-
#* options = Hash with the following keys:
|
656
|
-
# :Objectify -- if true, return NetAddr::CIDR objects
|
657
|
-
# :Short -- if true, return IPv6 addresses in short-hand notation
|
658
|
-
#
|
659
|
-
#===Returns:
|
660
|
-
#* Array of CIDR addresses or NetAddr::CIDR objects
|
661
|
-
#
|
662
|
-
def supernets(list,options=nil)
|
663
|
-
known_args = [:Objectify, :Short]
|
664
|
-
short = false
|
665
|
-
objectify = false
|
666
|
-
verbose = false
|
667
|
-
|
668
|
-
# validate list
|
669
|
-
raise ArgumentError, "Array expected for argument 'list' but #{list.class} provided." if (!list.kind_of?(Array) )
|
670
|
-
|
671
|
-
# validate options
|
672
|
-
if (options)
|
673
|
-
raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash) )
|
674
|
-
NetAddr.validate_args(options.keys,known_args)
|
675
|
-
|
676
|
-
if (options.has_key?(:Objectify) && options[:Objectify] == true)
|
677
|
-
objectify = true
|
678
|
-
end
|
679
|
-
|
680
|
-
if (options.has_key?(:Short) && options[:Short] == true)
|
681
|
-
short = true
|
682
|
-
end
|
683
|
-
end
|
684
|
-
|
685
|
-
# make sure all are valid types of the same IP version
|
686
|
-
v4_list = []
|
687
|
-
v6_list = []
|
688
|
-
list.each do |obj|
|
689
|
-
if (!obj.kind_of?(NetAddr::CIDR))
|
690
|
-
begin
|
691
|
-
obj = NetAddr::CIDR.create(obj)
|
692
|
-
rescue Exception => error
|
693
|
-
raise ArgumentError, "One of the provided CIDR addresses raised the following " +
|
694
|
-
"errors: #{error}"
|
695
|
-
end
|
696
|
-
end
|
697
|
-
|
698
|
-
if (obj.version == 4)
|
699
|
-
v4_list.push(obj)
|
700
|
-
else
|
701
|
-
v6_list.push(obj)
|
702
|
-
end
|
703
|
-
end
|
704
|
-
|
705
|
-
# do summary calcs
|
706
|
-
v4_summary = []
|
707
|
-
v6_summary = []
|
708
|
-
if (v4_list.length != 0)
|
709
|
-
v4_summary = NetAddr.cidr_supernets(v4_list)
|
710
|
-
end
|
711
|
-
|
712
|
-
if (v6_list.length != 0)
|
713
|
-
v6_summary = NetAddr.cidr_supernets(v6_list)
|
714
|
-
end
|
715
|
-
|
716
|
-
# decide what to return
|
717
|
-
summarized_list = []
|
718
|
-
if (!objectify)
|
719
|
-
summarized_list = []
|
720
|
-
if (v4_summary.length != 0)
|
721
|
-
v4_summary.each {|x| summarized_list.push(x.desc())}
|
722
|
-
end
|
723
|
-
|
724
|
-
if (v6_summary.length != 0)
|
725
|
-
v6_summary.each {|x| summarized_list.push(x.desc(:Short => short))}
|
726
|
-
end
|
727
|
-
|
728
|
-
else
|
729
|
-
summarized_list.concat(v4_summary) if (v4_summary.length != 0)
|
730
|
-
summarized_list.concat(v6_summary) if (v6_summary.length != 0)
|
731
|
-
end
|
732
|
-
|
733
|
-
return(summarized_list)
|
734
|
-
end
|
735
|
-
module_function :supernets
|
736
|
-
|
737
|
-
#===Synopsis
|
738
|
-
#Take an IPv6 address in short-hand format, and expand it into standard
|
739
|
-
#notation. The address should not contain a netmask.
|
740
|
-
#
|
741
|
-
# Example:
|
742
|
-
# NetAddr.unshorten('fec0::1') => "fec0:0000:0000:0000:0000:0000:0000:0001"
|
743
|
-
#
|
744
|
-
#===Arguments:
|
745
|
-
#* ip = CIDR address as a String
|
746
|
-
#
|
747
|
-
#===Returns:
|
748
|
-
#* String
|
749
|
-
#
|
750
|
-
def unshorten(ip)
|
751
|
-
|
752
|
-
# is this a string?
|
753
|
-
if (!ip.kind_of? String)
|
754
|
-
raise ArgumentError, "Expected String, but #{ip.class} provided."
|
755
|
-
end
|
756
|
-
|
757
|
-
validate_ip_str(ip, 6)
|
758
|
-
ipv4_mapped = true if (ip =~ /\./)
|
759
|
-
|
760
|
-
ip_int = ip_to_i(ip, :Version => 6)
|
761
|
-
if (!ipv4_mapped)
|
762
|
-
long = ip_int_to_str(ip_int, 6)
|
763
|
-
else
|
764
|
-
long = ip_int_to_str(ip_int, 6, true)
|
765
|
-
end
|
766
|
-
|
767
|
-
return(long)
|
768
|
-
end
|
769
|
-
module_function :unshorten
|
770
|
-
|
771
|
-
#===Synopsis
|
772
|
-
#Validate an EUI-48 or EUI-64 address. Raises NetAddr::ValidationError on validation failure.
|
773
|
-
#
|
774
|
-
# Example:
|
775
|
-
# NetAddr.validate_eui('01-00-5e-12-34-56') => true
|
776
|
-
#
|
777
|
-
# - Arguments
|
778
|
-
#* eui = EUI address as a String
|
779
|
-
#
|
780
|
-
#===Returns:
|
781
|
-
#* True
|
782
|
-
#
|
783
|
-
def validate_eui(eui)
|
784
|
-
if (eui.kind_of?(String))
|
785
|
-
# check for invalid characters
|
786
|
-
if (eui =~ /[^0-9a-fA-F\.\-\:]/)
|
787
|
-
raise ValidationError, "#{eui} is invalid (contains invalid characters)."
|
788
|
-
end
|
789
|
-
|
790
|
-
# split on formatting characters & check lengths
|
791
|
-
if (eui =~ /\-/)
|
792
|
-
fields = eui.split('-')
|
793
|
-
if (fields.length != 6 && fields.length != 8)
|
794
|
-
raise ValidationError, "#{eui} is invalid (unrecognized formatting)."
|
795
|
-
end
|
796
|
-
fields.each {|x| raise ValidationError, "#{eui} is invalid (missing characters)." if (x.length != 2)}
|
797
|
-
elsif (eui =~ /\:/)
|
798
|
-
fields = eui.split(':')
|
799
|
-
if (fields.length != 6 && fields.length != 8)
|
800
|
-
raise ValidationError, "#{eui} is invalid (unrecognized formatting)."
|
801
|
-
end
|
802
|
-
fields.each {|x| raise ValidationError, "#{eui} is invalid (missing characters)." if (x.length != 2)}
|
803
|
-
elsif (eui =~ /\./)
|
804
|
-
fields = eui.split('.')
|
805
|
-
if (fields.length != 3 && fields.length != 4)
|
806
|
-
raise ValidationError, "#{eui} is invalid (unrecognized formatting)."
|
807
|
-
end
|
808
|
-
fields.each {|x| raise ValidationError, "#{eui} is invalid (missing characters)." if (x.length != 4)}
|
809
|
-
else
|
810
|
-
raise ValidationError, "#{eui} is invalid (unrecognized formatting)."
|
811
|
-
end
|
812
|
-
|
813
|
-
else
|
814
|
-
raise ArgumentError, "EUI address should be a String, but was a#{eui.class}."
|
815
|
-
end
|
816
|
-
return(true)
|
817
|
-
end
|
818
|
-
module_function :validate_eui
|
819
|
-
|
820
|
-
#===Synopsis
|
821
|
-
#Validate an IP address. The address should not contain a netmask.
|
822
|
-
#This method will attempt to auto-detect the IP version
|
823
|
-
#if not provided, however a slight speed increase is realized if version is provided.
|
824
|
-
#Raises NetAddr::ValidationError on validation failure.
|
825
|
-
#
|
826
|
-
# Example:
|
827
|
-
# NetAddr.validate_ip_addr('192.168.1.1') => true
|
828
|
-
# NetAddr.validate_ip_addr('ffff::1', :Version => 6) => true
|
829
|
-
# NetAddr.validate_ip_addr('::192.168.1.1') => true
|
830
|
-
# NetAddr.validate_ip_addr(0xFFFFFF) => true
|
831
|
-
# NetAddr.validate_ip_addr(2**128-1) => true
|
832
|
-
# NetAddr.validate_ip_addr(2**32-1, :Version => 4) => true
|
833
|
-
#
|
834
|
-
#===Arguments
|
835
|
-
#* ip = IP address as a String or Integer
|
836
|
-
#* options = Hash with the following keys:
|
837
|
-
# :Version -- IP version - Integer (optional)
|
838
|
-
#
|
839
|
-
#===Returns:
|
840
|
-
#* True
|
841
|
-
#
|
842
|
-
def validate_ip_addr(ip, options=nil)
|
843
|
-
known_args = [:Version]
|
844
|
-
version = nil
|
845
|
-
|
846
|
-
# validate options
|
847
|
-
if (options)
|
848
|
-
raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
|
849
|
-
NetAddr.validate_args(options.keys,known_args)
|
850
|
-
|
851
|
-
if (options.has_key?(:Version))
|
852
|
-
version = options[:Version]
|
853
|
-
if (version != 4 && version != 6)
|
854
|
-
raise ArgumentError, ":Version should be 4 or 6, but was '#{version}'."
|
855
|
-
end
|
856
|
-
end
|
857
|
-
end
|
858
|
-
|
859
|
-
if ( ip.kind_of?(String) )
|
860
|
-
version = NetAddr.detect_ip_version(ip) if (!version)
|
861
|
-
NetAddr.validate_ip_str(ip,version)
|
862
|
-
|
863
|
-
elsif ( ip.kind_of?(Integer) )
|
864
|
-
NetAddr.validate_ip_int(ip,version)
|
865
|
-
|
866
|
-
else
|
867
|
-
raise ArgumentError, "Integer or String expected for argument 'ip' but " +
|
868
|
-
"#{ip.class} provided." if (!ip.kind_of?(String) && !ip.kind_of?(Integer))
|
869
|
-
end
|
870
|
-
|
871
|
-
return(true)
|
872
|
-
end
|
873
|
-
module_function :validate_ip_addr
|
874
|
-
|
875
|
-
#===Synopsis
|
876
|
-
#Validate IP Netmask. Version defaults to 4 if not specified.
|
877
|
-
#Raises NetAddr::ValidationError on validation failure.
|
878
|
-
#
|
879
|
-
# Examples:
|
880
|
-
# NetAddr.validate_ip_netmask('/32') => true
|
881
|
-
# NetAddr.validate_ip_netmask(32) => true
|
882
|
-
# NetAddr.validate_ip_netmask(0xffffffff, :Integer => true) => true
|
883
|
-
#
|
884
|
-
#===Arguments:
|
885
|
-
#* netmask = Netmask as a String or Integer
|
886
|
-
#* options = Hash with the following keys:
|
887
|
-
# :Integer -- if true, the provided Netmask is an Integer mask
|
888
|
-
# :Version -- IP version - Integer (optional)
|
889
|
-
#
|
890
|
-
#===Returns:
|
891
|
-
#* True
|
892
|
-
#
|
893
|
-
def validate_ip_netmask(netmask, options=nil)
|
894
|
-
known_args = [:Integer, :Version]
|
895
|
-
is_integer = false
|
896
|
-
version = 4
|
897
|
-
|
898
|
-
# validate options
|
899
|
-
if (options)
|
900
|
-
raise ArgumentError, "Hash expected for argument 'options' but #{options.class} provided." if (!options.kind_of?(Hash))
|
901
|
-
NetAddr.validate_args(options.keys,known_args)
|
902
|
-
|
903
|
-
if (options.has_key?(:Integer) && options[:Integer] == true)
|
904
|
-
is_integer = true
|
905
|
-
end
|
906
|
-
|
907
|
-
if (options.has_key?(:Version))
|
908
|
-
version = options[:Version]
|
909
|
-
if (version != 4 && version != 6)
|
910
|
-
raise ArgumentError, ":Version should be 4 or 6, but was '#{version}'."
|
911
|
-
end
|
912
|
-
end
|
913
|
-
end
|
914
|
-
|
915
|
-
# validate netmask
|
916
|
-
if (netmask.kind_of?(String))
|
917
|
-
validate_netmask_str(netmask,version)
|
918
|
-
elsif (netmask.kind_of?(Integer) )
|
919
|
-
validate_netmask_int(netmask,version,is_integer)
|
920
|
-
else
|
921
|
-
raise ArgumentError, "Integer or String expected for argument 'netmask' but " +
|
922
|
-
"#{netmask.class} provided." if (!netmask.kind_of?(String) && !netmask.kind_of?(Integer))
|
923
|
-
end
|
924
|
-
|
925
|
-
return(true)
|
926
|
-
end
|
927
|
-
module_function :validate_ip_netmask
|
928
|
-
|
929
|
-
#===Synopsis
|
930
|
-
#Convert a wildcard IP into a valid CIDR address. Wildcards must always be at
|
931
|
-
#the end of the address. Any data located after the first wildcard will be lost.
|
932
|
-
#Shorthand notation is prohibited for IPv6 addresses.
|
933
|
-
#IPv6 encoded IPv4 addresses are not currently supported.
|
934
|
-
#
|
935
|
-
# Examples:
|
936
|
-
# NetAddr.wildcard('192.168.*')
|
937
|
-
# NetAddr.wildcard('192.168.1.*')
|
938
|
-
# NetAddr.wildcard('fec0:*')
|
939
|
-
# NetAddr.wildcard('fec0:1:*')
|
940
|
-
#
|
941
|
-
#===Arguments:
|
942
|
-
#* ip = Wildcard IP address as a String
|
943
|
-
#
|
944
|
-
#===Returns:
|
945
|
-
#* CIDR object
|
946
|
-
#
|
947
|
-
def wildcard(ip)
|
948
|
-
version = 4
|
949
|
-
|
950
|
-
# do operations per version of address
|
951
|
-
if (ip =~ /\./ && ip !~ /:/)
|
952
|
-
octets = []
|
953
|
-
mask = 0
|
954
|
-
|
955
|
-
ip.split('.').each do |x|
|
956
|
-
if (x =~ /\*/)
|
957
|
-
break
|
958
|
-
end
|
959
|
-
octets.push(x)
|
960
|
-
end
|
961
|
-
|
962
|
-
octets.length.times do
|
963
|
-
mask = mask << 8
|
964
|
-
mask = mask | 0xff
|
965
|
-
end
|
966
|
-
|
967
|
-
until (octets.length == 4)
|
968
|
-
octets.push('0')
|
969
|
-
mask = mask << 8
|
970
|
-
end
|
971
|
-
ip = octets.join('.')
|
972
|
-
|
973
|
-
elsif (ip =~ /:/)
|
974
|
-
version = 6
|
975
|
-
fields = []
|
976
|
-
mask = 0
|
977
|
-
|
978
|
-
raise ArgumentError, "IPv6 encoded IPv4 addresses are unsupported." if (ip =~ /\./)
|
979
|
-
raise ArgumentError, "Shorthand IPv6 addresses are unsupported." if (ip =~ /::/)
|
980
|
-
|
981
|
-
ip.split(':').each do |x|
|
982
|
-
if (x =~ /\*/)
|
983
|
-
break
|
984
|
-
end
|
985
|
-
fields.push(x)
|
986
|
-
end
|
987
|
-
|
988
|
-
fields.length.times do
|
989
|
-
mask = mask << 16
|
990
|
-
mask = mask | 0xffff
|
991
|
-
end
|
992
|
-
|
993
|
-
until (fields.length == 8)
|
994
|
-
fields.push('0')
|
995
|
-
mask = mask << 16
|
996
|
-
end
|
997
|
-
ip = fields.join(':')
|
998
|
-
end
|
999
|
-
|
1000
|
-
# make & return cidr
|
1001
|
-
cidr = cidr_build( version, ip_str_to_int(ip,version), mask )
|
1002
|
-
|
1003
|
-
return(cidr)
|
1004
|
-
end
|
1005
|
-
module_function :wildcard
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
end # module NetAddr
|
1011
|
-
|
1012
|
-
__END__
|
1013
|
-
|