module Ethernet::Devices

Information about the available Ethernet devices.

Public Class Methods

all() click to toggle source

Array containing device names.

# File lib/ethernet/devices.rb, line 7
def self.all
  info.keys
end
info() click to toggle source

Hash mapping device names to information about devices.

# File lib/ethernet/devices.rb, line 28
def self.info
  # array of struct ifreq in /usr/include/net/if.h
  buffer_size = ifreq_size * 128
  buffer_ptr = FFI::MemoryPointer.new :uchar, buffer_size, 0
  # struct ifconf in /usr/include/net/if.h
  ifconf = [buffer_size, buffer_ptr.address].pack ifconf_packspec
  ioctl_socket.ioctl siocgifconf_ioctl, ifconf
  
  output_size = ifconf.unpack('l').first
  offset = 0
  devices = {}
  while offset < output_size
    name = (buffer_ptr + offset).read_string_to_null
    devices[name] ||= {}
    # struct sockaddr
    addr_length, addr_family = *(buffer_ptr + offset + 16).read_string(2).
                                                           unpack('CC')
    addr_length = ifreq_size - 16 if addr_length < ifreq_size - 16
    if addr_family == ll_address_family
      # struct sockaddr_dl in /usr/include/net/if_dl.h
      devices[name][:index], blah, skip, length =
          *(buffer_ptr + offset + 18).read_string(4).unpack('SCCC')
      devices[name][:mac] =
          (buffer_ptr + offset + 24 + skip).read_string(length)
    end
    
    offset += 16 + addr_length
  end
  
  if devices.all? { |k, v| v[:mac].nil? }
    # Linux only provides IP addresses in SIOCGIFCONF.
    devices.keys.each do |device|
      devices[device][:mac] ||= mac device
      devices[device][:index] ||= interface_index device
    end
  end
  devices.delete_if { |k, v| v[:mac].nil? || v[:mac].empty? }
  
  devices
end
interface_index(eth_device) click to toggle source

The interface number for an Ethernet interface.

Args:

eth_device:: device name for the Ethernet card, e.g. 'eth0'
# File lib/ethernet/devices.rb, line 23
def self.interface_index(eth_device)
  info[eth_device][:index]
end
mac(eth_device) click to toggle source

The MAC address for an Ethernet device.

Args:

eth_device:: device name for the Ethernet card, e.g. 'eth0'
# File lib/ethernet/devices.rb, line 15
def self.mac(eth_device)
  info[eth_device][:mac]
end
siocgifconf_ioctl() click to toggle source

SIOCGIFCONF ioctl number.

# File lib/ethernet/devices.rb, line 71
def siocgifconf_ioctl
  raise "Unsupported os #{Ethernet::Provisioning::OS}"
end

Private Class Methods

ifconf_packspec() click to toggle source

Array#pack specification for struct ifconf.

The specification converts a [size, pointer] array into a valid struct.

# File lib/ethernet/devices.rb, line 79
def ifconf_packspec
  raise "Unsupported os #{Ethernet::Provisioning::OS}"
end
ifreq_size() click to toggle source

Size of a struct ifreq.

# File lib/ethernet/devices.rb, line 85
def ifreq_size
  raise "Unsupported os #{Ethernet::Provisioning::OS}"
end
ioctl_socket() click to toggle source

Socket that is solely used for issuing ioctls.

# File lib/ethernet/devices.rb, line 97
def ioctl_socket
  Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
end
ll_address_family() click to toggle source

The link layer address number for raw sockets.

# File lib/ethernet/devices.rb, line 91
def ll_address_family
  raise "Unsupported os #{Ethernet::Provisioning::OS}"
end