netaddr 1.5.1 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of netaddr might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/LICENSE +201 -0
- data/README.md +29 -0
- data/lib/eui48.rb +65 -0
- data/lib/eui64.rb +77 -0
- data/lib/ipv4.rb +77 -0
- data/lib/ipv4net.rb +245 -0
- data/lib/ipv6.rb +110 -0
- data/lib/ipv6net.rb +246 -0
- data/lib/mask128.rb +68 -0
- data/lib/mask32.rb +99 -0
- data/lib/netaddr.rb +105 -27
- data/lib/util.rb +310 -0
- data/test/eui48_test.rb +30 -0
- data/test/eui64_test.rb +32 -0
- data/test/examples.rb +137 -0
- data/test/ipv4_test.rb +54 -0
- data/test/ipv4net_test.rb +166 -0
- data/test/ipv6_test.rb +90 -0
- data/test/ipv6net_test.rb +146 -0
- data/test/mask128_test.rb +45 -0
- data/test/mask32_test.rb +51 -0
- data/test/netaddr_test.rb +127 -0
- data/test/run_all.rb +10 -0
- metadata +29 -24
- data/Errors +0 -7
- data/README +0 -17
- data/changelog +0 -58
- data/lib/cidr.rb +0 -2189
- data/lib/cidr_shortcuts.rb +0 -440
- data/lib/eui.rb +0 -463
- data/lib/ip_math.rb +0 -259
- data/lib/methods.rb +0 -1079
- data/lib/tree.rb +0 -921
- data/lib/validation_shortcuts.rb +0 -219
- data/license +0 -13
- data/test/cidr_test.rb +0 -544
- data/test/eui_test.rb +0 -101
- data/test/methods_test.rb +0 -331
- data/test/tree_test.rb +0 -347
data/lib/cidr_shortcuts.rb
DELETED
@@ -1,440 +0,0 @@
|
|
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.to_i(:network) == cidr2.to_i(:network) )
|
33
|
-
# same network, check netmask
|
34
|
-
if (cidr1.to_i(:netmask) == cidr2.to_i(:netmask) )
|
35
|
-
comparasin = 0
|
36
|
-
elsif(cidr1.to_i(:netmask) < cidr2.to_i(:netmask))
|
37
|
-
comparasin = 1
|
38
|
-
elsif(cidr1.to_i(:netmask) > cidr2.to_i(:netmask))
|
39
|
-
comparasin = -1
|
40
|
-
end
|
41
|
-
|
42
|
-
elsif( (cidr2.to_i(:network) | cidr1.to_i(:hostmask)) == (cidr1.to_i(:network) | cidr1.to_i(:hostmask)) )
|
43
|
-
# cidr1 contains cidr2
|
44
|
-
comparasin = 1
|
45
|
-
|
46
|
-
elsif( (cidr2.to_i(:network) | cidr2.to_i(:hostmask)) == (cidr1.to_i(:network) | cidr2.to_i(: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.to_i(:network) < cidr2.to_i(:network))
|
68
|
-
gt_lt = -1
|
69
|
-
elsif (cidr1.to_i(:network) == cidr2.to_i(:network))
|
70
|
-
if (cidr1.to_i(:netmask) < cidr2.to_i(:netmask))
|
71
|
-
gt_lt = -1
|
72
|
-
elsif (cidr1.to_i(:netmask) == cidr2.to_i(: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.to_i(:network)
|
92
|
-
all_f = supernet.all_f
|
93
|
-
|
94
|
-
NetAddr.cidr_sort(list).each do |cidr|
|
95
|
-
network = cidr.to_i(:network)
|
96
|
-
bitstep = (all_f + 1) - cidr.to_i(:netmask)
|
97
|
-
|
98
|
-
if (network > expected) # missing space at beginning of supernet, so fill in the hole
|
99
|
-
num_ips_missing = network - expected
|
100
|
-
sub_list = cidr_make_subnets_from_base_and_ip_count(supernet,expected,num_ips_missing)
|
101
|
-
complete_list.concat(sub_list)
|
102
|
-
elsif (network < expected)
|
103
|
-
next
|
104
|
-
end
|
105
|
-
|
106
|
-
complete_list.push(cidr)
|
107
|
-
expected = network + bitstep
|
108
|
-
end
|
109
|
-
|
110
|
-
# if expected is not the next subnet, then we're missing subnets
|
111
|
-
# at the end of the cidr
|
112
|
-
next_sub = supernet.next_subnet(:Objectify => true).to_i(:network)
|
113
|
-
if (expected != next_sub)
|
114
|
-
num_ips_missing = next_sub - expected
|
115
|
-
sub_list = cidr_make_subnets_from_base_and_ip_count(supernet,expected,num_ips_missing)
|
116
|
-
complete_list.concat(sub_list)
|
117
|
-
end
|
118
|
-
|
119
|
-
return(complete_list)
|
120
|
-
end
|
121
|
-
module_function :cidr_fill_in
|
122
|
-
|
123
|
-
#==============================================================================#
|
124
|
-
# cidr_find_in_list()
|
125
|
-
#==============================================================================#
|
126
|
-
|
127
|
-
# evaluate cidr against list of cidrs.
|
128
|
-
#
|
129
|
-
# return entry from list if entry is supernet of cidr (first matching entry)
|
130
|
-
# return index # of entry if entry is a duplicate of cidr
|
131
|
-
# return nil if no match found
|
132
|
-
#
|
133
|
-
def cidr_find_in_list(cidr,list)
|
134
|
-
return(nil) if (list.length == 0)
|
135
|
-
|
136
|
-
match = nil
|
137
|
-
low = 0
|
138
|
-
high = list.length - 1
|
139
|
-
index = low + ( (high-low)/2 )
|
140
|
-
while ( low <= high)
|
141
|
-
cmp = cidr_gt_lt(cidr,list[index])
|
142
|
-
if ( cmp == -1 )
|
143
|
-
high = index - 1
|
144
|
-
|
145
|
-
elsif ( cmp == 1 )
|
146
|
-
if (cidr_compare(cidr,list[index]) == -1)
|
147
|
-
match = list[index]
|
148
|
-
break
|
149
|
-
end
|
150
|
-
low = index + 1
|
151
|
-
|
152
|
-
else
|
153
|
-
match = index
|
154
|
-
break
|
155
|
-
end
|
156
|
-
index = low + ( (high-low)/2 )
|
157
|
-
end
|
158
|
-
return(match)
|
159
|
-
end
|
160
|
-
module_function :cidr_find_in_list
|
161
|
-
|
162
|
-
#==============================================================================#
|
163
|
-
# cidr_make_subnets_from_base_and_ip_count()
|
164
|
-
#==============================================================================#
|
165
|
-
|
166
|
-
# Make CIDR addresses from a base addr and an number of ip's to encapsulate.
|
167
|
-
#
|
168
|
-
#===Arguments:
|
169
|
-
# * cidr
|
170
|
-
# * base ip as 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, desc=false)
|
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
|
-
if (desc)
|
224
|
-
list.each do |x|
|
225
|
-
if ( pivot.to_i(:network) < x.to_i(:network) )
|
226
|
-
less_list.push(x)
|
227
|
-
elsif ( pivot.to_i(:network) > x.to_i(:network) )
|
228
|
-
greater_list.push(x)
|
229
|
-
else
|
230
|
-
if ( pivot.to_i(:netmask) < x.to_i(:netmask) )
|
231
|
-
greater_list.push(x)
|
232
|
-
elsif ( pivot.to_i(:netmask) > x.to_i(:netmask) )
|
233
|
-
less_list.push(x)
|
234
|
-
else
|
235
|
-
equal_list.push(x)
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
239
|
-
else
|
240
|
-
list.each do |x|
|
241
|
-
gt_lt = cidr_gt_lt(pivot,x)
|
242
|
-
if (gt_lt == 1)
|
243
|
-
less_list.push(x)
|
244
|
-
elsif (gt_lt == -1)
|
245
|
-
greater_list.push(x)
|
246
|
-
else
|
247
|
-
equal_list.push(x)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
sorted_list.concat( cidr_sort(less_list, desc) )
|
253
|
-
sorted_list.concat(equal_list)
|
254
|
-
sorted_list.concat( cidr_sort(greater_list, desc) )
|
255
|
-
end
|
256
|
-
|
257
|
-
return(sorted_list)
|
258
|
-
end
|
259
|
-
module_function :cidr_sort
|
260
|
-
|
261
|
-
#==============================================================================#
|
262
|
-
# cidr_summarize()
|
263
|
-
#==============================================================================#
|
264
|
-
|
265
|
-
# given a list of NetAddr::CIDRs (of the same version) summarize them
|
266
|
-
#
|
267
|
-
# return a hash, with the key = summary address and val = array of original cidrs
|
268
|
-
#
|
269
|
-
def cidr_summarize(subnet_list)
|
270
|
-
all_f = subnet_list[0].all_f
|
271
|
-
version = subnet_list[0].version
|
272
|
-
subnet_list = cidr_sort(subnet_list)
|
273
|
-
|
274
|
-
# continue summarization attempts until sorted_list stops getting shorter
|
275
|
-
sorted_list = subnet_list.dup
|
276
|
-
sorted_list_len = sorted_list.length
|
277
|
-
while (1)
|
278
|
-
summarized_list = []
|
279
|
-
until (sorted_list.length == 0)
|
280
|
-
cidr = sorted_list.shift
|
281
|
-
network, netmask = cidr.to_i(:network), cidr.to_i(:netmask)
|
282
|
-
supermask = (netmask << 1) & all_f
|
283
|
-
supernet = supermask & network
|
284
|
-
|
285
|
-
if (network == supernet && sorted_list.length > 0)
|
286
|
-
# network is lower half of supernet, so see if we have the upper half
|
287
|
-
bitstep = (all_f + 1) - netmask
|
288
|
-
expected = network + bitstep
|
289
|
-
next_cidr = sorted_list.shift
|
290
|
-
next_network, next_netmask = next_cidr.to_i(:network), next_cidr.to_i(:netmask)
|
291
|
-
|
292
|
-
if ( (next_network == expected) && (next_netmask == netmask) )
|
293
|
-
# we do indeed have the upper half. store new supernet.
|
294
|
-
summarized_list.push( cidr_build(version,supernet,supermask) )
|
295
|
-
else
|
296
|
-
# we do not have the upper half. put next_cidr back into sorted_list
|
297
|
-
# and store only the original network
|
298
|
-
sorted_list.unshift(next_cidr)
|
299
|
-
summarized_list.push(cidr)
|
300
|
-
end
|
301
|
-
else
|
302
|
-
# network is upper half of supernet, so save original network only
|
303
|
-
summarized_list.push(cidr)
|
304
|
-
end
|
305
|
-
|
306
|
-
end
|
307
|
-
|
308
|
-
sorted_list = summarized_list.dup
|
309
|
-
break if (sorted_list.length == sorted_list_len)
|
310
|
-
sorted_list_len = sorted_list.length
|
311
|
-
end
|
312
|
-
|
313
|
-
# clean up summarized_list
|
314
|
-
unique_list = {}
|
315
|
-
summarized_list.reverse.each do |supernet|
|
316
|
-
next if ( unique_list.has_key?(supernet.desc) )
|
317
|
-
# remove duplicates
|
318
|
-
unique_list[supernet.desc] = supernet
|
319
|
-
|
320
|
-
# remove any summary blocks that are children of other summary blocks
|
321
|
-
index = 0
|
322
|
-
until (index >= summarized_list.length)
|
323
|
-
subnet = summarized_list[index]
|
324
|
-
if (subnet && cidr_compare(supernet,subnet) == 1 )
|
325
|
-
unique_list.delete(subnet.desc)
|
326
|
-
end
|
327
|
-
index += 1
|
328
|
-
end
|
329
|
-
end
|
330
|
-
summarized_list = unique_list.values
|
331
|
-
|
332
|
-
# map original blocks to their summaries
|
333
|
-
summarized_list.each do |supernet|
|
334
|
-
supernet.tag[:Subnets] = []
|
335
|
-
index = 0
|
336
|
-
until (index >= subnet_list.length)
|
337
|
-
subnet = subnet_list[index]
|
338
|
-
if (subnet && cidr_compare(supernet,subnet) == 1 )
|
339
|
-
subnet_list[index] = nil
|
340
|
-
supernet.tag[:Subnets].push(subnet)
|
341
|
-
end
|
342
|
-
index += 1
|
343
|
-
end
|
344
|
-
end
|
345
|
-
|
346
|
-
return( NetAddr.cidr_sort(summarized_list) )
|
347
|
-
end
|
348
|
-
module_function :cidr_summarize
|
349
|
-
|
350
|
-
#==============================================================================#
|
351
|
-
# cidr_supernets()
|
352
|
-
#==============================================================================#
|
353
|
-
|
354
|
-
# given a list of NetAddr::CIDRs (of the same version), return only the 'top level' blocks (i.e. blocks not
|
355
|
-
# contained by other blocks
|
356
|
-
|
357
|
-
def cidr_supernets(subnet_list)
|
358
|
-
summary_list = []
|
359
|
-
subnet_list = netmask_sort(subnet_list)
|
360
|
-
subnet_list.each do |child|
|
361
|
-
is_parent = true
|
362
|
-
summary_list.each do |parent|
|
363
|
-
if (NetAddr.cidr_compare(parent,child) == 1)
|
364
|
-
is_parent = false
|
365
|
-
parent.tag[:Subnets].push(child)
|
366
|
-
end
|
367
|
-
end
|
368
|
-
|
369
|
-
if (is_parent)
|
370
|
-
child.tag[:Subnets] = []
|
371
|
-
summary_list.push(child)
|
372
|
-
end
|
373
|
-
end
|
374
|
-
|
375
|
-
return(summary_list)
|
376
|
-
end
|
377
|
-
module_function :cidr_supernets
|
378
|
-
|
379
|
-
#==============================================================================#
|
380
|
-
# netmask_sort()
|
381
|
-
#==============================================================================#
|
382
|
-
|
383
|
-
# given a list of NetAddr::CIDRs, return them as a sorted (by netmask) list
|
384
|
-
#
|
385
|
-
def netmask_sort(list, desc=false)
|
386
|
-
# uses simple quicksort algorithm
|
387
|
-
sorted_list = []
|
388
|
-
if (list.length < 1)
|
389
|
-
sorted_list = list
|
390
|
-
else
|
391
|
-
less_list = []
|
392
|
-
greater_list = []
|
393
|
-
equal_list = []
|
394
|
-
pivot = list[rand(list.length)]
|
395
|
-
if (desc)
|
396
|
-
list.each do |x|
|
397
|
-
if ( pivot.to_i(:netmask) < x.to_i(:netmask) )
|
398
|
-
less_list.push(x)
|
399
|
-
elsif ( pivot.to_i(:netmask) > x.to_i(:netmask) )
|
400
|
-
greater_list.push(x)
|
401
|
-
else
|
402
|
-
if ( pivot.to_i(:network) < x.to_i(:network) )
|
403
|
-
greater_list.push(x)
|
404
|
-
elsif ( pivot.to_i(:network) > x.to_i(:network) )
|
405
|
-
less_list.push(x)
|
406
|
-
else
|
407
|
-
equal_list.push(x)
|
408
|
-
end
|
409
|
-
end
|
410
|
-
end
|
411
|
-
else
|
412
|
-
list.each do |x|
|
413
|
-
if ( pivot.to_i(:netmask) < x.to_i(:netmask) )
|
414
|
-
greater_list.push(x)
|
415
|
-
elsif ( pivot.to_i(:netmask) > x.to_i(:netmask) )
|
416
|
-
less_list.push(x)
|
417
|
-
else
|
418
|
-
if ( pivot.to_i(:network) < x.to_i(:network) )
|
419
|
-
greater_list.push(x)
|
420
|
-
elsif ( pivot.to_i(:network) > x.to_i(:network) )
|
421
|
-
less_list.push(x)
|
422
|
-
else
|
423
|
-
equal_list.push(x)
|
424
|
-
end
|
425
|
-
end
|
426
|
-
end
|
427
|
-
end
|
428
|
-
|
429
|
-
sorted_list.concat( netmask_sort(less_list, desc) )
|
430
|
-
sorted_list.concat(equal_list)
|
431
|
-
sorted_list.concat( netmask_sort(greater_list, desc) )
|
432
|
-
end
|
433
|
-
|
434
|
-
return(sorted_list)
|
435
|
-
end
|
436
|
-
module_function :netmask_sort
|
437
|
-
|
438
|
-
end # module NetAddr
|
439
|
-
|
440
|
-
__END__
|
data/lib/eui.rb
DELETED
@@ -1,463 +0,0 @@
|
|
1
|
-
=begin rdoc
|
2
|
-
Copyleft (c) 2006 Dustin Spinhirne
|
3
|
-
|
4
|
-
Licensed under the same terms as Ruby, No Warranty is provided.
|
5
|
-
=end
|
6
|
-
|
7
|
-
module NetAddr
|
8
|
-
|
9
|
-
#=EUI - Extended Unique Identifier
|
10
|
-
#
|
11
|
-
#A class & series of methods for creating and manipulating Extended Unique Identifier
|
12
|
-
#(EUI) addresses. Two types of address formats are supported EUI-48 and EUI-64. The
|
13
|
-
#most common use for this class will be to manipulate MAC addresses (which are essentially
|
14
|
-
#a type of EUI-48 address).
|
15
|
-
#
|
16
|
-
#EUI addresses are separated into two parts, the
|
17
|
-
#Organizationally Unique Identifier (OUI) and the Extended Identifier (EI). The OUI
|
18
|
-
#is assigned by the IEEE and is used to identify a particular hardware manufacturer.
|
19
|
-
#The EI is assigned by the hardware manufacturer as a per device unique address.
|
20
|
-
#
|
21
|
-
#Probably the most useful feature of this class, and thus the reason it was created,
|
22
|
-
#is to help automate certain address assignments within IP. For example, IPv6
|
23
|
-
#Link Local addresses use MAC addresses for IP auto-assignment and multicast MAC addresses
|
24
|
-
#are determined based on the multicast IP address.
|
25
|
-
#
|
26
|
-
class EUI
|
27
|
-
|
28
|
-
private_class_method :new
|
29
|
-
|
30
|
-
#==============================================================================#
|
31
|
-
# initialize()
|
32
|
-
#==============================================================================#
|
33
|
-
|
34
|
-
#===Synopsis
|
35
|
-
# This method performs absolutely no error checking, and is meant to be used only by
|
36
|
-
# other internal methods for the sake of the speedier creation of EUI objects.
|
37
|
-
# Please consider using #create unless you know what you are doing with 100% certainty.
|
38
|
-
#
|
39
|
-
# Example:
|
40
|
-
# NetAddr::EUI48.new('aabbccddeeff')
|
41
|
-
#
|
42
|
-
#===Arguments:
|
43
|
-
#* EUI as a String or Integer. Strings should contain no formatting characters.
|
44
|
-
#
|
45
|
-
def initialize(eui)
|
46
|
-
|
47
|
-
if (eui.kind_of?(Integer))
|
48
|
-
@eui_i = eui
|
49
|
-
@eui = eui.to_s(16)
|
50
|
-
if ( self.kind_of?(NetAddr::EUI48) )
|
51
|
-
@eui = '0' * (12 - @eui.length) << @eui if (@eui.length < 12)
|
52
|
-
else
|
53
|
-
@eui = '0' * (16 - @eui.length) << @eui if (@eui.length < 16)
|
54
|
-
end
|
55
|
-
|
56
|
-
elsif(eui.kind_of?(String))
|
57
|
-
@eui = eui
|
58
|
-
@eui_i = eui.to_i(16)
|
59
|
-
else
|
60
|
-
raise ArgumentError, "Expected String or Integer, but #{eui.class} provided."
|
61
|
-
end
|
62
|
-
|
63
|
-
# set ei & oui
|
64
|
-
if ( self.kind_of?(NetAddr::EUI48) )
|
65
|
-
@ei = @eui.slice(6..11)
|
66
|
-
else
|
67
|
-
@ei = @eui.slice(6..15)
|
68
|
-
end
|
69
|
-
|
70
|
-
@oui = @eui.slice(0..5)
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
#==============================================================================#
|
75
|
-
# create()
|
76
|
-
#==============================================================================#
|
77
|
-
|
78
|
-
#===Synopsis
|
79
|
-
#Create a new EUI48 or EUI64 object.
|
80
|
-
#
|
81
|
-
# Example:
|
82
|
-
# addr = NetAddr::EUI.create('aa-bb-cc-dd-ee-ff')
|
83
|
-
# addr = NetAddr::EUI.create('aa:bb:cc:dd:ee:ff')
|
84
|
-
# addr = NetAddr::EUI.create('aabb.ccdd.eeff')
|
85
|
-
# addr = NetAddr::EUI.create('aa-bb-cc-dd-ee-ff-00-01')
|
86
|
-
#
|
87
|
-
#===Arguments
|
88
|
-
#* eui = EUI as a String
|
89
|
-
#
|
90
|
-
#===Returns
|
91
|
-
#* EUI48 or EUI64 object
|
92
|
-
#
|
93
|
-
def EUI.create(eui)
|
94
|
-
if (!eui.kind_of? String)
|
95
|
-
raise ArgumentError, "Expected String, but #{eui.class} provided."
|
96
|
-
end
|
97
|
-
|
98
|
-
# validate
|
99
|
-
NetAddr.validate_eui(eui)
|
100
|
-
|
101
|
-
# remove formatting characters
|
102
|
-
eui.gsub!(/[\.\:\-]/, '')
|
103
|
-
|
104
|
-
if (eui.length == 12)
|
105
|
-
eui = NetAddr::EUI48.new(eui)
|
106
|
-
else
|
107
|
-
eui = NetAddr::EUI64.new(eui)
|
108
|
-
end
|
109
|
-
|
110
|
-
return(eui)
|
111
|
-
end
|
112
|
-
|
113
|
-
#==============================================================================#
|
114
|
-
# address()
|
115
|
-
#==============================================================================#
|
116
|
-
|
117
|
-
#===Synopsis
|
118
|
-
# Returns EUI address. The default address format is xxxx.xxxx.xxxx
|
119
|
-
#
|
120
|
-
# Example:
|
121
|
-
# addr = NetAddr::EUI.create('aabb.ccdd.eeff')
|
122
|
-
# addr.address(:Delimiter => '-') => "aa-bb-cc-dd-ee-ff"
|
123
|
-
# addr.address(:Delimiter => ':') => "aa:bb:cc:dd:ee:ff"
|
124
|
-
#
|
125
|
-
#===Arguments:
|
126
|
-
#* options = Hash with the following fields:
|
127
|
-
# :Delimiter -- delimitation character. valid values are (- : .)
|
128
|
-
#
|
129
|
-
#===Returns:
|
130
|
-
#* String
|
131
|
-
#
|
132
|
-
def address(options=nil)
|
133
|
-
known_args = [:Delimiter]
|
134
|
-
delimiter = '-'
|
135
|
-
|
136
|
-
if (options)
|
137
|
-
if (!options.kind_of? Hash)
|
138
|
-
raise ArgumentError, "Expected Hash, but #{options.class} provided."
|
139
|
-
end
|
140
|
-
NetAddr.validate_args(options.keys,known_args)
|
141
|
-
|
142
|
-
if (options.has_key?(:Delimiter))
|
143
|
-
delimiter = options[:Delimiter]
|
144
|
-
delimiter = '-' if (delimiter != ':' && delimiter != '.')
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
if (delimiter == '-' || delimiter == ':')
|
149
|
-
addr = octets.join(delimiter)
|
150
|
-
elsif (delimiter == '.')
|
151
|
-
toggle = 0
|
152
|
-
octets.each do |x|
|
153
|
-
if (!addr)
|
154
|
-
addr = x
|
155
|
-
toggle = 1
|
156
|
-
elsif (toggle == 0)
|
157
|
-
addr = addr << '.' << x
|
158
|
-
toggle = 1
|
159
|
-
else
|
160
|
-
addr = addr << x
|
161
|
-
toggle = 0
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
return(addr)
|
167
|
-
end
|
168
|
-
|
169
|
-
#==============================================================================#
|
170
|
-
# ei()
|
171
|
-
#==============================================================================#
|
172
|
-
|
173
|
-
#===Synopsis
|
174
|
-
#Returns Extended Identifier portion of an EUI address (the vendor assigned ID).
|
175
|
-
#The default address format is xx-xx-xx
|
176
|
-
#
|
177
|
-
# Example:
|
178
|
-
# addr = NetAddr::EUI.create('aabb.ccdd.eeff')
|
179
|
-
# addr.ei(:Delimiter => '-') => "dd-ee-ff"
|
180
|
-
#
|
181
|
-
#===Arguments:
|
182
|
-
#* options = Hash with the following fields:
|
183
|
-
# :Delimiter -- delimitation character. valid values are (-, and :)
|
184
|
-
#
|
185
|
-
#===Returns:
|
186
|
-
#* String
|
187
|
-
#
|
188
|
-
def ei(options=nil)
|
189
|
-
known_args = [:Delimiter]
|
190
|
-
delimiter = '-'
|
191
|
-
|
192
|
-
if (options)
|
193
|
-
if (!options.kind_of? Hash)
|
194
|
-
raise ArgumentError, "Expected Hash, but #{options.class} provided."
|
195
|
-
end
|
196
|
-
NetAddr.validate_args(options.keys,known_args)
|
197
|
-
|
198
|
-
if (options.has_key?(:Delimiter))
|
199
|
-
if (options[:Delimiter] == ':')
|
200
|
-
delimiter = options[:Delimiter]
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
if ( self.kind_of?(NetAddr::EUI48) )
|
206
|
-
ei = octets[3..5].join(delimiter)
|
207
|
-
else
|
208
|
-
ei = octets[3..7].join(delimiter)
|
209
|
-
end
|
210
|
-
|
211
|
-
return(ei)
|
212
|
-
end
|
213
|
-
|
214
|
-
#==============================================================================#
|
215
|
-
# link_local()
|
216
|
-
#==============================================================================#
|
217
|
-
|
218
|
-
#===Synopsis
|
219
|
-
# Provide an IPv6 Link Local address based on the current EUI address.
|
220
|
-
#
|
221
|
-
# Example:
|
222
|
-
# addr = NetAddr::EUI.create('aabb.ccdd.eeff')
|
223
|
-
# addr.link_local() => "fe80:0000:0000:0000:aabb:ccff:fedd:eeff"
|
224
|
-
#
|
225
|
-
#===Arguments:
|
226
|
-
#* options = Hash with the following fields:
|
227
|
-
# :Short -- if true, return IPv6 addresses in short-hand notation
|
228
|
-
# :Objectify -- if true, return CIDR objects
|
229
|
-
#
|
230
|
-
#===Returns:
|
231
|
-
#* CIDR address String or an NetAddr::CIDR object
|
232
|
-
#
|
233
|
-
def link_local(options=nil)
|
234
|
-
return( self.to_ipv6('fe80::/64', options) )
|
235
|
-
end
|
236
|
-
|
237
|
-
#==============================================================================#
|
238
|
-
# oui()
|
239
|
-
#==============================================================================#
|
240
|
-
|
241
|
-
#===Synopsis
|
242
|
-
#Returns Organizationally Unique Identifier portion of an EUI address (the vendor ID).
|
243
|
-
#The default address format is xx-xx-xx.
|
244
|
-
#
|
245
|
-
# Example:
|
246
|
-
# addr = NetAddr::EUI.create('aabb.ccdd.eeff')
|
247
|
-
# addr.oui(:Delimiter => '-') => "aa-bb-cc"
|
248
|
-
#
|
249
|
-
#===Arguments:
|
250
|
-
#* options = Hash with the following fields:
|
251
|
-
# :Delimiter -- delimitation character. valid values are (-, and :)
|
252
|
-
#
|
253
|
-
#===Returns:
|
254
|
-
#* String
|
255
|
-
#
|
256
|
-
def oui(options=nil)
|
257
|
-
known_args = [:Delimiter]
|
258
|
-
delimiter = '-'
|
259
|
-
|
260
|
-
if (options)
|
261
|
-
if (!options.kind_of? Hash)
|
262
|
-
raise ArgumentError, "Expected Hash, but #{options.class} provided."
|
263
|
-
end
|
264
|
-
NetAddr.validate_args(options.keys,known_args)
|
265
|
-
|
266
|
-
if (options.has_key?(:Delimiter))
|
267
|
-
if (options[:Delimiter] == ':')
|
268
|
-
delimiter = options[:Delimiter]
|
269
|
-
end
|
270
|
-
end
|
271
|
-
end
|
272
|
-
oui = octets[0..2].join(delimiter)
|
273
|
-
|
274
|
-
return(oui)
|
275
|
-
end
|
276
|
-
|
277
|
-
#==============================================================================#
|
278
|
-
# to_i()
|
279
|
-
#==============================================================================#
|
280
|
-
|
281
|
-
#===Synopsis
|
282
|
-
#Returns the EUI as an Integer.
|
283
|
-
#
|
284
|
-
# Example:
|
285
|
-
# addr = NetAddr::EUI.create('aabb.ccdd.eeff')
|
286
|
-
# addr.to_i => 187723572702975
|
287
|
-
#
|
288
|
-
#===Arguments:
|
289
|
-
#* none
|
290
|
-
#
|
291
|
-
#===Returns:
|
292
|
-
#* Integer
|
293
|
-
#
|
294
|
-
def to_i()
|
295
|
-
return(@eui_i)
|
296
|
-
end
|
297
|
-
|
298
|
-
#==============================================================================#
|
299
|
-
# to_ipv6
|
300
|
-
#==============================================================================#
|
301
|
-
|
302
|
-
#===Synopsis
|
303
|
-
# Given a valid IPv6 subnet, return an IPv6 address based on the current EUI.
|
304
|
-
#
|
305
|
-
# Example:
|
306
|
-
# addr = NetAddr::EUI.create('aabb.ccdd.eeff')
|
307
|
-
# addr.to_ipv6('3ffe::/64') => "3ffe:0000:0000:0000:a8bb:ccff:fedd:eeff"
|
308
|
-
#
|
309
|
-
#===Arguments:
|
310
|
-
#* options = Hash with the following fields:
|
311
|
-
# :Short -- if true, return IPv6 addresses in short-hand notation
|
312
|
-
# :Objectify -- if true, return CIDR objects
|
313
|
-
#
|
314
|
-
#===Returns:
|
315
|
-
#* IPv6 address String or an NetAddr::CIDRv6 object
|
316
|
-
#
|
317
|
-
def to_ipv6(cidr, options=nil)
|
318
|
-
known_args = [:Short, :Objectify]
|
319
|
-
objectify = false
|
320
|
-
short = false
|
321
|
-
|
322
|
-
if ( !cidr.kind_of?(NetAddr::CIDR) )
|
323
|
-
begin
|
324
|
-
cidr = NetAddr::CIDR.create(cidr)
|
325
|
-
rescue Exception => error
|
326
|
-
raise ArgumentError, "CIDR raised the following errors: #{error}"
|
327
|
-
end
|
328
|
-
elsif (cidr.kind_of?(NetAddr::CIDRv4) )
|
329
|
-
raise ArgumentError, "Expected CIDRv6, but #{cidr.class} provided."
|
330
|
-
end
|
331
|
-
|
332
|
-
if (cidr.bits > 64)
|
333
|
-
raise ValidationError, "Prefix length of provided CIDR must be /64 or less but was #{cidr.netmask}."
|
334
|
-
end
|
335
|
-
|
336
|
-
if (options)
|
337
|
-
if (!options.kind_of? Hash)
|
338
|
-
raise ArgumentError, "Expected Hash, but #{options.class} provided."
|
339
|
-
end
|
340
|
-
NetAddr.validate_args(options.keys,known_args)
|
341
|
-
|
342
|
-
if (options.has_key?(:Objectify) && options[:Objectify] == true)
|
343
|
-
objectify = true
|
344
|
-
end
|
345
|
-
|
346
|
-
if (options.has_key?(:Short) && options[:Short] == true)
|
347
|
-
short = true
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
|
-
# get integer equiv of addr. conver eui48 to eui64 if needed
|
352
|
-
if ( self.kind_of?(NetAddr::EUI48) )
|
353
|
-
eui_i = self.to_eui64.to_i
|
354
|
-
else
|
355
|
-
eui_i = self.to_i
|
356
|
-
end
|
357
|
-
|
358
|
-
# toggle u/l bit
|
359
|
-
eui_i = eui_i ^ 0x0200000000000000
|
360
|
-
|
361
|
-
# create ipv6 address
|
362
|
-
ipv6 = cidr.to_i | eui_i
|
363
|
-
|
364
|
-
if (!objectify)
|
365
|
-
ipv6 = NetAddr.i_to_ip(ipv6, :Version => 6)
|
366
|
-
ipv6 = NetAddr.shorten(ipv6) if (short)
|
367
|
-
else
|
368
|
-
ipv6 = NetAddr::CIDRv6.new(ipv6)
|
369
|
-
end
|
370
|
-
|
371
|
-
return(ipv6)
|
372
|
-
end
|
373
|
-
|
374
|
-
#==============================================================================#
|
375
|
-
# to_s()
|
376
|
-
#==============================================================================#
|
377
|
-
|
378
|
-
#===Synopsis
|
379
|
-
#Returns the EUI as an unformatted String.
|
380
|
-
#
|
381
|
-
# Example:
|
382
|
-
# addr = NetAddr::EUI.create('aabb.ccdd.eeff')
|
383
|
-
# addr.to_s => "aabbccddeeff"
|
384
|
-
#
|
385
|
-
#===Arguments:
|
386
|
-
#* none
|
387
|
-
#
|
388
|
-
#===Returns:
|
389
|
-
#* String
|
390
|
-
#
|
391
|
-
def to_s()
|
392
|
-
return(@eui)
|
393
|
-
end
|
394
|
-
|
395
|
-
private
|
396
|
-
|
397
|
-
#==============================================================================#
|
398
|
-
# octets()
|
399
|
-
#==============================================================================#
|
400
|
-
|
401
|
-
#Returns array with each element representing a single octet of the eui.
|
402
|
-
#
|
403
|
-
def octets()
|
404
|
-
return(@octets) if (@octets)
|
405
|
-
|
406
|
-
@octets = []
|
407
|
-
str = ''
|
408
|
-
@eui.each_byte do |chr|
|
409
|
-
str = str << chr
|
410
|
-
if (str.length == 2)
|
411
|
-
@octets.push(str)
|
412
|
-
str = ''
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
return(@octets)
|
417
|
-
end
|
418
|
-
|
419
|
-
end
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
# EUI-48 Address - Inherits all methods from NetAddr::EUI.
|
424
|
-
# Addresses of this class have a 24-bit OUI and a 24-bit EI.
|
425
|
-
class EUI48 < EUI
|
426
|
-
|
427
|
-
public_class_method :new
|
428
|
-
|
429
|
-
#==============================================================================#
|
430
|
-
# to_eui64()
|
431
|
-
#==============================================================================#
|
432
|
-
|
433
|
-
#===Synopsis
|
434
|
-
#Return an EUI64 address based on the current EUI48 address.
|
435
|
-
#
|
436
|
-
# Example:
|
437
|
-
# addr = NetAddr::EUI.create('aabb.ccdd.eeff')
|
438
|
-
# addr.to_eui64 => NetAddr::EUI64
|
439
|
-
#
|
440
|
-
#===Arguments:
|
441
|
-
#* none
|
442
|
-
#
|
443
|
-
#===Returns:
|
444
|
-
#* NetAddr::EUI64 object
|
445
|
-
#
|
446
|
-
def to_eui64()
|
447
|
-
eui = @oui + 'fffe' + @ei
|
448
|
-
return( NetAddr::EUI64.new(eui.to_i(16)) )
|
449
|
-
end
|
450
|
-
|
451
|
-
end
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
# EUI-64 Address - Inherits all methods from NetAddr::EUI.
|
456
|
-
# Addresses of this class have a 24-bit OUI and a 40-bit EI.
|
457
|
-
class EUI64 < EUI
|
458
|
-
public_class_method :new
|
459
|
-
end
|
460
|
-
|
461
|
-
|
462
|
-
end # module NetAddr
|
463
|
-
__END__
|