netaddr 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of netaddr might be problematic. Click here for more details.
- data/changelog +27 -0
- data/lib/cidr.rb +595 -795
- data/lib/cidr_shortcuts.rb +334 -0
- data/lib/eui.rb +16 -16
- data/lib/ip_math.rb +241 -0
- data/lib/methods.rb +230 -643
- data/lib/net_addr.rb +3 -1
- data/lib/tree.rb +202 -196
- data/lib/validation_shortcuts.rb +219 -0
- data/tests/cidr_test.rb +66 -62
- data/tests/methods_test.rb +31 -50
- data/tests/tree_test.rb +1 -1
- metadata +7 -2
@@ -0,0 +1,334 @@
|
|
1
|
+
module NetAddr
|
2
|
+
private
|
3
|
+
|
4
|
+
# CIDR METHODS
|
5
|
+
|
6
|
+
#==============================================================================#
|
7
|
+
# cidr_build()
|
8
|
+
#==============================================================================#
|
9
|
+
|
10
|
+
# create either a CIDRv4 or CIDRv6 object
|
11
|
+
#
|
12
|
+
def cidr_build(version, ip, netmask=nil, tag={}, wildcard_mask=nil, wildcard_mask_bit_flipped=false)
|
13
|
+
return( NetAddr::CIDRv4.new(ip, netmask, tag, wildcard_mask, wildcard_mask_bit_flipped) ) if (version == 4)
|
14
|
+
return( NetAddr::CIDRv6.new(ip, netmask, tag, wildcard_mask, wildcard_mask_bit_flipped) )
|
15
|
+
end
|
16
|
+
module_function :cidr_build
|
17
|
+
|
18
|
+
#==============================================================================#
|
19
|
+
# cidr_compare()
|
20
|
+
#==============================================================================#
|
21
|
+
|
22
|
+
# compare 2 CIDR objects
|
23
|
+
#
|
24
|
+
#return:
|
25
|
+
#* 1 if the cidr1 contains cidr2
|
26
|
+
#* 0 if the cidr1 and cidr2 are equal
|
27
|
+
#* -1 if cidr1 is a subnet of cidr2
|
28
|
+
#* nil if the two are unrelated
|
29
|
+
#
|
30
|
+
def cidr_compare(cidr1,cidr2)
|
31
|
+
comparasin = nil
|
32
|
+
if ( (cidr1.packed_network == cidr2.packed_network))
|
33
|
+
# same network, check netmask
|
34
|
+
if (cidr1.packed_netmask == cidr2.packed_netmask)
|
35
|
+
comparasin = 0
|
36
|
+
elsif(cidr1.packed_netmask < cidr2.packed_netmask)
|
37
|
+
comparasin = 1
|
38
|
+
elsif(cidr1.packed_netmask > cidr2.packed_netmask)
|
39
|
+
comparasin = -1
|
40
|
+
end
|
41
|
+
|
42
|
+
elsif( (cidr2.packed_network | cidr1.packed_hostmask) == (cidr1.packed_network | cidr1.packed_hostmask) )
|
43
|
+
# cidr1 contains cidr2
|
44
|
+
comparasin = 1
|
45
|
+
|
46
|
+
elsif( (cidr2.packed_network | cidr2.packed_hostmask) == (cidr1.packed_network | cidr2.packed_hostmask) )
|
47
|
+
# cidr2 contains cidr1
|
48
|
+
comparasin = -1
|
49
|
+
end
|
50
|
+
|
51
|
+
return(comparasin)
|
52
|
+
end
|
53
|
+
module_function :cidr_compare
|
54
|
+
|
55
|
+
#==============================================================================#
|
56
|
+
# cidr_gt_lt()
|
57
|
+
#==============================================================================#
|
58
|
+
|
59
|
+
# given a pair of CIDRs, determine if first is greater than or less than the second
|
60
|
+
#
|
61
|
+
# return 1 if cidr1 > cidr2
|
62
|
+
# return 0 if cidr1 == cidr2
|
63
|
+
# return -1 if cidr1 < cidr2
|
64
|
+
#
|
65
|
+
def cidr_gt_lt(cidr1,cidr2)
|
66
|
+
gt_lt = 1
|
67
|
+
if(cidr1.packed_network < cidr2.packed_network)
|
68
|
+
gt_lt = -1
|
69
|
+
elsif (cidr1.packed_network == cidr2.packed_network)
|
70
|
+
if (cidr1.packed_netmask < cidr2.packed_netmask)
|
71
|
+
gt_lt = -1
|
72
|
+
elsif (cidr1.packed_netmask == cidr2.packed_netmask)
|
73
|
+
gt_lt = 0
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
return(gt_lt)
|
78
|
+
end
|
79
|
+
module_function :cidr_gt_lt
|
80
|
+
|
81
|
+
#==============================================================================#
|
82
|
+
# cidr_fill_in()
|
83
|
+
#==============================================================================#
|
84
|
+
|
85
|
+
#Given a list of subnets of supernet, return a new list with any
|
86
|
+
#holes (missing subnets) filled in.
|
87
|
+
#
|
88
|
+
def cidr_fill_in(supernet,list)
|
89
|
+
# sort our cidr's and see what is missing
|
90
|
+
complete_list = []
|
91
|
+
expected = supernet.packed_network
|
92
|
+
all_f = supernet.all_f
|
93
|
+
version = supernet.version
|
94
|
+
|
95
|
+
NetAddr.cidr_sort(list).each do |cidr|
|
96
|
+
network = cidr.packed_network
|
97
|
+
bitstep = (all_f + 1) - cidr.packed_netmask
|
98
|
+
|
99
|
+
if (network > expected)
|
100
|
+
num_ips_missing = network - expected
|
101
|
+
sub_list = cidr_make_subnets_from_base_and_ip_count(supernet,expected,num_ips_missing)
|
102
|
+
complete_list.concat(sub_list)
|
103
|
+
elsif (network < expected)
|
104
|
+
next
|
105
|
+
end
|
106
|
+
|
107
|
+
complete_list.push(NetAddr.cidr_build(version,network,cidr.packed_netmask))
|
108
|
+
expected = network + bitstep
|
109
|
+
end
|
110
|
+
|
111
|
+
# if expected is not the next subnet, then we're missing subnets
|
112
|
+
# at the end of the cidr
|
113
|
+
next_sub = supernet.next_subnet(:Objectify => true).packed_network
|
114
|
+
if (expected != next_sub)
|
115
|
+
num_ips_missing = next_sub - expected
|
116
|
+
sub_list = cidr_make_subnets_from_base_and_ip_count(supernet,expected,num_ips_missing)
|
117
|
+
complete_list.concat(sub_list)
|
118
|
+
end
|
119
|
+
|
120
|
+
return(complete_list)
|
121
|
+
end
|
122
|
+
module_function :cidr_fill_in
|
123
|
+
|
124
|
+
#==============================================================================#
|
125
|
+
# cidr_find_in_list()
|
126
|
+
#==============================================================================#
|
127
|
+
|
128
|
+
# evaluate cidr against list of cidrs.
|
129
|
+
#
|
130
|
+
# return entry from list if entry is supernet of cidr (first matching entry)
|
131
|
+
# return index # of entry if entry is a duplicate of cidr
|
132
|
+
# return nil if no match found
|
133
|
+
#
|
134
|
+
def cidr_find_in_list(cidr,list)
|
135
|
+
return(nil) if (list.length == 0)
|
136
|
+
|
137
|
+
match = nil
|
138
|
+
low = 0
|
139
|
+
high = list.length - 1
|
140
|
+
index = low + ( (high-low)/2 )
|
141
|
+
while ( low <= high)
|
142
|
+
cmp = cidr_gt_lt(cidr,list[index])
|
143
|
+
if ( cmp == -1 )
|
144
|
+
high = index - 1
|
145
|
+
|
146
|
+
elsif ( cmp == 1 )
|
147
|
+
if (cidr_compare(cidr,list[index]) == -1)
|
148
|
+
match = list[index]
|
149
|
+
break
|
150
|
+
end
|
151
|
+
low = index + 1
|
152
|
+
|
153
|
+
else
|
154
|
+
match = index
|
155
|
+
break
|
156
|
+
end
|
157
|
+
index = low + ( (high-low)/2 )
|
158
|
+
end
|
159
|
+
return(match)
|
160
|
+
end
|
161
|
+
module_function :cidr_find_in_list
|
162
|
+
|
163
|
+
#==============================================================================#
|
164
|
+
# cidr_make_subnets_from_base_and_ip_count()
|
165
|
+
#==============================================================================#
|
166
|
+
|
167
|
+
# Make CIDR addresses from a base addr and an number of ip's to encapsulate.
|
168
|
+
#
|
169
|
+
#===Arguments:
|
170
|
+
# * base ip as packed integer
|
171
|
+
# * number of ip's required
|
172
|
+
#
|
173
|
+
#===Returns:
|
174
|
+
# * array of NetAddr::CIDR objects
|
175
|
+
#
|
176
|
+
def cidr_make_subnets_from_base_and_ip_count(cidr,base_addr,ip_count)
|
177
|
+
list = []
|
178
|
+
until (ip_count == 0)
|
179
|
+
mask = cidr.all_f
|
180
|
+
multiplier = 0
|
181
|
+
bitstep = 0
|
182
|
+
last_addr = base_addr
|
183
|
+
done = false
|
184
|
+
until (done == true)
|
185
|
+
if (bitstep < ip_count && (base_addr & mask == last_addr & mask) )
|
186
|
+
multiplier += 1
|
187
|
+
elsif (bitstep > ip_count || (base_addr & mask != last_addr & mask) )
|
188
|
+
multiplier -= 1
|
189
|
+
done = true
|
190
|
+
else
|
191
|
+
done = true
|
192
|
+
end
|
193
|
+
bitstep = 2**multiplier
|
194
|
+
mask = cidr.all_f << multiplier & cidr.all_f
|
195
|
+
last_addr = base_addr + bitstep - 1
|
196
|
+
end
|
197
|
+
|
198
|
+
list.push(NetAddr.cidr_build(cidr.version,base_addr,mask))
|
199
|
+
ip_count -= bitstep
|
200
|
+
base_addr += bitstep
|
201
|
+
end
|
202
|
+
|
203
|
+
return(list)
|
204
|
+
end
|
205
|
+
module_function :cidr_make_subnets_from_base_and_ip_count
|
206
|
+
|
207
|
+
#==============================================================================#
|
208
|
+
# cidr_sort()
|
209
|
+
#==============================================================================#
|
210
|
+
|
211
|
+
# given a list of NetAddr::CIDRs, return them as a sorted list
|
212
|
+
#
|
213
|
+
def cidr_sort(list)
|
214
|
+
# uses simple quicksort algorithm
|
215
|
+
sorted_list = []
|
216
|
+
if (list.length < 1)
|
217
|
+
sorted_list = list
|
218
|
+
else
|
219
|
+
less_list = []
|
220
|
+
greater_list = []
|
221
|
+
equal_list = []
|
222
|
+
pivot = list[rand(list.length)]
|
223
|
+
list.each do |x|
|
224
|
+
gt_lt = cidr_gt_lt(pivot,x)
|
225
|
+
if (gt_lt == 1)
|
226
|
+
less_list.push(x)
|
227
|
+
elsif (gt_lt == -1)
|
228
|
+
greater_list.push(x)
|
229
|
+
else
|
230
|
+
equal_list.push(x)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
sorted_list.concat( cidr_sort(less_list) )
|
234
|
+
sorted_list.concat(equal_list)
|
235
|
+
sorted_list.concat( cidr_sort(greater_list) )
|
236
|
+
end
|
237
|
+
|
238
|
+
return(sorted_list)
|
239
|
+
end
|
240
|
+
module_function :cidr_sort
|
241
|
+
|
242
|
+
#==============================================================================#
|
243
|
+
# cidr_summarize()
|
244
|
+
#==============================================================================#
|
245
|
+
|
246
|
+
# given a list of NetAddr::CIDRs (of the same version) summarize them
|
247
|
+
#
|
248
|
+
# return a hash, with the key = summary address and val = array of original cidrs
|
249
|
+
#
|
250
|
+
def cidr_summarize(subnet_list)
|
251
|
+
all_f = subnet_list[0].all_f
|
252
|
+
version = subnet_list[0].version
|
253
|
+
subnet_list = cidr_sort(subnet_list)
|
254
|
+
|
255
|
+
# continue summarization attempts until sorted_list stops getting shorter
|
256
|
+
sorted_list = subnet_list.dup
|
257
|
+
sorted_list_len = sorted_list.length
|
258
|
+
while (1)
|
259
|
+
summarized_list = []
|
260
|
+
until (sorted_list.length == 0)
|
261
|
+
cidr = sorted_list.shift
|
262
|
+
network, netmask = cidr.packed_network, cidr.packed_netmask
|
263
|
+
supermask = (netmask << 1) & all_f
|
264
|
+
supernet = supermask & network
|
265
|
+
|
266
|
+
if (network == supernet && sorted_list.length > 0)
|
267
|
+
# network is lower half of supernet, so see if we have the upper half
|
268
|
+
bitstep = (all_f + 1) - netmask
|
269
|
+
expected = network + bitstep
|
270
|
+
next_cidr = sorted_list.shift
|
271
|
+
next_network, next_netmask = next_cidr.packed_network, next_cidr.packed_netmask
|
272
|
+
|
273
|
+
if ( (next_network == expected) && (next_netmask == netmask) )
|
274
|
+
# we do indeed have the upper half. store new supernet.
|
275
|
+
summarized_list.push( cidr_build(version,supernet,supermask) )
|
276
|
+
else
|
277
|
+
# we do not have the upper half. put next_cidr back into sorted_list
|
278
|
+
# and store only the original network
|
279
|
+
sorted_list.unshift(next_cidr)
|
280
|
+
summarized_list.push(cidr)
|
281
|
+
end
|
282
|
+
else
|
283
|
+
# network is upper half of supernet, so save original network only
|
284
|
+
summarized_list.push(cidr)
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
288
|
+
|
289
|
+
sorted_list = summarized_list.dup
|
290
|
+
break if (sorted_list.length == sorted_list_len)
|
291
|
+
sorted_list_len = sorted_list.length
|
292
|
+
end
|
293
|
+
|
294
|
+
# clean up summarized_list
|
295
|
+
unique_list = {}
|
296
|
+
summarized_list.reverse.each do |supernet|
|
297
|
+
next if ( unique_list.has_key?(supernet.desc) )
|
298
|
+
# remove duplicates
|
299
|
+
unique_list[supernet.desc] = supernet
|
300
|
+
|
301
|
+
# remove any summary blocks that are children of other summary blocks
|
302
|
+
index = 0
|
303
|
+
until (index >= summarized_list.length)
|
304
|
+
subnet = summarized_list[index]
|
305
|
+
if (subnet && cidr_compare(supernet,subnet) == 1 )
|
306
|
+
subnet_list[index] = nil
|
307
|
+
end
|
308
|
+
index += 1
|
309
|
+
end
|
310
|
+
end
|
311
|
+
summarized_list = unique_list.values
|
312
|
+
|
313
|
+
# map original blocks to their summaries
|
314
|
+
summarized_list.each do |supernet|
|
315
|
+
supernet.tag[:Subnets] = []
|
316
|
+
index = 0
|
317
|
+
until (index >= subnet_list.length)
|
318
|
+
subnet = subnet_list[index]
|
319
|
+
if (subnet && cidr_compare(supernet,subnet) == 1 )
|
320
|
+
subnet_list[index] = nil
|
321
|
+
supernet.tag[:Subnets].push(subnet)
|
322
|
+
end
|
323
|
+
index += 1
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
return( NetAddr.cidr_sort(summarized_list) )
|
328
|
+
end
|
329
|
+
module_function :cidr_summarize
|
330
|
+
|
331
|
+
|
332
|
+
end # module NetAddr
|
333
|
+
|
334
|
+
__END__
|
data/lib/eui.rb
CHANGED
@@ -40,7 +40,7 @@ private_class_method :new
|
|
40
40
|
# addr = NetAddr::EUI.new('aa-bb-cc-dd-ee-ff-00-01')
|
41
41
|
#
|
42
42
|
#===Arguments
|
43
|
-
#* EUI as a String
|
43
|
+
#* eui = EUI as a String
|
44
44
|
#
|
45
45
|
#===Returns
|
46
46
|
#* EUI48 or EUI64 object
|
@@ -62,7 +62,7 @@ private_class_method :new
|
|
62
62
|
else
|
63
63
|
eui = NetAddr::EUI64.new(eui.to_i(16))
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
return(eui)
|
67
67
|
end
|
68
68
|
|
@@ -76,8 +76,8 @@ private_class_method :new
|
|
76
76
|
# puts addr.address(:Delimiter => '.') --> 'aabb.ccdd.eeff'
|
77
77
|
#
|
78
78
|
#===Arguments:
|
79
|
-
#*
|
80
|
-
# :Delimiter -- delimitation character. valid values are (-,:,and .)
|
79
|
+
#* options = Hash with the following fields:
|
80
|
+
# :Delimiter -- delimitation character. valid values are (-,:,and .)
|
81
81
|
#
|
82
82
|
#===Returns:
|
83
83
|
#* String
|
@@ -135,8 +135,8 @@ private_class_method :new
|
|
135
135
|
# puts addr.ei(:Delimiter => '-')
|
136
136
|
#
|
137
137
|
#===Arguments:
|
138
|
-
#*
|
139
|
-
# :Delimiter -- delimitation character. valid values are (-, and :)
|
138
|
+
#* options = Hash with the following fields:
|
139
|
+
# :Delimiter -- delimitation character. valid values are (-, and :)
|
140
140
|
#
|
141
141
|
#===Returns:
|
142
142
|
#* String
|
@@ -173,9 +173,9 @@ private_class_method :new
|
|
173
173
|
# puts addr.link_local()
|
174
174
|
#
|
175
175
|
#===Arguments:
|
176
|
-
#*
|
177
|
-
# :Short -- if true, return IPv6 addresses in short-hand notation
|
178
|
-
# :Objectify -- if true, return CIDR objects
|
176
|
+
#* options = Hash with the following fields:
|
177
|
+
# :Short -- if true, return IPv6 addresses in short-hand notation
|
178
|
+
# :Objectify -- if true, return CIDR objects
|
179
179
|
#
|
180
180
|
#===Returns:
|
181
181
|
#* CIDR address String or an NetAddr::CIDR object
|
@@ -228,8 +228,8 @@ private_class_method :new
|
|
228
228
|
# puts addr.oui(:Delimiter => '-')
|
229
229
|
#
|
230
230
|
#===Arguments:
|
231
|
-
#*
|
232
|
-
# :Delimiter -- delimitation character. valid values are (-, and :)
|
231
|
+
#* options = Hash with the following fields:
|
232
|
+
# :Delimiter -- delimitation character. valid values are (-, and :)
|
233
233
|
#
|
234
234
|
#===Returns:
|
235
235
|
#* String
|
@@ -323,12 +323,12 @@ public_class_method :new
|
|
323
323
|
#* EUI as a String or Integer
|
324
324
|
#
|
325
325
|
def initialize(eui)
|
326
|
-
|
326
|
+
|
327
327
|
if (eui.kind_of?(Integer))
|
328
328
|
@oui = eui >> 24
|
329
329
|
@ei = eui & 0xffffff
|
330
330
|
|
331
|
-
elsif(eui.kind_of?(String))
|
331
|
+
elsif(eui.kind_of?(String))
|
332
332
|
# validate
|
333
333
|
NetAddr.validate_eui(eui)
|
334
334
|
|
@@ -361,15 +361,15 @@ public_class_method :new
|
|
361
361
|
# addr = NetAddr::EUI64.new('aa-bb-cc-dd-ee-ff-00-01')
|
362
362
|
#
|
363
363
|
#===Arguments:
|
364
|
-
#* EUI as a String or Integer
|
364
|
+
#* eui = EUI as a String or Integer
|
365
365
|
#
|
366
366
|
def initialize(eui)
|
367
|
-
|
367
|
+
|
368
368
|
if (eui.kind_of?(Integer))
|
369
369
|
@oui = eui >> 40
|
370
370
|
@ei = eui & 0xffffffffffd
|
371
371
|
|
372
|
-
elsif(eui.kind_of?(String))
|
372
|
+
elsif(eui.kind_of?(String))
|
373
373
|
# validate
|
374
374
|
NetAddr.validate_eui(eui)
|
375
375
|
|
data/lib/ip_math.rb
ADDED
@@ -0,0 +1,241 @@
|
|
1
|
+
module NetAddr
|
2
|
+
private
|
3
|
+
|
4
|
+
|
5
|
+
# IP MATH METHODS
|
6
|
+
|
7
|
+
#==============================================================================#
|
8
|
+
# bits_to_mask()
|
9
|
+
#==============================================================================#
|
10
|
+
|
11
|
+
# convert a netmask (in bits) to an integer mask
|
12
|
+
#
|
13
|
+
def bits_to_mask(netmask,version)
|
14
|
+
return(0) if (netmask == 0)
|
15
|
+
all_f = 2**32-1
|
16
|
+
all_f = 2**128-1 if (version == 6)
|
17
|
+
return( all_f ^ (all_f >> netmask) )
|
18
|
+
end
|
19
|
+
module_function :bits_to_mask
|
20
|
+
|
21
|
+
#==============================================================================#
|
22
|
+
# detect_ip_version()
|
23
|
+
#==============================================================================#
|
24
|
+
|
25
|
+
# determine the ip version from ip address string.
|
26
|
+
#
|
27
|
+
# return 4, 6, or nil
|
28
|
+
#
|
29
|
+
def detect_ip_version(ip)
|
30
|
+
version = nil
|
31
|
+
if ( ip =~ /\./ && ip !~ /:/ )
|
32
|
+
version = 4
|
33
|
+
elsif (ip =~ /:/)
|
34
|
+
version = 6
|
35
|
+
else
|
36
|
+
raise ValidationError, "Count not auto-detect IP version for '#{ip}'."
|
37
|
+
end
|
38
|
+
return(version)
|
39
|
+
end
|
40
|
+
module_function :detect_ip_version
|
41
|
+
|
42
|
+
#==============================================================================#
|
43
|
+
# ip_count_to_size()
|
44
|
+
#==============================================================================#
|
45
|
+
|
46
|
+
# given an ip count, determine the most appropriate mask (in bits)
|
47
|
+
#
|
48
|
+
def ip_count_to_size(ipcount,version,extended=false)
|
49
|
+
address_len = 32
|
50
|
+
address_len = 128 if (version == 6 )
|
51
|
+
|
52
|
+
if (ipcount > 2**address_len)
|
53
|
+
raise BoundaryError, "Required IP count exceeds number of IP addresses available " +
|
54
|
+
"for IPv#{version}."
|
55
|
+
end
|
56
|
+
|
57
|
+
bits_needed = 0
|
58
|
+
until (2**bits_needed >= ipcount)
|
59
|
+
bits_needed += 1
|
60
|
+
end
|
61
|
+
subnet_bits = address_len - bits_needed
|
62
|
+
|
63
|
+
return( ip_int_to_str(bits_to_mask(subnet_bits, 4), 4) ) if (extended && version == 4)
|
64
|
+
return(subnet_bits)
|
65
|
+
end
|
66
|
+
module_function :ip_count_to_size
|
67
|
+
|
68
|
+
#==============================================================================#
|
69
|
+
# ip_int_to_str()
|
70
|
+
#==============================================================================#
|
71
|
+
|
72
|
+
# unpack an int into an ip address string
|
73
|
+
#
|
74
|
+
def ip_int_to_str(packed_ip, version, ipv4_mapped=nil)
|
75
|
+
ip = nil
|
76
|
+
version = 4 if (!version && packed_ip < 2**32)
|
77
|
+
if (version == 4)
|
78
|
+
octets = []
|
79
|
+
4.times do
|
80
|
+
octet = packed_ip & 0xFF
|
81
|
+
octets.unshift(octet.to_s)
|
82
|
+
packed_ip = packed_ip >> 8
|
83
|
+
end
|
84
|
+
ip = octets.join('.')
|
85
|
+
else
|
86
|
+
fields = []
|
87
|
+
if (!ipv4_mapped)
|
88
|
+
loop_count = 8
|
89
|
+
else
|
90
|
+
loop_count = 6
|
91
|
+
packed_v4 = packed_ip & 0xffffffff
|
92
|
+
ipv4_addr = ip_int_to_str(packed_v4, 4)
|
93
|
+
fields.unshift(ipv4_addr)
|
94
|
+
packed_ip = packed_ip >> 32
|
95
|
+
end
|
96
|
+
|
97
|
+
loop_count.times do
|
98
|
+
octet = packed_ip & 0xFFFF
|
99
|
+
octet = octet.to_s(16)
|
100
|
+
packed_ip = packed_ip >> 16
|
101
|
+
|
102
|
+
# if octet < 4 characters, then pad with 0's
|
103
|
+
(4 - octet.length).times do
|
104
|
+
octet = '0' << octet
|
105
|
+
end
|
106
|
+
fields.unshift(octet)
|
107
|
+
end
|
108
|
+
ip = fields.join(':')
|
109
|
+
end
|
110
|
+
return(ip)
|
111
|
+
end
|
112
|
+
module_function :ip_int_to_str
|
113
|
+
|
114
|
+
#==============================================================================#
|
115
|
+
# ip_str_to_int()
|
116
|
+
#==============================================================================#
|
117
|
+
|
118
|
+
# convert an ip string into an int
|
119
|
+
#
|
120
|
+
def ip_str_to_int(ip,version)
|
121
|
+
packed_ip = 0
|
122
|
+
if ( version == 4)
|
123
|
+
octets = ip.split('.')
|
124
|
+
(0..3).each do |x|
|
125
|
+
octet = octets.pop.to_i
|
126
|
+
octet = octet << 8*x
|
127
|
+
packed_ip = packed_ip | octet
|
128
|
+
end
|
129
|
+
|
130
|
+
else
|
131
|
+
# if ipv4-mapped ipv6 addr
|
132
|
+
if (ip =~ /\./)
|
133
|
+
dotted_dec = true
|
134
|
+
end
|
135
|
+
|
136
|
+
# split up by ':'
|
137
|
+
fields = []
|
138
|
+
if (ip =~ /::/)
|
139
|
+
shrthnd = ip.split( /::/ )
|
140
|
+
if (shrthnd.length == 0)
|
141
|
+
return(0)
|
142
|
+
else
|
143
|
+
first_half = shrthnd[0].split( /:/ ) if (shrthnd[0])
|
144
|
+
sec_half = shrthnd[1].split( /:/ ) if (shrthnd[1])
|
145
|
+
first_half = [] if (!first_half)
|
146
|
+
sec_half = [] if (!sec_half)
|
147
|
+
end
|
148
|
+
missing_fields = 8 - first_half.length - sec_half.length
|
149
|
+
missing_fields -= 1 if dotted_dec
|
150
|
+
fields = fields.concat(first_half)
|
151
|
+
missing_fields.times {fields.push('0')}
|
152
|
+
fields = fields.concat(sec_half)
|
153
|
+
|
154
|
+
else
|
155
|
+
fields = ip.split(':')
|
156
|
+
end
|
157
|
+
|
158
|
+
if (dotted_dec)
|
159
|
+
ipv4_addr = fields.pop
|
160
|
+
packed_v4 = NetAddr.pack_ip_addr(ipv4_addr, :Version => 4)
|
161
|
+
octets = []
|
162
|
+
2.times do
|
163
|
+
octet = packed_v4 & 0xFFFF
|
164
|
+
octets.unshift(octet.to_s(16))
|
165
|
+
packed_v4 = packed_v4 >> 16
|
166
|
+
end
|
167
|
+
fields.concat(octets)
|
168
|
+
end
|
169
|
+
|
170
|
+
# pack
|
171
|
+
(0..7).each do |x|
|
172
|
+
field = fields.pop.to_i(16)
|
173
|
+
field = field << 16*x
|
174
|
+
packed_ip = packed_ip | field
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
return(packed_ip)
|
179
|
+
end
|
180
|
+
module_function :ip_str_to_int
|
181
|
+
|
182
|
+
#==============================================================================#
|
183
|
+
# mask_to_bits()
|
184
|
+
#==============================================================================#
|
185
|
+
|
186
|
+
# convert integer into a cidr formatted netmask (bits)
|
187
|
+
#
|
188
|
+
def mask_to_bits(packed_netmask)
|
189
|
+
return(packed_netmask) if (packed_netmask == 0)
|
190
|
+
|
191
|
+
mask = nil
|
192
|
+
if (packed_netmask < 2**32)
|
193
|
+
mask = 32
|
194
|
+
validate_netmask_int(packed_netmask, 4, true)
|
195
|
+
else
|
196
|
+
mask = 128
|
197
|
+
validate_netmask_int(packed_netmask, 6, true)
|
198
|
+
end
|
199
|
+
|
200
|
+
mask.times do
|
201
|
+
if ( (packed_netmask & 1) == 1)
|
202
|
+
break
|
203
|
+
end
|
204
|
+
packed_netmask = packed_netmask >> 1
|
205
|
+
mask = mask - 1
|
206
|
+
end
|
207
|
+
return(mask)
|
208
|
+
end
|
209
|
+
module_function :mask_to_bits
|
210
|
+
|
211
|
+
#==============================================================================#
|
212
|
+
# netmask_str_to_int()
|
213
|
+
#==============================================================================#
|
214
|
+
|
215
|
+
# convert string into integer mask
|
216
|
+
#
|
217
|
+
def netmask_str_to_int(netmask,version)
|
218
|
+
packed_netmask = nil
|
219
|
+
all_f = 2**32-1
|
220
|
+
all_f = 2**128-1 if (version == 6)
|
221
|
+
if(netmask =~ /\./)
|
222
|
+
packed_netmask = NetAddr.pack_ip_addr(netmask)
|
223
|
+
else
|
224
|
+
# remove '/' if present
|
225
|
+
if (netmask =~ /^\// )
|
226
|
+
netmask[0] = " "
|
227
|
+
netmask.lstrip!
|
228
|
+
end
|
229
|
+
netmask = netmask.to_i
|
230
|
+
packed_netmask = all_f ^ (all_f >> netmask)
|
231
|
+
end
|
232
|
+
return(packed_netmask)
|
233
|
+
end
|
234
|
+
module_function :netmask_str_to_int
|
235
|
+
|
236
|
+
|
237
|
+
|
238
|
+
end # module NetAddr
|
239
|
+
|
240
|
+
__END__
|
241
|
+
|