netaddr 1.5.1 → 2.0.3

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/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
-