ipadmin 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +190 -151
- data/lib/cidr.rb +412 -210
- data/lib/eui.rb +92 -115
- data/lib/methods.rb +409 -438
- data/lib/tree.rb +609 -367
- data/tests/cidr_test.rb +56 -43
- data/tests/eui_test.rb +16 -14
- data/tests/methods_test.rb +191 -185
- data/tests/tree_test.rb +191 -231
- metadata +3 -3
data/lib/methods.rb
CHANGED
@@ -1,68 +1,63 @@
|
|
1
|
-
=begin rdoc
|
2
|
-
Copyright (c) 2006 Dustin Spinhirne -
|
3
|
-
Licensed under the same terms as Ruby, No Warranty is provided.
|
4
|
-
=end
|
5
|
-
|
6
|
-
|
7
|
-
|
8
1
|
module IPAdmin
|
9
2
|
|
10
3
|
#==============================================================================#
|
11
4
|
# compare()
|
12
5
|
#==============================================================================#
|
13
6
|
|
14
|
-
# Compare CIDR
|
7
|
+
# Compare (2) CIDR addresses, and determine if one
|
15
8
|
# is the supernet of the other.
|
16
9
|
#
|
17
10
|
# - Arguments:
|
18
|
-
# *
|
11
|
+
# * (2) CIDR addresses or IPAdmin::CIDR objects
|
19
12
|
#
|
20
13
|
# - Returns:
|
21
|
-
# * if one
|
22
|
-
# [supernet,subnet]
|
14
|
+
# * if one is a subnet of another, then return original array in order of [supernet,subnet]
|
23
15
|
# * if both are equal, return 1
|
24
16
|
# * if neither is a supernet of the other, return nil
|
25
17
|
#
|
26
|
-
#
|
18
|
+
# Examples:
|
27
19
|
# supernet,subnet = IPAdmin.compare(cidr1,cidr2)
|
20
|
+
# supernet,subnet = IPAdmin.compare('192.168.1.0/24','192.168.1.32/27')
|
28
21
|
#
|
29
22
|
|
30
|
-
def compare(
|
23
|
+
def compare(cidr1,cidr2)
|
31
24
|
ret_val = nil
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
25
|
+
orig1 = cidr1
|
26
|
+
orig2 = cidr2
|
27
|
+
|
28
|
+
# if args are not CIDR objects, then attempt to create
|
29
|
+
# cidr objects from them
|
30
|
+
if ( !cidr1.kind_of?(IPAdmin::CIDR) )
|
31
|
+
begin
|
32
|
+
cidr1 = IPAdmin::CIDR.new(:CIDR => cidr1)
|
33
|
+
rescue Exception => error
|
34
|
+
raise ArgumentError, "First provided argument raised the following " +
|
35
|
+
"errors: #{error}"
|
36
|
+
end
|
38
37
|
end
|
39
38
|
|
40
|
-
if ( !
|
41
|
-
|
42
|
-
|
43
|
-
|
39
|
+
if ( !cidr2.kind_of?(IPAdmin::CIDR))
|
40
|
+
begin
|
41
|
+
cidr2 = IPAdmin::CIDR.new(:CIDR => cidr2)
|
42
|
+
rescue Exception => error
|
43
|
+
raise ArgumentError, "Second provided argument raised the following " +
|
44
|
+
"errors: #{error}"
|
45
|
+
end
|
44
46
|
end
|
45
47
|
|
46
48
|
# make sure both are same version
|
47
|
-
if (
|
48
|
-
raise ArgumentError, "Provided
|
49
|
+
if (cidr1.version != cidr2.version )
|
50
|
+
raise ArgumentError, "Provided CIDR addresses are of different IP versions."
|
49
51
|
end
|
50
52
|
|
51
53
|
|
52
54
|
# get network/netmask of each
|
53
|
-
objects = [
|
55
|
+
objects = [cidr1,cidr2]
|
54
56
|
networks = []
|
55
57
|
netmasks = []
|
56
58
|
for obj in objects
|
57
|
-
|
58
|
-
|
59
|
-
netmasks.push(obj.packed_netmask)
|
60
|
-
|
61
|
-
elsif ( obj.kind_of?(IPAdmin::NetStruct) )
|
62
|
-
networks.push(obj.network)
|
63
|
-
netmasks.push(obj.netmask)
|
64
|
-
|
65
|
-
end
|
59
|
+
networks.push(obj.packed_network)
|
60
|
+
netmasks.push(obj.packed_netmask)
|
66
61
|
end
|
67
62
|
|
68
63
|
# return 1's if objects are equal otherwise
|
@@ -73,11 +68,11 @@ def compare(obj1,obj2)
|
|
73
68
|
ret_val = 1
|
74
69
|
elsif (netmasks[0] < netmasks[1])
|
75
70
|
if ( (netmasks[0] & networks[0]) == (netmasks[0] & networks[1]) )
|
76
|
-
ret_val = [
|
71
|
+
ret_val = [orig1,orig2]
|
77
72
|
end
|
78
73
|
elsif (netmasks[1] < netmasks[0])
|
79
74
|
if ( (netmasks[1] & networks[0]) == (netmasks[1] & networks[1]) )
|
80
|
-
ret_val = [
|
75
|
+
ret_val = [orig2,orig1]
|
81
76
|
end
|
82
77
|
end
|
83
78
|
|
@@ -90,69 +85,26 @@ module_function :compare
|
|
90
85
|
#======================================#
|
91
86
|
|
92
87
|
|
93
|
-
#==============================================================================#
|
94
|
-
# create_net_struct()
|
95
|
-
#==============================================================================#
|
96
|
-
|
97
|
-
# Create a NetStruct object from an CIDR or NetStruct object.
|
98
|
-
# This type of Struct is used internally for various tasks, and is not likely
|
99
|
-
# to be useful to anyone.
|
100
|
-
#
|
101
|
-
# - Arguments:
|
102
|
-
# * CIDR or NetStruct object
|
103
|
-
#
|
104
|
-
# - Returns:
|
105
|
-
# * NetStruct object
|
106
|
-
#
|
107
|
-
# Example:
|
108
|
-
# net_struct = IPAdmin.create_net_struct(object)
|
109
|
-
#
|
110
|
-
def create_net_struct(object)
|
111
|
-
|
112
|
-
if ( object.kind_of?(IPAdmin::CIDR) )
|
113
|
-
network = object.packed_ip
|
114
|
-
netmask = object.packed_netmask
|
115
|
-
|
116
|
-
elsif ( object.kind_of?(IPAdmin::NetStruct) )
|
117
|
-
network = object.network
|
118
|
-
netmask = object.netmask
|
119
|
-
else
|
120
|
-
raise ArgumentError, "Expected IPAdmin::CIDR or NetStruct "+
|
121
|
-
"object, but #{object.class} provided."
|
122
|
-
end
|
123
|
-
|
124
|
-
version = object.version
|
125
|
-
net_struct = NetStruct.new(network,netmask,version,object,[])
|
126
|
-
|
127
|
-
return(net_struct)
|
128
|
-
end
|
129
|
-
module_function :create_net_struct
|
130
|
-
|
131
|
-
#======================================#
|
132
|
-
#
|
133
|
-
#======================================#
|
134
|
-
|
135
|
-
|
136
88
|
#==============================================================================#
|
137
89
|
# merge()
|
138
90
|
#==============================================================================#
|
139
91
|
|
140
|
-
# Given a list of CIDR or
|
141
|
-
# merge (
|
142
|
-
# will only occur when the newly created
|
92
|
+
# Given a list of CIDR addresses or IPAdmin::CIDR objects of the same version,
|
93
|
+
# merge (summarize) them in the most efficient way possible. Summarization
|
94
|
+
# will only occur when the newly created supernets will not result in the
|
143
95
|
# 'creation' of additional space. For example the following blocks
|
144
|
-
# (192.168.0.0/24, 192.168.1.0/24, and 192.168.2.0/24) would
|
96
|
+
# (192.168.0.0/24, 192.168.1.0/24, and 192.168.2.0/24) would be summarized into
|
145
97
|
# 192.168.0.0/23 and 192.168.2.0/24 rather than into 192.168.0.0/22
|
146
98
|
#
|
147
99
|
# - Arguments:
|
148
|
-
# * Hash with
|
149
|
-
#
|
150
|
-
# - :
|
100
|
+
# * Array of CIDR addresses or IPAdmin::CIDR objects, or a Hash with
|
101
|
+
# the following fields:
|
102
|
+
# - :List -- Array of CIDR addresses or IPAdmin::CIDR objects
|
151
103
|
# - :Objectify -- if true, return IPAdmin::CIDR objects (optional)
|
152
104
|
# - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
|
153
105
|
#
|
154
106
|
# - Returns:
|
155
|
-
# * Array of CIDR or
|
107
|
+
# * Array of CIDR address Strings or IPAdmin::CIDR objects
|
156
108
|
#
|
157
109
|
# - Notes:
|
158
110
|
# * I have designed this with enough flexibility that you can pass in CIDR
|
@@ -160,211 +112,155 @@ module_function :create_net_struct
|
|
160
112
|
# 10.1.0.0/26, 10.1.0.64/26) and they will be merged properly (ie 192.168.1.0/25,
|
161
113
|
# and 10.1.0.0/25 would be returned).
|
162
114
|
#
|
163
|
-
#
|
164
|
-
# supernets = IPAdmin.merge(
|
115
|
+
# Examples:
|
116
|
+
# supernets = IPAdmin.merge(['192.168.1.0/27','192.168.1.32/27'])
|
117
|
+
# supernets = IPAdmin.merge(:List => ['192.168.1.0/27','192.168.1.32/27'], :Short => true)
|
165
118
|
#
|
166
119
|
def merge(options)
|
167
120
|
version = nil
|
121
|
+
all_f = nil
|
168
122
|
short = false
|
169
123
|
objectify = false
|
170
124
|
|
171
125
|
# validate options
|
172
|
-
if (
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
if (!options.has_key?(:List))
|
177
|
-
raise ArgumentError, "Missing argument: List."
|
178
|
-
end
|
126
|
+
if ( options.kind_of?(Hash) )
|
127
|
+
if (!options.has_key?(:List))
|
128
|
+
raise ArgumentError, "Missing argument: List."
|
129
|
+
end
|
179
130
|
|
180
|
-
|
181
|
-
|
182
|
-
|
131
|
+
if (options.has_key?(:Short) && options[:Short] == true)
|
132
|
+
short = true
|
133
|
+
end
|
183
134
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
list = options[:List]
|
189
|
-
ret_struct = 1 if (options.has_key?(:NetStruct))
|
135
|
+
if (options.has_key?(:Objectify) && options[:Objectify] == true)
|
136
|
+
objectify = true
|
137
|
+
end
|
190
138
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
139
|
+
# make sure :List is an array
|
140
|
+
if ( !options[:List].kind_of?(Array) )
|
141
|
+
raise ArgumentError, "Expected Array for option :List, " +
|
142
|
+
"but #{list.class} provided."
|
143
|
+
end
|
144
|
+
list = options[:List]
|
145
|
+
|
146
|
+
elsif ( options.kind_of?(Array) )
|
147
|
+
list = options
|
148
|
+
|
149
|
+
else
|
150
|
+
raise ArgumentError, "Array or Hash expected but #{options.class} provided."
|
195
151
|
end
|
196
|
-
|
152
|
+
|
197
153
|
# make sure all are valid types of the same IP version
|
154
|
+
supernet_list = []
|
198
155
|
list.each do |obj|
|
199
|
-
if (!obj.kind_of?(IPAdmin::CIDR)
|
200
|
-
|
201
|
-
|
156
|
+
if (!obj.kind_of?(IPAdmin::CIDR))
|
157
|
+
begin
|
158
|
+
obj = IPAdmin::CIDR.new(:CIDR => obj)
|
159
|
+
rescue Exception => error
|
160
|
+
raise ArgumentError, "An array element of :List raised the following " +
|
161
|
+
"errors: #{error}"
|
162
|
+
end
|
202
163
|
end
|
203
164
|
|
204
165
|
version = obj.version if (!version)
|
166
|
+
all_f = obj.all_f if (!all_f)
|
205
167
|
if (!obj.version == version)
|
206
168
|
raise "Provided objects must be of the same IP version."
|
207
169
|
end
|
170
|
+
supernet_list.push(obj)
|
208
171
|
end
|
209
172
|
|
210
|
-
#
|
211
|
-
|
212
|
-
all_f = 2**32 - 1
|
213
|
-
else
|
214
|
-
all_f = 2**128 - 1
|
215
|
-
end
|
216
|
-
|
217
|
-
# make sure that our list is in order, and contains no duplicates
|
218
|
-
list = IPAdmin.sort(list)
|
219
|
-
index = 0
|
220
|
-
(list.length).times do
|
221
|
-
if ((index > 0)&&(IPAdmin.compare(list[index],list[index-1]) == 1))
|
222
|
-
list.delete_at(index)
|
223
|
-
else
|
224
|
-
index += 1
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
# create supernet_list from list
|
229
|
-
supernet_list = []
|
230
|
-
list.each do |obj|
|
231
|
-
if (obj.kind_of?(IPAdmin::CIDR))
|
232
|
-
supernet_list.push(IPAdmin.create_net_struct(obj))
|
233
|
-
|
234
|
-
elsif ( obj.kind_of?(IPAdmin::NetStruct) )
|
235
|
-
if (obj.subnets && obj.subnets.length > 0)
|
236
|
-
# get all child subnets of this branch entry
|
237
|
-
children = merge(:List => obj.subnets, :NetStruct => 1)
|
238
|
-
|
239
|
-
# if any child subnets are equal to the parent subnet
|
240
|
-
# then copy the grandchild subnets and delete the child
|
241
|
-
children.each do |child|
|
242
|
-
if ( (obj.network == child.network) &&
|
243
|
-
(obj.netmask == child.netmask) )
|
244
|
-
if (child.subnets && child.subnets.length > 0)
|
245
|
-
grandchildren = child.subnets
|
246
|
-
children.concat(grandchildren)
|
247
|
-
end
|
248
|
-
children.delete(child)
|
249
|
-
children = IPAdmin.sort(children)
|
250
|
-
break
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
obj.subnets.clear
|
255
|
-
obj.subnets.concat(children)
|
256
|
-
end
|
257
|
-
|
258
|
-
supernet_list.push(obj)
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
# merge subnets of this new branch by removing them from 'supernet_list',
|
263
|
-
# and categorizing them into hash of arrays (key=netmask)
|
173
|
+
# merge subnets by removing them from 'supernet_list',
|
174
|
+
# and categorizing them into hash of arrays ({packed_netmask => [packed_network,packed_network,etc...] )
|
264
175
|
# within each categorization we merge contiguous subnets
|
265
176
|
# and then remove them from that category & put them back into
|
266
|
-
# 'supernet_list'. we do this until
|
177
|
+
# 'supernet_list'. we do this until supernet_list stops getting any shorter
|
267
178
|
categories = {}
|
268
179
|
supernet_list_length = 0
|
269
180
|
until (supernet_list_length == supernet_list.length)
|
270
181
|
supernet_list_length = supernet_list.length
|
271
182
|
|
272
183
|
# categorize
|
273
|
-
supernet_list.each do |
|
274
|
-
netmask =
|
184
|
+
supernet_list.each do |cidr|
|
185
|
+
netmask = cidr.packed_netmask
|
186
|
+
network = cidr.packed_network
|
275
187
|
if (categories.has_key?(netmask) )
|
276
|
-
|
188
|
+
categories[netmask].push(network)
|
277
189
|
else
|
278
|
-
categories[netmask] = [
|
190
|
+
categories[netmask] = [network]
|
279
191
|
end
|
280
192
|
end
|
281
193
|
supernet_list.clear
|
282
194
|
|
283
|
-
categories.
|
284
|
-
|
195
|
+
ordered_cats = categories.keys.sort
|
196
|
+
ordered_cats.each do |netmask|
|
197
|
+
nets = categories[netmask].sort
|
285
198
|
bitstep = (all_f + 1) - netmask
|
286
|
-
|
287
|
-
|
288
|
-
|
199
|
+
|
200
|
+
until (nets.length == 0)
|
201
|
+
# take the first network & create its supernet. this
|
202
|
+
# supernet will have x number of subnets, so we'll look
|
203
|
+
# & see if we have those subnets. if so, keep supernet & delete subnets.
|
289
204
|
to_merge = []
|
290
205
|
multiplier = 1
|
291
|
-
|
206
|
+
network1 = nets[0]
|
292
207
|
num_required = 2**multiplier
|
293
208
|
supermask = (netmask << multiplier) & all_f
|
294
|
-
supernet = supermask &
|
295
|
-
if (
|
296
|
-
#
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
entries.each do |entry|
|
302
|
-
if ( (entry.network == expected) && (first.network == supernet) )
|
303
|
-
to_merge.push(entry)
|
209
|
+
supernet = supermask & network1
|
210
|
+
if (network1 == supernet)
|
211
|
+
# we have the first half of the new supernet
|
212
|
+
expected = network1
|
213
|
+
nets.each do |network|
|
214
|
+
if (network == expected)
|
215
|
+
to_merge.push(network)
|
304
216
|
expected = expected + bitstep
|
305
|
-
if ( (to_merge.length == num_required) &&
|
306
|
-
|
217
|
+
if ( (to_merge.length == num_required) && (nets.length > num_required) )
|
218
|
+
# we have all of our subnets for this round, but still have
|
219
|
+
# more to look at
|
307
220
|
multiplier += 1
|
308
221
|
num_required = 2**multiplier
|
309
222
|
supermask = (netmask << multiplier) & all_f
|
310
|
-
supernet = supermask &
|
223
|
+
supernet = supermask & network1
|
311
224
|
end
|
312
225
|
else
|
313
|
-
# if entry is a duplicate, then kill it
|
314
|
-
if (IPAdmin.compare(entry,to_merge.last) == 1)
|
315
|
-
entries.delete(entry)
|
316
|
-
end
|
317
226
|
break
|
318
227
|
end
|
319
228
|
end
|
320
229
|
else
|
321
|
-
|
230
|
+
# we have the second half of the new supernet only
|
231
|
+
to_merge.push(network1)
|
322
232
|
end
|
323
233
|
|
324
|
-
|
325
|
-
# create our new supernet
|
234
|
+
|
326
235
|
if (to_merge.length != num_required)
|
236
|
+
# we dont have all of our subnets, so backstep 1 bit
|
327
237
|
multiplier -= 1
|
328
238
|
supermask = (netmask << multiplier) & all_f
|
329
|
-
supernet = supermask &
|
239
|
+
supernet = supermask & network1
|
330
240
|
end
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
entries.delete(to_kill)
|
340
|
-
end
|
341
|
-
supernet_list.push(net_struct)
|
241
|
+
|
242
|
+
# save new supernet
|
243
|
+
supernet_list.push(IPAdmin::CIDR.new(:PackedIP => supernet,
|
244
|
+
:PackedNetmask => supermask,
|
245
|
+
:Version => version))
|
246
|
+
|
247
|
+
# delete the subnets of the new supernet
|
248
|
+
(2**multiplier).times {nets.delete(to_merge.shift)}
|
342
249
|
end
|
343
250
|
end
|
344
251
|
categories.clear
|
345
252
|
supernet_list = IPAdmin.sort(supernet_list)
|
346
253
|
end
|
347
254
|
|
348
|
-
#
|
349
|
-
if (!
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
network = IPAdmin.unpack_ip_addr(:Integer => entry.network, :Version => version)
|
354
|
-
network = IPAdmin.shorten(network) if (short && version == 6)
|
355
|
-
netmask = IPAdmin.unpack_ip_netmask(:Integer => entry.netmask, :Version => version)
|
356
|
-
supernets.push("#{network}/#{netmask}")
|
357
|
-
else
|
358
|
-
supernets.push(IPAdmin::CIDR.new(:PackedIP => entry.network,
|
359
|
-
:PackedNetmask => entry.netmask,
|
360
|
-
:Version => version))
|
361
|
-
end
|
362
|
-
end
|
255
|
+
# decide what to return
|
256
|
+
if (!objectify)
|
257
|
+
supernets = []
|
258
|
+
supernet_list.each {|entry| supernets.push(entry.desc(:Short => short))}
|
259
|
+
return(supernets)
|
363
260
|
else
|
364
|
-
|
261
|
+
return(supernet_list)
|
365
262
|
end
|
366
263
|
|
367
|
-
return(supernets)
|
368
264
|
end
|
369
265
|
module_function :merge
|
370
266
|
|
@@ -378,10 +274,10 @@ module_function :merge
|
|
378
274
|
#==============================================================================#
|
379
275
|
|
380
276
|
# Given the number of IP addresses required in a subnet, return the minimum
|
381
|
-
# netmask required for that subnet.
|
277
|
+
# netmask (in bits) required for that subnet.
|
382
278
|
#
|
383
279
|
# - Arguments:
|
384
|
-
# * Hash with the following fields:
|
280
|
+
# * Integer or Hash with the following fields:
|
385
281
|
# - :IPCount -- the number of IP addresses required - Integer
|
386
282
|
# - :Version -- IP version - Integer(optional)
|
387
283
|
#
|
@@ -391,23 +287,26 @@ module_function :merge
|
|
391
287
|
# - Notes:
|
392
288
|
# * Version is assumed to be 4 unless specified otherwise.
|
393
289
|
#
|
394
|
-
#
|
395
|
-
# netmask = IPAdmin.minumum_size(
|
290
|
+
# Examples:
|
291
|
+
# netmask = IPAdmin.minumum_size(14)
|
292
|
+
# netmask = IPAdmin.minumum_size(:IPCount => 65536, :Version => 6)
|
396
293
|
#
|
397
294
|
def minimum_size(options)
|
398
295
|
version = 4
|
399
296
|
|
400
|
-
if (
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
raise ArgumentError, "Missing argument: List."
|
406
|
-
end
|
407
|
-
ipcount = options[:IPCount]
|
297
|
+
if ( options.kind_of?(Hash) )
|
298
|
+
if ( !options.has_key?(:IPCount) )
|
299
|
+
raise ArgumentError, "Missing argument: List."
|
300
|
+
end
|
301
|
+
ipcount = options[:IPCount]
|
408
302
|
|
409
|
-
|
410
|
-
|
303
|
+
if (options.has_key?(:Version))
|
304
|
+
version = options[:Version]
|
305
|
+
end
|
306
|
+
elsif ( options.kind_of?(Integer) )
|
307
|
+
ipcount = options
|
308
|
+
else
|
309
|
+
raise ArgumentError, "Integer or Hash expected but #{options.class} provided."
|
411
310
|
end
|
412
311
|
|
413
312
|
if (version == 4)
|
@@ -442,11 +341,10 @@ module_function :minimum_size
|
|
442
341
|
# pack_ip_addr()
|
443
342
|
#==============================================================================#
|
444
343
|
|
445
|
-
# Convert IP addresses into an integer.
|
446
|
-
# validation is performed.
|
344
|
+
# Convert IP addresses into an integer.
|
447
345
|
#
|
448
346
|
# - Arguments:
|
449
|
-
# * Hash with the following fields:
|
347
|
+
# * IP address as a String, or a Hash with the following fields:
|
450
348
|
# - :IP -- IP address - String
|
451
349
|
# - :Version -- IP version - Integer
|
452
350
|
#
|
@@ -456,32 +354,39 @@ module_function :minimum_size
|
|
456
354
|
# - Notes:
|
457
355
|
# * Will attempt to auto-detect IP version if not provided
|
458
356
|
#
|
459
|
-
#
|
460
|
-
# pack_ip_addr(
|
461
|
-
# pack_ip_addr(IP => 'ffff::1')
|
462
|
-
# pack_ip_addr(
|
357
|
+
# Examples:
|
358
|
+
# pack_ip_addr('192.168.1.1')
|
359
|
+
# pack_ip_addr(IP => 'ffff::1', :Version => 6)
|
360
|
+
# pack_ip_addr(::192.168.1.1')
|
463
361
|
#
|
464
362
|
def pack_ip_addr(options)
|
363
|
+
to_validate = {}
|
465
364
|
|
466
|
-
if (
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
if (!options.has_key?(:IP))
|
471
|
-
raise ArgumentError, "Missing argument: IP."
|
472
|
-
end
|
473
|
-
ip = options[:IP]
|
474
|
-
|
475
|
-
if (options.has_key?(:Version))
|
476
|
-
version = options[:Version]
|
477
|
-
if (version != 4 && version != 6)
|
478
|
-
raise ArgumentError, ":Version should be 4 or 6, but was '#{version}'."
|
365
|
+
if (options.kind_of?(Hash))
|
366
|
+
if (!options.has_key?(:IP))
|
367
|
+
raise ArgumentError, "Missing argument: IP."
|
479
368
|
end
|
480
|
-
|
369
|
+
ip = options[:IP]
|
370
|
+
|
371
|
+
if (options.has_key?(:Version))
|
372
|
+
version = options[:Version]
|
373
|
+
to_validate[:Version] = version
|
374
|
+
if (version != 4 && version != 6)
|
375
|
+
raise ArgumentError, ":Version should be 4 or 6, but was '#{version}'."
|
376
|
+
end
|
377
|
+
end
|
378
|
+
elsif
|
379
|
+
ip = options
|
380
|
+
else
|
381
|
+
raise ArgumentError, "String or Hash expected, but #{options.class} provided."
|
382
|
+
end
|
383
|
+
to_validate[:IP] = ip
|
481
384
|
|
482
|
-
|
483
385
|
if ( ip.kind_of?(String) )
|
484
386
|
|
387
|
+
# validate
|
388
|
+
IPAdmin.validate_ip_addr(to_validate)
|
389
|
+
|
485
390
|
# determine version if not provided
|
486
391
|
if (!version)
|
487
392
|
if ( ip =~ /\./ && ip !~ /:/ )
|
@@ -550,7 +455,7 @@ def pack_ip_addr(options)
|
|
550
455
|
end
|
551
456
|
|
552
457
|
else
|
553
|
-
raise ArgumentError, "
|
458
|
+
raise ArgumentError, "IP address should be a String, but is a #{ip.class}."
|
554
459
|
end
|
555
460
|
|
556
461
|
return(packed_ip)
|
@@ -566,12 +471,12 @@ module_function :pack_ip_addr
|
|
566
471
|
# pack_ip_netmask()
|
567
472
|
#==============================================================================#
|
568
473
|
|
569
|
-
# Convert IP netmask into an integer.
|
570
|
-
#
|
571
|
-
#
|
474
|
+
# Convert IP netmask into an integer.Netmask may be in either CIDR (/yy) or
|
475
|
+
# extended (y.y.y.y) format. CIDR formatted netmasks may either
|
476
|
+
# be a String or an Integer.
|
572
477
|
#
|
573
478
|
# - Arguments
|
574
|
-
# * Hash with the following fields:
|
479
|
+
# * Netmask as a String, or a Integer, or a Hash with the following fields:
|
575
480
|
# - :Netmask -- Netmask - String or Integer
|
576
481
|
# - :Version -- IP version - Integer (optional)
|
577
482
|
#
|
@@ -581,38 +486,45 @@ module_function :pack_ip_addr
|
|
581
486
|
# - Notes:
|
582
487
|
# * Version defaults to 4
|
583
488
|
#
|
584
|
-
#
|
585
|
-
# packed = IPAdmin.pack_ip_netmask(
|
586
|
-
# packed = IPAdmin.pack_ip_netmask(
|
587
|
-
# packed = IPAdmin.pack_ip_netmask(
|
588
|
-
# packed = IPAdmin.pack_ip_netmask(
|
489
|
+
# Examples:
|
490
|
+
# packed = IPAdmin.pack_ip_netmask('255.255.255.0')
|
491
|
+
# packed = IPAdmin.pack_ip_netmask('24')
|
492
|
+
# packed = IPAdmin.pack_ip_netmask(24)
|
493
|
+
# packed = IPAdmin.pack_ip_netmask('/24')
|
589
494
|
# packed = IPAdmin.pack_ip_netmask(Netmask => '64', :Version => 6)
|
590
495
|
#
|
591
496
|
def pack_ip_netmask(options)
|
592
|
-
|
593
|
-
raise ArgumentError, "Expected Hash, but #{options.class} provided."
|
594
|
-
end
|
497
|
+
all_f = 2**32-1
|
595
498
|
|
596
|
-
if (
|
597
|
-
|
598
|
-
|
599
|
-
|
499
|
+
if (options.kind_of?(Hash))
|
500
|
+
if (!options.has_key?(:Netmask))
|
501
|
+
raise ArgumentError, "Missing argument: Netmask."
|
502
|
+
end
|
503
|
+
netmask = options[:Netmask]
|
504
|
+
to_validate = {:Netmask => netmask}
|
600
505
|
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
506
|
+
if (options.has_key?(:Version))
|
507
|
+
version = options[:Version]
|
508
|
+
if (version != 4 && version != 6)
|
509
|
+
raise ArgumentError, ":Version should be 4 or 6, but was '#{version}'."
|
510
|
+
elsif (version == 6)
|
511
|
+
all_f = 2**128-1
|
512
|
+
else
|
513
|
+
all_f = 2**32-1
|
514
|
+
end
|
515
|
+
to_validate[:Version] = version
|
609
516
|
end
|
517
|
+
|
518
|
+
elsif (options.kind_of?(String) || options.kind_of?(Integer))
|
519
|
+
netmask = options
|
520
|
+
to_validate = {:Netmask => netmask}
|
610
521
|
else
|
611
|
-
|
522
|
+
raise ArgumentError, "String, Integer, or Hash expected, but #{options.class} provided."
|
612
523
|
end
|
613
524
|
|
614
|
-
|
615
525
|
if (netmask.kind_of?(String))
|
526
|
+
IPAdmin.validate_ip_netmask(to_validate)
|
527
|
+
|
616
528
|
if(netmask =~ /\./)
|
617
529
|
packed_netmask = IPAdmin.pack_ip_addr(:IP => netmask)
|
618
530
|
|
@@ -625,11 +537,14 @@ def pack_ip_netmask(options)
|
|
625
537
|
netmask = netmask.to_i
|
626
538
|
packed_netmask = all_f ^ (all_f >> netmask)
|
627
539
|
end
|
540
|
+
|
628
541
|
elsif (netmask.kind_of?(Integer))
|
542
|
+
to_validate[:Packed] = true
|
543
|
+
IPAdmin.validate_ip_netmask(to_validate)
|
629
544
|
packed_netmask = all_f ^ (all_f >> netmask)
|
630
545
|
|
631
546
|
else
|
632
|
-
raise ArgumentError, "
|
547
|
+
raise ArgumentError, "Netmask should be a String or Integer, but is a #{netmask.class}."
|
633
548
|
|
634
549
|
end
|
635
550
|
|
@@ -646,36 +561,41 @@ module_function :pack_ip_netmask
|
|
646
561
|
# range()
|
647
562
|
#==============================================================================#
|
648
563
|
|
649
|
-
# Given two IPAdmin::CIDR objects of the same version,
|
650
|
-
# addresses between them
|
564
|
+
# Given two CIDR addresses or IPAdmin::CIDR objects of the same version,
|
565
|
+
# return all IP addresses between them.
|
651
566
|
#
|
652
567
|
# - Arguments:
|
653
|
-
# *
|
568
|
+
# * Array of (2)CIDR addresses or IPAdmin::CIDR objects, or a Hash
|
569
|
+
# with the following fields:
|
654
570
|
# - :Bitstep -- enumerate in X sized steps - Integer (optional)
|
655
|
-
# - :Boundaries -- array of (2) CIDR objects
|
571
|
+
# - :Boundaries -- array of (2) CIDR addresses or IPAdmin::CIDR objects
|
572
|
+
# - :Inclusive -- if true, include boundaries in returned data
|
656
573
|
# - :Limit -- limit returned list to X number of items - Integer (optional)
|
657
574
|
# - :Objectify -- if true, return CIDR objects (optional)
|
658
575
|
# - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
|
659
576
|
#
|
660
577
|
# - Returns:
|
661
|
-
# * Array of Strings or CIDR objects
|
578
|
+
# * Array of CIDR address Strings or IPAdmin::CIDR objects
|
662
579
|
#
|
663
580
|
# - Notes:
|
664
581
|
# * IPAdmin.range will use the original IP address passed during the initialization
|
665
|
-
# of the CIDR objects
|
582
|
+
# of the IPAdmin::CIDR objects, or the base address of any CIDR addresses passed.
|
583
|
+
# * The default behavior is to be non-inclusive (dont include boundaries as part of returned data)
|
666
584
|
#
|
667
|
-
#
|
668
|
-
# list = IPAdmin.range(:Boundaries => [cidr1,cidr2])
|
585
|
+
# Examples:
|
586
|
+
# list = IPAdmin.range(:Boundaries => [cidr1,cidr2], :Limit => 10)
|
587
|
+
# list = IPAdmin.range(['192.168.1.0','192.168.1.10']
|
669
588
|
#
|
670
589
|
def range(options)
|
671
590
|
list = []
|
672
591
|
bitstep = 1
|
673
592
|
objectify = false
|
674
593
|
short = false
|
594
|
+
inclusive = false
|
675
595
|
limit = nil
|
676
596
|
|
677
597
|
# check options
|
678
|
-
if (options)
|
598
|
+
if (options.kind_of?(Hash))
|
679
599
|
if ( !options.has_key?(:Boundaries) )
|
680
600
|
raise ArgumentError, "Missing argument: Boundaries."
|
681
601
|
end
|
@@ -698,16 +618,39 @@ def range(options)
|
|
698
618
|
if( options.has_key?(:Short) && options[:Short] == true )
|
699
619
|
short = true
|
700
620
|
end
|
621
|
+
|
622
|
+
if( options.has_key?(:Inclusive) && options[:Inclusive] == true )
|
623
|
+
inclusive = true
|
624
|
+
end
|
701
625
|
|
702
626
|
if( options.has_key?(:Limit) )
|
703
627
|
limit = options[:Limit]
|
704
628
|
end
|
629
|
+
|
630
|
+
elsif(options.kind_of?(Array))
|
631
|
+
(cidr1,cidr2) = options
|
632
|
+
else
|
633
|
+
raise ArgumentError, "Array or Hash expected but #{options.class} provided."
|
634
|
+
end
|
635
|
+
|
636
|
+
# if cidr1/cidr2 are not CIDR objects, then attempt to create
|
637
|
+
# cidr objects from them
|
638
|
+
if ( !cidr1.kind_of?(IPAdmin::CIDR) )
|
639
|
+
begin
|
640
|
+
cidr1 = IPAdmin::CIDR.new(:CIDR => cidr1)
|
641
|
+
rescue Exception => error
|
642
|
+
raise ArgumentError, "First argument of :Boundaries raised the following " +
|
643
|
+
"errors: #{error}"
|
644
|
+
end
|
705
645
|
end
|
706
646
|
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
647
|
+
if ( !cidr2.kind_of?(IPAdmin::CIDR))
|
648
|
+
begin
|
649
|
+
cidr2 = IPAdmin::CIDR.new(:CIDR => cidr2)
|
650
|
+
rescue Exception => error
|
651
|
+
raise ArgumentError, "Second argument of :Boundaries raised the following " +
|
652
|
+
"errors: #{error}"
|
653
|
+
end
|
711
654
|
end
|
712
655
|
|
713
656
|
# check version, store & sort
|
@@ -720,8 +663,15 @@ def range(options)
|
|
720
663
|
end
|
721
664
|
|
722
665
|
# dump our range
|
723
|
-
|
724
|
-
|
666
|
+
if (!inclusive)
|
667
|
+
my_ip = boundaries[0] + 1
|
668
|
+
end_ip = boundaries[1]
|
669
|
+
else
|
670
|
+
my_ip = boundaries[0]
|
671
|
+
end_ip = boundaries[1] + 1
|
672
|
+
end
|
673
|
+
|
674
|
+
until (my_ip >= end_ip)
|
725
675
|
if (!objectify)
|
726
676
|
my_ip_s = IPAdmin.unpack_ip_addr(:Integer => my_ip, :Version => version)
|
727
677
|
my_ips = IPAdmin.shorten(my_ips) if (short && version == 6)
|
@@ -754,13 +704,13 @@ module_function :range
|
|
754
704
|
# The address should not contain a netmask.
|
755
705
|
#
|
756
706
|
# - Arguments:
|
757
|
-
# * String
|
707
|
+
# * IP address as a String
|
758
708
|
#
|
759
709
|
# - Returns:
|
760
710
|
# * String
|
761
711
|
#
|
762
|
-
#
|
763
|
-
# short = IPAdmin.shorten('fec0:0000:0000:0000:0000:0000:0000:0001')
|
712
|
+
# Examples:
|
713
|
+
# short = IPAdmin.shorten('fec0:0000:0000:0000:0000:0000:0000:0001')
|
764
714
|
#
|
765
715
|
def shorten(addr)
|
766
716
|
|
@@ -846,21 +796,22 @@ module_function :shorten
|
|
846
796
|
# sort()
|
847
797
|
#==============================================================================#
|
848
798
|
|
849
|
-
# Given a list of
|
799
|
+
# Given a list of CIDR addresses or IPAdmin::CIDR objects,
|
850
800
|
# sort them from lowest to highest by Network/Netmask.
|
851
801
|
#
|
852
802
|
# - Arguments:
|
853
|
-
# * Array of CIDR or
|
803
|
+
# * Array of CIDR addresses or IPAdmin::CIDR objects
|
854
804
|
#
|
855
805
|
# - Returns:
|
856
|
-
# * Array
|
806
|
+
# * Array of CIDR address Strings or IPAdmin::CIDR objects
|
857
807
|
#
|
858
808
|
# - Notes:
|
859
809
|
# * IPAdmin.sort will use the original IP address passed during the initialization
|
860
|
-
# of
|
810
|
+
# of any IPAdmin::CIDR objects, or the base address of any CIDR addresses passed.
|
861
811
|
#
|
862
|
-
#
|
863
|
-
# sorted = IPAdmin.sort(
|
812
|
+
# Examples:
|
813
|
+
# sorted = IPAdmin.sort([cidr1,cidr2])
|
814
|
+
# sorted = IPAdmin.sort(['192.168.1.32/27','192.168.1.0/27'])
|
864
815
|
#
|
865
816
|
def sort(list)
|
866
817
|
|
@@ -872,33 +823,35 @@ def sort(list)
|
|
872
823
|
|
873
824
|
# make sure all are valid types of the same IP version
|
874
825
|
version = nil
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
826
|
+
cidr_hash = {}
|
827
|
+
list.each do |cidr|
|
828
|
+
if (!cidr.kind_of?(IPAdmin::CIDR))
|
829
|
+
begin
|
830
|
+
new_cidr = IPAdmin::CIDR.new(cidr)
|
831
|
+
rescue Exception => error
|
832
|
+
raise ArgumentError, "An element of the provided Array " +
|
833
|
+
"raised the following errors: #{error}"
|
834
|
+
end
|
835
|
+
else
|
836
|
+
new_cidr = cidr
|
879
837
|
end
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
838
|
+
cidr_hash[new_cidr] = cidr
|
839
|
+
|
840
|
+
version = new_cidr.version if (!version)
|
841
|
+
unless (new_cidr.version == version)
|
842
|
+
raise "Provided CIDR addresses must all be of the same IP version."
|
884
843
|
end
|
885
844
|
end
|
886
845
|
|
887
|
-
# create unsorted_list from list
|
888
|
-
unsorted_list = []
|
889
|
-
list.each do |obj|
|
890
|
-
unsorted_list.push(IPAdmin.create_net_struct(obj))
|
891
|
-
end
|
892
|
-
|
893
846
|
# sort by network. if networks are equal, sort by netmask.
|
894
847
|
sorted_list = []
|
895
|
-
|
848
|
+
cidr_hash.each_key do |entry|
|
896
849
|
index = 0
|
897
850
|
sorted_list.each do
|
898
|
-
if(entry.
|
851
|
+
if(entry.packed_network < (sorted_list[index]).packed_network)
|
899
852
|
break
|
900
|
-
elsif (entry.
|
901
|
-
if (entry.
|
853
|
+
elsif (entry.packed_network == (sorted_list[index]).packed_network)
|
854
|
+
if (entry.packed_netmask < (sorted_list[index]).packed_netmask)
|
902
855
|
break
|
903
856
|
end
|
904
857
|
end
|
@@ -906,15 +859,12 @@ def sort(list)
|
|
906
859
|
end
|
907
860
|
sorted_list.insert(index, entry)
|
908
861
|
end
|
862
|
+
|
863
|
+
# return original values passed
|
864
|
+
ret_list = []
|
865
|
+
sorted_list.each {|x| ret_list.push(cidr_hash[x])}
|
909
866
|
|
910
|
-
|
911
|
-
index = 0
|
912
|
-
sorted_list.length.times do
|
913
|
-
sorted_list[index] = (sorted_list[index]).object
|
914
|
-
index += 1
|
915
|
-
end
|
916
|
-
|
917
|
-
return(sorted_list)
|
867
|
+
return(ret_list)
|
918
868
|
end
|
919
869
|
module_function :sort
|
920
870
|
|
@@ -927,11 +877,10 @@ module_function :sort
|
|
927
877
|
# unpack_ip_addr()
|
928
878
|
#==============================================================================#
|
929
879
|
|
930
|
-
# Unack a packed IP address back into a printable string.
|
931
|
-
# validation is performed.
|
880
|
+
# Unack a packed IP address back into a printable string.
|
932
881
|
#
|
933
882
|
# - Arguments:
|
934
|
-
# * Hash with the following fields:
|
883
|
+
# * Integer or a Hash with the following fields:
|
935
884
|
# - :Integer -- Integer representaion of an IP address
|
936
885
|
# - :Version -- IP version - Integer (optional)
|
937
886
|
# - :IPv4Mapped -- if true, unpack IPv6 as an IPv4 mapped address (optional)
|
@@ -942,35 +891,44 @@ module_function :sort
|
|
942
891
|
# - Notes:
|
943
892
|
# * IP version will attempt to be auto-detected if not provided
|
944
893
|
#
|
945
|
-
#
|
894
|
+
# Examples:
|
895
|
+
# unpacked = IPAdmin.unpack_ip_addr(3232235906)
|
946
896
|
# unpacked = IPAdmin.unpack_ip_addr(:Integer => packed)
|
947
897
|
#
|
948
898
|
def unpack_ip_addr(options)
|
949
899
|
ipv4_mapped = false
|
900
|
+
to_validate = {}
|
950
901
|
|
951
|
-
if (
|
952
|
-
|
953
|
-
|
902
|
+
if (options.kind_of?(Hash))
|
903
|
+
if (!options.has_key?(:Integer))
|
904
|
+
raise ArgumentError, "Missing argument: Integer."
|
905
|
+
end
|
906
|
+
packed_ip = options[:Integer]
|
907
|
+
|
908
|
+
if (options.has_key?(:Version))
|
909
|
+
version = options[:Version]
|
910
|
+
to_validate[:Version] = version
|
911
|
+
if (version != 4 && version != 6)
|
912
|
+
raise ArgumentError, ":Version should be 4 or 6, but was '#{version}'."
|
913
|
+
end
|
914
|
+
end
|
954
915
|
|
955
|
-
|
956
|
-
|
916
|
+
if (options.has_key?(:IPv4Mapped) && options[:IPv4Mapped] == true)
|
917
|
+
ipv4_mapped = true
|
918
|
+
end
|
919
|
+
elsif (options.kind_of?(Integer))
|
920
|
+
packed_ip = options
|
921
|
+
else
|
922
|
+
raise ArgumentError, "Integer or Hash expected, but #{options.class} provided."
|
957
923
|
end
|
958
|
-
packed_ip = options[:Integer]
|
959
924
|
|
960
925
|
if (!packed_ip.kind_of?(Integer))
|
961
|
-
raise ArgumentError, "
|
962
|
-
end
|
963
|
-
|
964
|
-
if (options.has_key?(:Version))
|
965
|
-
version = options[:Version]
|
966
|
-
if (version != 4 && version != 6)
|
967
|
-
raise ArgumentError, ":Version should be 4 or 6, but was '#{version}'."
|
968
|
-
end
|
926
|
+
raise ArgumentError, "Packed IP should be an Integer, but was a #{options.class}."
|
969
927
|
end
|
970
928
|
|
971
|
-
|
972
|
-
|
973
|
-
|
929
|
+
# validate
|
930
|
+
to_validate[:IP] = packed_ip
|
931
|
+
IPAdmin.validate_ip_addr(to_validate)
|
974
932
|
|
975
933
|
# set version if not set
|
976
934
|
if (!version)
|
@@ -1030,38 +988,48 @@ module_function :unpack_ip_addr
|
|
1030
988
|
#==============================================================================#
|
1031
989
|
|
1032
990
|
# Unack a packed IP netmask into a integer representing the number of
|
1033
|
-
# bits in the CIDR mask.
|
991
|
+
# bits in the CIDR mask.
|
1034
992
|
#
|
1035
993
|
# - Arguments:
|
1036
|
-
# * Hash with the following fields:
|
994
|
+
# * Integer or a Hash with the following fields:
|
1037
995
|
# - :Integer -- Integer representation of an IP Netmask
|
1038
996
|
#
|
1039
997
|
# - Returns:
|
1040
998
|
# * Integer
|
1041
999
|
#
|
1042
|
-
#
|
1000
|
+
# Examples:
|
1001
|
+
# unpacked = IPAdmin.unpack_ip_netmask(0xfffffffe)
|
1043
1002
|
# unpacked = IPAdmin.unpack_ip_netmask(:Integer => packed)
|
1044
1003
|
#
|
1045
1004
|
def unpack_ip_netmask(options)
|
1046
|
-
if (!options.kind_of?(Hash))
|
1047
|
-
raise ArgumentError, "Expected Hash, but #{options.class} provided."
|
1048
|
-
end
|
1049
1005
|
|
1050
|
-
if (
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1006
|
+
if (options.kind_of?(Hash))
|
1007
|
+
if (!options.has_key?(:Integer))
|
1008
|
+
raise ArgumentError, "Missing argument: Integer."
|
1009
|
+
end
|
1010
|
+
packed_netmask = options[:Integer]
|
1011
|
+
|
1012
|
+
if (!packed_netmask.kind_of?(Integer))
|
1013
|
+
raise ArgumentError, "Packed netmask should be an Integer, but is a #{packed_netmask.class}."
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
elsif (options.kind_of?(Integer))
|
1017
|
+
packed_netmask = options
|
1018
|
+
|
1019
|
+
else
|
1020
|
+
raise ArgumentError, "Integer or Hash expected, but #{options.class} provided."
|
1021
|
+
end
|
1054
1022
|
|
1055
|
-
if (!packed_netmask.kind_of?(Integer))
|
1056
|
-
raise ArgumentError, "Argument :Integer should be an Integer, but is a #{packed_netmask.class}."
|
1057
|
-
end
|
1058
1023
|
|
1059
1024
|
if (packed_netmask < 2**32)
|
1060
1025
|
mask = 32
|
1026
|
+
IPAdmin.validate_ip_netmask(:Netmask => packed_netmask, :Packed => true, :Version => 4)
|
1061
1027
|
else
|
1028
|
+
IPAdmin.validate_ip_netmask(:Netmask => packed_netmask, :Packed => true, :Version => 6)
|
1062
1029
|
mask = 128
|
1063
1030
|
end
|
1064
1031
|
|
1032
|
+
|
1065
1033
|
mask.times do
|
1066
1034
|
if ( (packed_netmask & 1) == 1)
|
1067
1035
|
break
|
@@ -1087,13 +1055,13 @@ module_function :unpack_ip_netmask
|
|
1087
1055
|
# notation. The address should not contain a netmask.
|
1088
1056
|
#
|
1089
1057
|
# - Arguments:
|
1090
|
-
# * String
|
1058
|
+
# * IP address as a String
|
1091
1059
|
#
|
1092
1060
|
# - Returns:
|
1093
1061
|
# * String
|
1094
1062
|
#
|
1095
|
-
#
|
1096
|
-
# long = IPAdmin.unshorten('fec0::1')
|
1063
|
+
# Examples:
|
1064
|
+
# long = IPAdmin.unshorten('fec0::1')
|
1097
1065
|
#
|
1098
1066
|
def unshorten(addr)
|
1099
1067
|
|
@@ -1128,24 +1096,27 @@ module_function :unshorten
|
|
1128
1096
|
# Validate an EUI-48 or EUI-64 address.
|
1129
1097
|
#
|
1130
1098
|
# - Arguments
|
1131
|
-
# * Hash with the following fields:
|
1099
|
+
# * EUI address as a String, or a Hash with the following fields:
|
1132
1100
|
# - :EUI -- Address to validate - String
|
1133
1101
|
#
|
1134
1102
|
# - Returns:
|
1135
1103
|
# * True
|
1136
1104
|
#
|
1137
|
-
#
|
1105
|
+
# Examples:
|
1106
|
+
# * IPAdmin.validate_eui('01-00-5e-12-34-56')
|
1138
1107
|
# * IPAdmin.validate_eui(:EUI => '01-00-5e-12-34-56')
|
1139
1108
|
#
|
1140
1109
|
def validate_eui(options)
|
1141
|
-
if (
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1110
|
+
if (options.kind_of? Hash)
|
1111
|
+
if (!options.has_key?(:EUI))
|
1112
|
+
raise ArgumentError, "Missing argument: EUI."
|
1113
|
+
end
|
1114
|
+
eui = options[:EUI]
|
1115
|
+
elsif (options.kind_of? String)
|
1116
|
+
eui = options
|
1117
|
+
else
|
1118
|
+
raise ArgumentError, "String or Hash expected, but #{options.class} provided."
|
1147
1119
|
end
|
1148
|
-
eui = options[:EUI]
|
1149
1120
|
|
1150
1121
|
if (eui.kind_of?(String))
|
1151
1122
|
# check for invalid characters
|
@@ -1174,8 +1145,7 @@ def validate_eui(options)
|
|
1174
1145
|
end
|
1175
1146
|
|
1176
1147
|
else
|
1177
|
-
raise ArgumentError, "
|
1178
|
-
"provided for argument :EUI."
|
1148
|
+
raise ArgumentError, "EUI address should be a String, but was a#{eui.class}."
|
1179
1149
|
end
|
1180
1150
|
return(true)
|
1181
1151
|
end
|
@@ -1193,7 +1163,7 @@ module_function :validate_eui
|
|
1193
1163
|
# Validate an IP address. The address should not contain a netmask.
|
1194
1164
|
#
|
1195
1165
|
# - Arguments
|
1196
|
-
# * Hash with the following fields:
|
1166
|
+
# * IP address as a String or Integer, or a Hash with the following fields:
|
1197
1167
|
# - :IP -- IP address to validate - String or Integer
|
1198
1168
|
# - :Version -- IP version - Integer (optional)
|
1199
1169
|
#
|
@@ -1203,9 +1173,9 @@ module_function :validate_eui
|
|
1203
1173
|
# - Notes:
|
1204
1174
|
# * IP version will attempt to be auto-detected if not provided
|
1205
1175
|
#
|
1206
|
-
#
|
1207
|
-
# validate_ip_addr(
|
1208
|
-
# validate_ip_addr(IP => 'ffff::1')
|
1176
|
+
# Examples:
|
1177
|
+
# validate_ip_addr('192.168.1.1')
|
1178
|
+
# validate_ip_addr(IP => 'ffff::1', :Version => 6)
|
1209
1179
|
# validate_ip_addr(IP => '::192.168.1.1')
|
1210
1180
|
# validate_ip_addr(IP => 0xFFFFFF)
|
1211
1181
|
# validate_ip_addr(IP => 2**128-1)
|
@@ -1213,20 +1183,22 @@ module_function :validate_eui
|
|
1213
1183
|
#
|
1214
1184
|
def validate_ip_addr(options)
|
1215
1185
|
|
1216
|
-
if (
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
raise ArgumentError, "Missing argument: IP."
|
1222
|
-
end
|
1223
|
-
ip = options[:IP]
|
1186
|
+
if (options.kind_of?(Hash))
|
1187
|
+
if (!options.has_key?(:IP))
|
1188
|
+
raise ArgumentError, "Missing argument: IP."
|
1189
|
+
end
|
1190
|
+
ip = options[:IP]
|
1224
1191
|
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1192
|
+
if (options.has_key?(:Version))
|
1193
|
+
version = options[:Version]
|
1194
|
+
if (version != 4 && version != 6)
|
1195
|
+
raise ArgumentError, ":Version should be 4 or 6, but was '#{version}'."
|
1196
|
+
end
|
1229
1197
|
end
|
1198
|
+
elsif (options.kind_of?(String) || options.kind_of?(Integer))
|
1199
|
+
ip = options
|
1200
|
+
else
|
1201
|
+
raise ArgumentError, "String or Hash expected, but #{options.class} provided."
|
1230
1202
|
end
|
1231
1203
|
|
1232
1204
|
if ( ip.kind_of?(String) )
|
@@ -1358,7 +1330,7 @@ module_function :validate_ip_addr
|
|
1358
1330
|
# Validate IP Netmask.
|
1359
1331
|
#
|
1360
1332
|
# - Arguments:
|
1361
|
-
# * Hash with the following fields:
|
1333
|
+
# * Netmask as a String or Integer, or a Hash with the following fields:
|
1362
1334
|
# - :Netmask -- Netmask to validate - String or Integer
|
1363
1335
|
# - :Packed -- if true, the provided Netmask is a packed Integer
|
1364
1336
|
# - :Version -- IP version - Integer (optional)
|
@@ -1369,42 +1341,43 @@ module_function :validate_ip_addr
|
|
1369
1341
|
# - Notes:
|
1370
1342
|
# * Version defaults to 4 if not specified.
|
1371
1343
|
#
|
1372
|
-
#
|
1373
|
-
# IPAdmin.validate_ip_netmask(
|
1374
|
-
# IPAdmin.validate_ip_netmask(
|
1344
|
+
# Examples:
|
1345
|
+
# IPAdmin.validate_ip_netmask('/32')
|
1346
|
+
# IPAdmin.validate_ip_netmask(32)
|
1375
1347
|
# IPAdmin.validate_ip_netmask(:Netmask => 0xffffffff, :Packed => true)
|
1376
1348
|
#
|
1377
1349
|
def validate_ip_netmask(options)
|
1378
1350
|
packed = false
|
1351
|
+
version = 4
|
1352
|
+
max_bits = 32
|
1379
1353
|
|
1380
|
-
if (
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
raise ArgumentError, "Missing argument: Netmask."
|
1386
|
-
end
|
1387
|
-
netmask = options[:Netmask]
|
1354
|
+
if (options.kind_of?(Hash))
|
1355
|
+
if (!options.has_key?(:Netmask))
|
1356
|
+
raise ArgumentError, "Missing argument: Netmask."
|
1357
|
+
end
|
1358
|
+
netmask = options[:Netmask]
|
1388
1359
|
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1360
|
+
if (options.has_key?(:Packed) && options[:Packed] == true)
|
1361
|
+
packed = true
|
1362
|
+
end
|
1392
1363
|
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1364
|
+
if (options.has_key?(:Version))
|
1365
|
+
version = options[:Version]
|
1366
|
+
if (version != 4 && version != 6)
|
1367
|
+
raise ArgumentError, ":Version should be 4 or 6, but was '#{version}'."
|
1368
|
+
elsif (version == 6)
|
1369
|
+
max_bits = 128
|
1370
|
+
else
|
1371
|
+
max_bits = 32
|
1372
|
+
end
|
1401
1373
|
end
|
1374
|
+
|
1375
|
+
elsif (options.kind_of?(String) || options.kind_of?(Integer))
|
1376
|
+
netmask = options
|
1402
1377
|
else
|
1403
|
-
|
1404
|
-
max_bits = 32
|
1378
|
+
raise ArgumentError, "String, Integer, or Hash expected, but #{options.class} provided."
|
1405
1379
|
end
|
1406
1380
|
|
1407
|
-
|
1408
1381
|
if (netmask.kind_of?(String))
|
1409
1382
|
if(netmask =~ /\./)
|
1410
1383
|
all_f = 2**32-1
|
@@ -1490,13 +1463,11 @@ module_function :validate_ip_netmask
|
|
1490
1463
|
# to anyone.
|
1491
1464
|
#
|
1492
1465
|
# Description of fields:
|
1493
|
-
# *
|
1494
|
-
# *
|
1495
|
-
# *
|
1496
|
-
# * object - holds an IPAdmin class object
|
1497
|
-
# * subnets - an array of children NetStruct objects
|
1466
|
+
# * cidr - IPAdmin::CIDR object
|
1467
|
+
# * parent - parent NetStruct in tree
|
1468
|
+
# * children - Array of children NetStruct objects
|
1498
1469
|
#
|
1499
|
-
NetStruct = Struct.new(:
|
1470
|
+
NetStruct = Struct.new(:cidr, :parent, :children)
|
1500
1471
|
|
1501
1472
|
#======================================#
|
1502
1473
|
#
|