Class: NetAddr::EUI

Inherits:
Object
  • Object
show all
Defined in:
lib/eui.rb

Overview

EUI - Extended Unique Identifier

A class & series of methods for creating and manipulating Extended Unique Identifier (EUI) addresses. Two types of address formats are supported EUI-48 and EUI-64. The most common use for this class will be to manipulate MAC addresses (which are essentially a type of EUI-48 address).

EUI addresses are separated into two parts, the Organizationally Unique Identifier (OUI) and the Extended Identifier (EI). The OUI is assigned by the IEEE and is used to identify a particular hardware manufacturer. The EI is assigned by the hardware manufacturer as a per device unique address.

Probably the most useful feature of this class, and thus the reason it was created, is to help automate certain address assignments within IP. For example, IPv6 Link Local addresses use MAC addresses for IP auto-assignment and multicast MAC addresses are determined based on the multicast IP address.

Direct Known Subclasses

EUI48, EUI64

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(eui) ⇒ EUI

Synopsis

This method performs absolutely no error checking, and is meant to be used only by other internal methods for the sake of the speedier creation of EUI objects. Please consider using #create unless you know what you are doing with 100% certainty.

Example: NetAddr::EUI48.new(‘aabbccddeeff’)

Arguments:

  • EUI as a String or Integer. Strings should contain no formatting characters.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/eui.rb', line 45

def initialize(eui)

    if (eui.kind_of?(Integer))
        @eui_i = eui
        @eui = eui.to_s(16)
        if ( self.kind_of?(NetAddr::EUI48) )
            @eui = '0' * (12 - @eui.length) << @eui if (@eui.length < 12)
        else
            @eui = '0' * (16 - @eui.length) << @eui if (@eui.length < 16)
        end

    elsif(eui.kind_of?(String))
        @eui = eui
        @eui_i = eui.to_i(16)
    else
        raise ArgumentError, "Expected String or Integer, but #{eui.class} provided."
    end

    # set ei & oui
    if ( self.kind_of?(NetAddr::EUI48) )
        @ei = @eui.slice(6..11)
    else
        @ei = @eui.slice(6..15)
    end

    @oui = @eui.slice(0..5)

end

Class Method Details

.create(eui) ⇒ Object

Synopsis

Create a new EUI48 or EUI64 object.

Example: addr = NetAddr::EUI.create(‘aa-bb-cc-dd-ee-ff’) addr = NetAddr::EUI.create(‘aa:bb:cc:dd:ee:ff’) addr = NetAddr::EUI.create(‘aabb.ccdd.eeff’) addr = NetAddr::EUI.create(‘aa-bb-cc-dd-ee-ff-00-01’)

Arguments

  • eui = EUI as a String

Returns

  • EUI48 or EUI64 object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/eui.rb', line 93

def EUI.create(eui)
    if (!eui.kind_of? String)
        raise ArgumentError, "Expected String, but #{eui.class} provided."
    end

    # validate
    NetAddr.validate_eui(eui)

    # remove formatting characters
    eui.gsub!(/[\.\:\-]/, '')

    if (eui.length == 12)
        eui = NetAddr::EUI48.new(eui)
    else
        eui = NetAddr::EUI64.new(eui)
    end

    return(eui)
end

Instance Method Details

#address(options = nil) ⇒ Object

Synopsis

Returns EUI address. The default address format is xxxx.xxxx.xxxx

Example: addr = NetAddr::EUI.create(‘aabb.ccdd.eeff’) addr.address(:Delimiter => ‘-’) => “aa-bb-cc-dd-ee-ff” addr.address(:Delimiter => ‘:’) => “aa:bb:cc:dd:ee:ff”

Arguments:

  • options = Hash with the following fields:

    :Delimiter -- delimitation character. valid values are (- : .)
    

Returns:

  • String



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/eui.rb', line 132

def address(options=nil)
    known_args = [:Delimiter]
    delimiter = '-'

    if (options)
        if (!options.kind_of? Hash)
            raise ArgumentError, "Expected Hash, but #{options.class} provided."
        end
        NetAddr.validate_args(options.keys,known_args)

        if (options.has_key?(:Delimiter))
            delimiter = options[:Delimiter]
            delimiter = '-' if (delimiter != ':' && delimiter != '.')
        end
    end

    if (delimiter == '-' || delimiter == ':')
        addr = octets.join(delimiter)
    elsif (delimiter == '.')
            toggle = 0
            octets.each do |x|
                if (!addr)
                    addr = x
                    toggle = 1
                elsif (toggle == 0)
                    addr = addr  << '.' << x
                    toggle = 1
                else
                    addr = addr << x
                    toggle = 0
                end
            end
    end

    return(addr)
end

#ei(options = nil) ⇒ Object

Synopsis

Returns Extended Identifier portion of an EUI address (the vendor assigned ID). The default address format is xx-xx-xx

Example: addr = NetAddr::EUI.create(‘aabb.ccdd.eeff’) addr.ei(:Delimiter => ‘-’) => “dd-ee-ff”

Arguments:

  • options = Hash with the following fields:

    :Delimiter -- delimitation character. valid values are (-, and :)
    

Returns:

  • String



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/eui.rb', line 188

