ipadmin 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +190 -151
- data/lib/cidr.rb +412 -210
- data/lib/eui.rb +92 -115
- data/lib/methods.rb +409 -438
- data/lib/tree.rb +609 -367
- data/tests/cidr_test.rb +56 -43
- data/tests/eui_test.rb +16 -14
- data/tests/methods_test.rb +191 -185
- data/tests/tree_test.rb +191 -231
- metadata +3 -3
data/lib/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
|
#
|