netaddr 1.5.3 → 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.

data/lib/eui.rb DELETED
@@ -1,402 +0,0 @@
1
- module NetAddr
2
-
3
- #=EUI - Extended Unique Identifier
4
- #
5
- #A class & series of methods for creating and manipulating Extended Unique Identifier
6
- #(EUI) addresses. Two types of address formats are supported EUI-48 and EUI-64. The
7
- #most common use for this class will be to manipulate MAC addresses (which are essentially
8
- #a type of EUI-48 address).
9
- #
10
- #EUI addresses are separated into two parts, the
11
- #Organizationally Unique Identifier (OUI) and the Extended Identifier (EI). The OUI
12
- #is assigned by the IEEE and is used to identify a particular hardware manufacturer.
13
- #The EI is assigned by the hardware manufacturer as a per device unique address.
14
- #
15
- #Probably the most useful feature of this class, and thus the reason it was created,
16
- #is to help automate certain address assignments within IP. For example, IPv6
17
- #Link Local addresses use MAC addresses for IP auto-assignment and multicast MAC addresses
18
- #are determined based on the multicast IP address.
19
- #
20
- class EUI
21
-
22
- private_class_method :new
23
-
24
- #===Synopsis
25
- # This method performs absolutely no error checking, and is meant to be used only by
26
- # other internal methods for the sake of the speedier creation of EUI objects.
27
- # Please consider using #create unless you know what you are doing with 100% certainty.
28
- #
29
- # Example:
30
- # NetAddr::EUI48.new('aabbccddeeff')
31
- #
32
- #===Arguments:
33
- #* EUI as a String or Integer. Strings should contain no formatting characters.
34
- #
35
- def initialize(eui)
36
-
37
- if (eui.kind_of?(Integer))
38
- @eui_i = eui
39
- @eui = eui.to_s(16)
40
- if ( self.kind_of?(NetAddr::EUI48) )
41
- @eui = '0' * (12 - @eui.length) << @eui if (@eui.length < 12)
42
- else
43
- @eui = '0' * (16 - @eui.length) << @eui if (@eui.length < 16)
44
- end
45
-
46
- elsif(eui.kind_of?(String))
47
- @eui = eui
48
- @eui_i = eui.to_i(16)
49
- else
50
- raise ArgumentError, "Expected String or Integer, but #{eui.class} provided."
51
- end
52
-
53
- # set ei & oui
54
- if ( self.kind_of?(NetAddr::EUI48) )
55
- @ei = @eui.slice(6..11)
56
- else
57
- @ei = @eui.slice(6..15)
58
- end
59
-
60
- @oui = @eui.slice(0..5)
61
-
62
- end
63
-
64
- #===Synopsis
65
- #Create a new EUI48 or EUI64 object.
66
- #
67
- # Example:
68
- # addr = NetAddr::EUI.create('aa-bb-cc-dd-ee-ff')
69
- # addr = NetAddr::EUI.create('aa:bb:cc:dd:ee:ff')
70
- # addr = NetAddr::EUI.create('aabb.ccdd.eeff')
71
- # addr = NetAddr::EUI.create('aa-bb-cc-dd-ee-ff-00-01')
72
- #
73
- #===Arguments
74
- #* eui = EUI as a String
75
- #
76
- #===Returns
77
- #* EUI48 or EUI64 object
78
- #
79
- def EUI.create(eui)
80
- if (!eui.kind_of? String)
81
- raise ArgumentError, "Expected String, but #{eui.class} provided."
82
- end
83
-
84
- # create local copy & validate
85
- eui = eui.dup
86
- NetAddr.validate_eui(eui)
87
-
88
- # remove formatting characters
89
- eui.gsub!(/[\.\:\-]/, '')
90
-
91
- if (eui.length == 12)
92
- eui = NetAddr::EUI48.new(eui)
93
- else
94
- eui = NetAddr::EUI64.new(eui)
95
- end
96
-
97
- return(eui)
98
- end
99
-
100
- #===Synopsis
101
- # Returns EUI address. The default address format is xxxx.xxxx.xxxx
102
- #
103
- # Example:
104
- # addr = NetAddr::EUI.create('aabb.ccdd.eeff')
105
- # addr.address(:Delimiter => '-') => "aa-bb-cc-dd-ee-ff"
106
- # addr.address(:Delimiter => ':') => "aa:bb:cc:dd:ee:ff"
107
- #
108
- #===Arguments:
109
- #* options = Hash with the following fields:
110
- # :Delimiter -- delimitation character. valid values are (- : .)
111
- #
112
- #===Returns:
113
- #* String
114
- #
115
- def address(options=nil)
116
- known_args = [:Delimiter]
117
- delimiter = '-'
118
-
119
- if (options)
120
- if (!options.kind_of? Hash)
121
- raise ArgumentError, "Expected Hash, but #{options.class} provided."
122
- end
123
- NetAddr.validate_args(options.keys,known_args)
124
-
125
- if (options.has_key?(:Delimiter))
126
- delimiter = options[:Delimiter]
127
- delimiter = '-' if (delimiter != ':' && delimiter != '.')
128
- end
129
- end
130
-
131
- if (delimiter == '-' || delimiter == ':')
132
- addr = octets.join(delimiter)
133
- elsif (delimiter == '.')
134
- addr = octets.each_slice(2).to_a.map(&:join).join('.')
135
- end
136
-
137
- return(addr)
138
- end
139
-
140
- #===Synopsis
141
- #Returns Extended Identifier portion of an EUI address (the vendor assigned ID).
142
- #The default address format is xx-xx-xx
143
- #
144
- # Example:
145
- # addr = NetAddr::EUI.create('aabb.ccdd.eeff')
146
- # addr.ei(:Delimiter => '-') => "dd-ee-ff"
147
- #
148
- #===Arguments:
149
- #* options = Hash with the following fields:
150
- # :Delimiter -- delimitation character. valid values are (-, and :)
151
- #
152
- #===Returns:
153
- #* String
154
- #
155
- def ei(options=nil)
156
- known_args = [:Delimiter]
157
- delimiter = '-'
158
-
159
- if (options)
160
- if (!options.kind_of? Hash)
161
- raise ArgumentError, "Expected Hash, but #{options.class} provided."
162
- end
163
- NetAddr.validate_args(options.keys,known_args)
164
-
165
- if (options.has_key?(:Delimiter))
166
- if (options[:Delimiter] == ':')
167
- delimiter = options[:Delimiter]
168
- end
169
- end
170
- end
171
-
172
- if ( self.kind_of?(NetAddr::EUI48) )
173
- ei = octets[3..5].join(delimiter)
174
- else
175
- ei = octets[3..7].join(delimiter)
176
- end
177
-
178
- return(ei)
179
- end
180
-
181
- #===Synopsis
182
- # Provide an IPv6 Link Local address based on the current EUI address.
183
- #
184
- # Example:
185
- # addr = NetAddr::EUI.create('aabb.ccdd.eeff')
186
- # addr.link_local() => "fe80:0000:0000:0000:aabb:ccff:fedd:eeff"
187
- #
188
- #===Arguments:
189
- #* options = Hash with the following fields:
190
- # :Short -- if true, return IPv6 addresses in short-hand notation
191
- # :Objectify -- if true, return CIDR objects
192
- #
193
- #===Returns:
194
- #* CIDR address String or an NetAddr::CIDR object
195
- #
196
- def link_local(options=nil)
197
- return( self.to_ipv6('fe80::/64', options) )
198
- end
199
-
200
- #===Synopsis
201
- #Returns Organizationally Unique Identifier portion of an EUI address (the vendor ID).
202
- #The default address format is xx-xx-xx.
203
- #
204
- # Example:
205
- # addr = NetAddr::EUI.create('aabb.ccdd.eeff')
206
- # addr.oui(:Delimiter => '-') => "aa-bb-cc"
207
- #
208
- #===Arguments:
209
- #* options = Hash with the following fields:
210
- # :Delimiter -- delimitation character. valid values are (-, and :)
211
- #
212
- #===Returns:
213
- #* String
214
- #
215
- def oui(options=nil)
216
- known_args = [:Delimiter]
217
- delimiter = '-'
218
-
219
- if (options)
220
- if (!options.kind_of? Hash)
221
- raise ArgumentError, "Expected Hash, but #{options.class} provided."
222
- end
223
- NetAddr.validate_args(options.keys,known_args)
224
-
225
- if (options.has_key?(:Delimiter))
226
- if (options[:Delimiter] == ':')
227
- delimiter = options[:Delimiter]
228
- end
229
- end
230
- end
231
- oui = octets[0..2].join(delimiter)
232
-
233
- return(oui)
234
- end
235
-
236
- #===Synopsis
237
- #Returns the EUI as an Integer.
238
- #
239
- # Example:
240
- # addr = NetAddr::EUI.create('aabb.ccdd.eeff')
241
- # addr.to_i => 187723572702975
242
- #
243
- #===Arguments:
244
- #* none
245
- #
246
- #===Returns:
247
- #* Integer
248
- #
249
- def to_i()
250
- return(@eui_i)
251
- end
252
-
253
- #===Synopsis
254
- # Given a valid IPv6 subnet, return an IPv6 address based on the current EUI.
255
- #
256
- # Example:
257
- # addr = NetAddr::EUI.create('aabb.ccdd.eeff')
258
- # addr.to_ipv6('3ffe::/64') => "3ffe:0000:0000:0000:a8bb:ccff:fedd:eeff"
259
- #
260
- #===Arguments:
261
- #* options = Hash with the following fields:
262
- # :Short -- if true, return IPv6 addresses in short-hand notation
263
- # :Objectify -- if true, return CIDR objects
264
- #
265
- #===Returns:
266
- #* IPv6 address String or an NetAddr::CIDRv6 object
267
- #
268
- def to_ipv6(cidr, options=nil)
269
- known_args = [:Short, :Objectify]
270
- objectify = false
271
- short = false
272
-
273
- if ( !cidr.kind_of?(NetAddr::CIDR) )
274
- begin
275
- cidr = NetAddr::CIDR.create(cidr)
276
- rescue Exception => error
277
- raise ArgumentError, "CIDR raised the following errors: #{error}"
278
- end
279
- elsif (cidr.kind_of?(NetAddr::CIDRv4) )
280
- raise ArgumentError, "Expected CIDRv6, but #{cidr.class} provided."
281
- end
282
-
283
- if (cidr.bits > 64)
284
- raise ValidationError, "Prefix length of provided CIDR must be /64 or less but was #{cidr.netmask}."
285
- end
286
-
287
- if (options)
288
- if (!options.kind_of? Hash)
289
- raise ArgumentError, "Expected Hash, but #{options.class} provided."
290
- end
291
- NetAddr.validate_args(options.keys,known_args)
292
-
293
- if (options.has_key?(:Objectify) && options[:Objectify] == true)
294
- objectify = true
295
- end
296
-
297
- if (options.has_key?(:Short) && options[:Short] == true)
298
- short = true
299
- end
300
- end
301
-
302
- # get integer equiv of addr. conver eui48 to eui64 if needed
303
- if ( self.kind_of?(NetAddr::EUI48) )
304
- eui_i = self.to_eui64.to_i
305
- else
306
- eui_i = self.to_i
307
- end
308
-
309
- # toggle u/l bit
310
- eui_i = eui_i ^ 0x0200000000000000
311
-
312
- # create ipv6 address
313
- ipv6 = cidr.to_i | eui_i
314
-
315
- if (!objectify)
316
- ipv6 = NetAddr.i_to_ip(ipv6, :Version => 6)
317
- ipv6 = NetAddr.shorten(ipv6) if (short)
318
- else
319
- ipv6 = NetAddr::CIDRv6.new(ipv6)
320
- end
321
-
322
- return(ipv6)
323
- end
324
-
325
- #===Synopsis
326
- #Returns the EUI as an unformatted String.
327
- #
328
- # Example:
329
- # addr = NetAddr::EUI.create('aabb.ccdd.eeff')
330
- # addr.to_s => "aabbccddeeff"
331
- #
332
- #===Arguments:
333
- #* none
334
- #
335
- #===Returns:
336
- #* String
337
- #
338
- def to_s()
339
- return(@eui)
340
- end
341
-
342
- private
343
-
344
- #Returns array with each element representing a single octet of the eui.
345
- #
346
- def octets()
347
- return(@octets) if (@octets)
348
-
349
- @octets = []
350
- str = ''
351
- @eui.each_byte do |chr|
352
- str = str << chr
353
- if (str.length == 2)
354
- @octets.push(str)
355
- str = ''
356
- end
357
- end
358
-
359
- return(@octets)
360
- end
361
-
362
- end
363
-
364
-
365
-
366
- # EUI-48 Address - Inherits all methods from NetAddr::EUI.
367
- # Addresses of this class have a 24-bit OUI and a 24-bit EI.
368
- class EUI48 < EUI
369
-
370
- public_class_method :new
371
-
372
- #===Synopsis
373
- #Return an EUI64 address based on the current EUI48 address.
374
- #
375
- # Example:
376
- # addr = NetAddr::EUI.create('aabb.ccdd.eeff')
377
- # addr.to_eui64 => NetAddr::EUI64
378
- #
379
- #===Arguments:
380
- #* none
381
- #
382
- #===Returns:
383
- #* NetAddr::EUI64 object
384
- #
385
- def to_eui64()
386
- eui = @oui + 'fffe' + @ei
387
- return( NetAddr::EUI64.new(eui.to_i(16)) )
388
- end
389
-
390
- end
391
-
392
-
393
-
394
- # EUI-64 Address - Inherits all methods from NetAddr::EUI.
395
- # Addresses of this class have a 24-bit OUI and a 40-bit EI.
396
- class EUI64 < EUI
397
- public_class_method :new
398
- end
399
-
400
-
401
- end # module NetAddr
402
- __END__
data/lib/ip_math.rb DELETED
@@ -1,227 +0,0 @@
1
- module NetAddr
2
- private
3
-
4
-
5
- # IP MATH METHODS
6
-
7
- # given an integer and number of bits to consider, return its binary mirror
8
- #
9
- def binary_mirror(num, bit_count)
10
- mirror = 0
11
- bit_count.times do # make mirror image of num by capturning lsb and left-shifting it onto mirror
12
- mirror = mirror << 1
13
- lsb = num & 1
14
- num = num >> 1
15
- mirror = mirror | lsb
16
- end
17
- return(mirror)
18
- end
19
- module_function :binary_mirror
20
-
21
- # convert a netmask (in bits) to an integer mask
22
- #
23
- def bits_to_mask(netmask,version)
24
- return(0) if (netmask == 0)
25
- all_f = 2**32-1
26
- all_f = 2**128-1 if (version == 6)
27
- return( all_f ^ (all_f >> netmask) )
28
- end
29
- module_function :bits_to_mask
30
-
31
- # determine the ip version from ip address string.
32
- #
33
- # return 4, 6, or nil
34
- #
35
- def detect_ip_version(ip)
36
- version = nil
37
- if ( ip =~ /\./ && ip !~ /:/ )
38
- version = 4
39
- elsif (ip =~ /:/)
40
- version = 6
41
- else
42
- raise ValidationError, "Could not auto-detect IP version for '#{ip}'."
43
- end
44
- return(version)
45
- end
46
- module_function :detect_ip_version
47
-
48
- # given an ip count, determine the most appropriate mask (in bits)
49
- #
50
- def ip_count_to_size(ipcount,version,extended=false)
51
- address_len = 32
52
- address_len = 128 if (version == 6 )
53
-
54
- if (ipcount > 2**address_len)
55
- raise BoundaryError, "Required IP count exceeds number of IP addresses available " +
56
- "for IPv#{version}."
57
- end
58
-
59
- bits_needed = 0
60
- until (2**bits_needed >= ipcount)
61
- bits_needed += 1
62
- end
63
- subnet_bits = address_len - bits_needed
64
-
65
- return( ip_int_to_str(bits_to_mask(subnet_bits, 4), 4) ) if (extended && version == 4)
66
- return(subnet_bits)
67
- end
68
- module_function :ip_count_to_size
69
-
70
- # unpack an int into an ip address string
71
- #
72
- def ip_int_to_str(ip_int, version, ipv4_mapped=nil)
73
- ip = nil
74
- version = 4 if (!version && ip_int < 2**32)
75
- if (version == 4)
76
- octets = []
77
- 4.times do
78
- octet = ip_int & 0xFF
79
- octets.unshift(octet.to_s)
80
- ip_int = ip_int >> 8
81
- end
82
- ip = octets.join('.')
83
- else
84
- fields = []
85
- if (!ipv4_mapped)
86
- loop_count = 8
87
- else
88
- loop_count = 6
89
- ipv4_int = ip_int & 0xffffffff
90
- ipv4_addr = ip_int_to_str(ipv4_int, 4)
91
- fields.unshift(ipv4_addr)
92
- ip_int = ip_int >> 32
93
- end
94
-
95
- loop_count.times do
96
- octet = ip_int & 0xFFFF
97
- octet = octet.to_s(16)
98
- ip_int = ip_int >> 16
99
-
100
- # if octet < 4 characters, then pad with 0's
101
- (4 - octet.length).times do
102
- octet = '0' << octet
103
- end
104
- fields.unshift(octet)
105
- end
106
- ip = fields.join(':')
107
- end
108
- return(ip)
109
- end
110
- module_function :ip_int_to_str
111
-
112
- # convert an ip string into an int
113
- #
114
- def ip_str_to_int(ip,version)
115
- ip_int = 0
116
- if ( version == 4)
117
- octets = ip.split('.')
118
- (0..3).each do |x|
119
- octet = octets.pop.to_i
120
- octet = octet << 8*x
121
- ip_int = ip_int | octet
122
- end
123
-
124
- else
125
- # if ipv4-mapped ipv6 addr
126
- if (ip =~ /\./)
127
- dotted_dec = true
128
- end
129
-
130
- # split up by ':'
131
- fields = []
132
- if (ip =~ /::/)
133
- shrthnd = ip.split( /::/ )
134
- if (shrthnd.length == 0)
135
- return(0)
136
- else
137
- first_half = shrthnd[0].split( /:/ ) if (shrthnd[0])
138
- sec_half = shrthnd[1].split( /:/ ) if (shrthnd[1])
139
- first_half = [] if (!first_half)
140
- sec_half = [] if (!sec_half)
141
- end
142
- missing_fields = 8 - first_half.length - sec_half.length
143
- missing_fields -= 1 if dotted_dec
144
- fields = fields.concat(first_half)
145
- missing_fields.times {fields.push('0')}
146
- fields = fields.concat(sec_half)
147
-
148
- else
149
- fields = ip.split(':')
150
- end
151
-
152
- if (dotted_dec)
153
- ipv4_addr = fields.pop
154
- ipv4_int = NetAddr.ip_to_i(ipv4_addr, :Version => 4)
155
- octets = []
156
- 2.times do
157
- octet = ipv4_int & 0xFFFF
158
- octets.unshift(octet.to_s(16))
159
- ipv4_int = ipv4_int >> 16
160
- end
161
- fields.concat(octets)
162
- end
163
-
164
- # pack
165
- (0..7).each do |x|
166
- field = fields.pop.to_i(16)
167
- field = field << 16*x
168
- ip_int = ip_int | field
169
- end
170
-
171
- end
172
- return(ip_int)
173
- end
174
- module_function :ip_str_to_int
175
-
176
- # convert integer into a cidr formatted netmask (bits)
177
- #
178
- def mask_to_bits(netmask_int)
179
- return(netmask_int) if (netmask_int == 0)
180
-
181
- mask = nil
182
- if (netmask_int < 2**32)
183
- mask = 32
184
- validate_netmask_int(netmask_int, 4, true)
185
- else
186
- mask = 128
187
- validate_netmask_int(netmask_int, 6, true)
188
- end
189
-
190
- mask.times do
191
- if ( (netmask_int & 1) == 1)
192
- break
193
- end
194
- netmask_int = netmask_int >> 1
195
- mask = mask - 1
196
- end
197
- return(mask)
198
- end
199
- module_function :mask_to_bits
200
-
201
- # convert string into integer mask
202
- #
203
- def netmask_str_to_int(netmask,version)
204
- netmask_int = nil
205
- all_f = 2**32-1
206
- all_f = 2**128-1 if (version == 6)
207
- if(netmask =~ /\./)
208
- netmask_int = NetAddr.ip_to_i(netmask)
209
- else
210
- # remove '/' if present
211
- if (netmask =~ /^\// )
212
- netmask[0] = " "
213
- netmask.lstrip!
214
- end
215
- netmask = netmask.to_i
216
- netmask_int = all_f ^ (all_f >> netmask)
217
- end
218
- return(netmask_int)
219
- end
220
- module_function :netmask_str_to_int
221
-
222
-
223
-
224
- end # module NetAddr
225
-
226
- __END__
227
-