def ei(options=nil)
    known_args = [:Delimiter]
    delimiter = '-'

    if (options)
        if (!options.kind_of? Hash)
            raise ArgumentError, "Expected Hash, but #{options.class} provided."
        end
        NetAddr.validate_args(options.keys,known_args)

        if (options.has_key?(:Delimiter))
            if (options[:Delimiter] == ':')
                delimiter = options[:Delimiter]
            end
        end
    end

    if ( self.kind_of?(NetAddr::EUI48) )
        ei = octets[3..5].join(delimiter)
    else
        ei = octets[3..7].join(delimiter)
    end

    return(ei)
end

Synopsis

Provide an IPv6 Link Local address based on the current EUI address.

Example: addr = NetAddr::EUI.create(‘aabb.ccdd.eeff’) addr.link_local() => “fe80:0000:0000:0000:aabb:ccff:fedd:eeff”

Arguments:

  • options = Hash with the following fields:

    :Short -- if true, return IPv6 addresses in short-hand notation
    :Objectify -- if true, return CIDR objects
    

Returns:

  • CIDR address String or an NetAddr::CIDR object



233
234
235
# File 'lib/eui.rb', line 233

def link_local(options=nil)
    return( self.to_ipv6('fe80::/64', options) )
end

#oui(options = nil) ⇒ Object

Synopsis

Returns Organizationally Unique Identifier portion of an EUI address (the vendor ID). The default address format is xx-xx-xx.

Example: addr = NetAddr::EUI.create(‘aabb.ccdd.eeff’) addr.oui(:Delimiter => ‘-’) => “aa-bb-cc”

Arguments:

  • options = Hash with the following fields:

    :Delimiter -- delimitation character. valid values are (-, and :)
    

Returns:

  • String



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/eui.rb', line 256

def oui(options=nil)
    known_args = [:Delimiter]
    delimiter = '-'

    if (options)
        if (!options.kind_of? Hash)
            raise ArgumentError, "Expected Hash, but #{options.class} provided."
        end
        NetAddr.validate_args(options.keys,known_args)

        if (options.has_key?(:Delimiter))
            if (options[:Delimiter] == ':')
                delimiter = options[:Delimiter]
            end
        end
    end
    oui = octets[0..2].join(delimiter)

    return(oui)
end

#to_iObject

Synopsis

Returns the EUI as an Integer.

Example: addr = NetAddr::EUI.create(‘aabb.ccdd.eeff’) addr.to_i => 187723572702975

Arguments:

  • none

Returns:

  • Integer



294
295
296
# File 'lib/eui.rb', line 294

def to_i()
    return(@eui_i)
end

#to_ipv6(cidr, options = nil) ⇒ Object

Synopsis

Given a valid IPv6 subnet, return an IPv6 address based on the current EUI.

Example: addr = NetAddr::EUI.create(‘aabb.ccdd.eeff’) addr.to_ipv6(‘3ffe::/64’) => “3ffe:0000:0000:0000:a8bb:ccff:fedd:eeff”

Arguments:

  • options = Hash with the following fields:

    :Short -- if true, return IPv6 addresses in short-hand notation
    :Objectify -- if true, return CIDR objects
    

Returns:

  • IPv6 address String or an NetAddr::CIDRv6 object



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'lib/eui.rb', line 317

def to_ipv6(cidr, options=nil)
    known_args = [:Short, :Objectify]
    objectify = false
    short = false

    if ( !cidr.kind_of?(NetAddr::CIDR) )
        begin
            cidr = NetAddr::CIDR.create(cidr)
        rescue Exception => error
            raise ArgumentError, "CIDR raised the following errors: #{error}"
        end
    elsif (cidr.kind_of?(NetAddr::CIDRv4)  )
        raise ArgumentError, "Expected CIDRv6, but #{cidr.class} provided."
    end

    if (cidr.bits > 64)
        raise ValidationError, "Prefix length of provided CIDR must be /64 or less but was #{cidr.netmask}."
    end

    if (options)
        if (!options.kind_of? Hash)
            raise ArgumentError, "Expected Hash, but #{options.class} provided."
        end
        NetAddr.validate_args(options.keys,known_args)

        if (options.has_key?(:Objectify) && options[:Objectify] == true)
            objectify = true
        end

        if (options.has_key?(:Short) && options[:Short] == true)
            short = true
        end
    end

    # get integer equiv of addr. conver eui48 to eui64 if needed
    if ( self.kind_of?(NetAddr::EUI48) )
        eui_i = self.to_eui64.to_i
    else
        eui_i = self.to_i
    end
  
    # toggle u/l bit
    eui_i = eui_i ^ 0x0200000000000000

    # create ipv6 address
    ipv6 = cidr.to_i | eui_i

    if (!objectify)
        ipv6 = NetAddr.i_to_ip(ipv6, :Version => 6)
        ipv6 = NetAddr.shorten(ipv6) if (short)
    else
        ipv6 = NetAddr::CIDRv6.new(ipv6)
    end

    return(ipv6)
end

#to_sObject

Synopsis

Returns the EUI as an unformatted String.

Example: addr = NetAddr::EUI.create(‘aabb.ccdd.eeff’) addr.to_s => “aabbccddeeff”

Arguments:

  • none

Returns:

  • String



391
392
393
# File 'lib/eui.rb', line 391

def to_s()
    return(@eui)
end