netaddr 1.5.0 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
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__
data/lib/ip_math.rb DELETED
@@ -1,259 +0,0 @@
1
- module NetAddr
2
- private
3
-
4
-
5
- # IP MATH METHODS
6
-
7
- #==============================================================================#
8
- # binary_mirror()
9
- #==============================================================================#
10
-
11
- # given an integer and number of bits to consider, return its binary mirror
12
- #
13
- def binary_mirror(num, bit_count)
14
- mirror = 0
15
- bit_count.times do # make mirror image of num by capturning lsb and left-shifting it onto mirror
16
- mirror = mirror << 1
17
- lsb = num & 1
18
- num = num >> 1
19
- mirror = mirror | lsb
20
- end
21
- return(mirror)
22
- end
23
- module_function :binary_mirror
24
-
25
- #==============================================================================#
26
- # bits_to_mask()
27
- #==============================================================================#
28
-
29
- # convert a netmask (in bits) to an integer mask
30
- #
31
- def bits_to_mask(netmask,version)
32
- return(0) if (netmask == 0)
33
- all_f = 2**32-1
34
- all_f = 2**128-1 if (version == 6)
35
- return( all_f ^ (all_f >> netmask) )
36
- end
37
- module_function :bits_to_mask
38
-
39
- #==============================================================================#
40
- # detect_ip_version()
41
- #==============================================================================#
42
-
43
- # determine the ip version from ip address string.
44
- #
45
- # return 4, 6, or nil
46
- #
47
- def detect_ip_version(ip)
48
- version = nil
49
- if ( ip =~ /\./ && ip !~ /:/ )
50
- version = 4
51
- elsif (ip =~ /:/)
52
- version = 6
53
- else
54
- raise ValidationError, "Could not auto-detect IP version for '#{ip}'."
55
- end
56
- return(version)
57
- end
58
- module_function :detect_ip_version
59
-
60
- #==============================================================================#
61
- # ip_count_to_size()
62
- #==============================================================================#
63
-
64
- # given an ip count, determine the most appropriate mask (in bits)
65
- #
66
- def ip_count_to_size(ipcount,version,extended=false)
67
- address_len = 32
68
- address_len = 128 if (version == 6 )
69
-
70
- if (ipcount > 2**address_len)
71
- raise BoundaryError, "Required IP count exceeds number of IP addresses available " +
72
- "for IPv#{version}."
73
- end
74
-
75
- bits_needed = 0
76
- until (2**bits_needed >= ipcount)
77
- bits_needed += 1
78
- end
79
- subnet_bits = address_len - bits_needed
80
-
81
- return( ip_int_to_str(bits_to_mask(subnet_bits, 4), 4) ) if (extended && version == 4)
82
- return(subnet_bits)
83
- end
84
- module_function :ip_count_to_size
85
-
86
- #==============================================================================#
87
- # ip_int_to_str()
88
- #==============================================================================#
89
-
90
- # unpack an int into an ip address string
91
- #
92
- def ip_int_to_str(ip_int, version, ipv4_mapped=nil)
93
- ip = nil
94
- version = 4 if (!version && ip_int < 2**32)
95
- if (version == 4)
96
- octets = []
97
- 4.times do
98
- octet = ip_int & 0xFF
99
- octets.unshift(octet.to_s)
100
- ip_int = ip_int >> 8
101
- end
102
- ip = octets.join('.')
103
- else
104
- fields = []
105
- if (!ipv4_mapped)
106
- loop_count = 8
107
- else
108
- loop_count = 6
109
- ipv4_int = ip_int & 0xffffffff
110
- ipv4_addr = ip_int_to_str(ipv4_int, 4)
111
- fields.unshift(ipv4_addr)
112
- ip_int = ip_int >> 32
113
- end
114
-
115
- loop_count.times do
116
- octet = ip_int & 0xFFFF
117
- octet = octet.to_s(16)
118
- ip_int = ip_int >> 16
119
-
120
- # if octet < 4 characters, then pad with 0's
121
- (4 - octet.length).times do
122
- octet = '0' << octet
123
- end
124
- fields.unshift(octet)
125
- end
126
- ip = fields.join(':')
127
- end
128
- return(ip)
129
- end
130
- module_function :ip_int_to_str
131
-
132
- #==============================================================================#
133
- # ip_str_to_int()
134
- #==============================================================================#
135
-
136
- # convert an ip string into an int
137
- #
138
- def ip_str_to_int(ip,version)
139
- ip_int = 0
140
- if ( version == 4)
141
- octets = ip.split('.')
142
- (0..3).each do |x|
143
- octet = octets.pop.to_i
144
- octet = octet << 8*x
145
- ip_int = ip_int | octet
146
- end
147
-
148
- else
149
- # if ipv4-mapped ipv6 addr
150
- if (ip =~ /\./)
151
- dotted_dec = true
152
- end
153
-
154
- # split up by ':'
155
- fields = []
156
- if (ip =~ /::/)
157
- shrthnd = ip.split( /::/ )
158
- if (shrthnd.length == 0)
159
- return(0)
160
- else
161
- first_half = shrthnd[0].split( /:/ ) if (shrthnd[0])
162
- sec_half = shrthnd[1].split( /:/ ) if (shrthnd[1])
163
- first_half = [] if (!first_half)
164
- sec_half = [] if (!sec_half)
165
- end
166
- missing_fields = 8 - first_half.length - sec_half.length
167
- missing_fields -= 1 if dotted_dec
168
- fields = fields.concat(first_half)
169
- missing_fields.times {fields.push('0')}
170
- fields = fields.concat(sec_half)
171
-
172
- else
173
- fields = ip.split(':')
174
- end
175
-
176
- if (dotted_dec)
177
- ipv4_addr = fields.pop
178
- ipv4_int = NetAddr.ip_to_i(ipv4_addr, :Version => 4)
179
- octets = []
180
- 2.times do
181
- octet = ipv4_int & 0xFFFF
182
- octets.unshift(octet.to_s(16))
183
- ipv4_int = ipv4_int >> 16
184
- end
185
- fields.concat(octets)
186
- end
187
-
188
- # pack
189
- (0..7).each do |x|
190
- field = fields.pop.to_i(16)
191
- field = field << 16*x
192
- ip_int = ip_int | field
193
- end
194
-
195
- end
196
- return(ip_int)
197
- end
198
- module_function :ip_str_to_int
199
-
200
- #==============================================================================#
201
- # mask_to_bits()
202
- #==============================================================================#
203
-
204
- # convert integer into a cidr formatted netmask (bits)
205
- #
206
- def mask_to_bits(netmask_int)
207
- return(netmask_int) if (netmask_int == 0)
208
-
209
- mask = nil
210
- if (netmask_int < 2**32)
211
- mask = 32
212
- validate_netmask_int(netmask_int, 4, true)
213
- else
214
- mask = 128
215
- validate_netmask_int(netmask_int, 6, true)
216
- end
217
-
218
- mask.times do
219
- if ( (netmask_int & 1) == 1)
220
- break
221
- end
222
- netmask_int = netmask_int >> 1
223
- mask = mask - 1
224
- end
225
- return(mask)
226
- end
227
- module_function :mask_to_bits
228
-
229
- #==============================================================================#
230
- # netmask_str_to_int()
231
- #==============================================================================#
232
-
233
- # convert string into integer mask
234
- #
235
- def netmask_str_to_int(netmask,version)
236
- netmask_int = nil
237
- all_f = 2**32-1
238
- all_f = 2**128-1 if (version == 6)
239
- if(netmask =~ /\./)
240
- netmask_int = NetAddr.ip_to_i(netmask)
241
- else
242
- # remove '/' if present
243
- if (netmask =~ /^\// )
244
- netmask[0] = " "
245
- netmask.lstrip!
246
- end
247
- netmask = netmask.to_i
248
- netmask_int = all_f ^ (all_f >> netmask)
249
- end
250
- return(netmask_int)
251
- end
252
- module_function :netmask_str_to_int
253
-
254
-
255
-
256
- end # module NetAddr
257
-
258
- __END__
259
-