class Facter::Util::Linux::SocketParser

Public Class Methods

retrieve_interfaces(logger) click to toggle source
# File lib/facter/util/linux/socket_parser.rb, line 8
def retrieve_interfaces(logger)
  require 'socket'
  @interfaces = {}
  @log = logger
  Socket.getifaddrs.each do |ifaddr|
    populate_interface_info(ifaddr)
  end

  @interfaces
end

Private Class Methods

add_binding(interface_name, ifaddr) click to toggle source
# File lib/facter/util/linux/socket_parser.rb, line 106
def add_binding(interface_name, ifaddr)
  ip, netmask, binding_key = binding_data(ifaddr)
  binding = Facter::Util::Resolvers::Networking.build_binding(ip, netmask)
  return if binding.nil?

  @interfaces[interface_name][binding_key] = [] if @interfaces[interface_name][binding_key].nil?
  @interfaces[interface_name][binding_key] << binding

  @log.debug("Adding to interface #{interface_name}, binding:\n#{binding}")
end
binding_data(ifaddr) click to toggle source
# File lib/facter/util/linux/socket_parser.rb, line 117
def binding_data(ifaddr)
  # ipv6 ips are retrieved as <ip>%<interface_name>
  ip = ifaddr.addr.ip_address.split('%').first
  netmask = ifaddr.netmask.ip_address
  binding_key = ifaddr.addr.ipv4? ? :bindings : :bindings6

  [ip, netmask, binding_key]
end
bond_master_of(interface_name) click to toggle source
# File lib/facter/util/linux/socket_parser.rb, line 61
def bond_master_of(interface_name)
  content = get_ip_link_show_data(interface_name)
  content&.match(/master (\S*) /)&.captures&.first
end
ip_info_of(ifaddr) click to toggle source
# File lib/facter/util/linux/socket_parser.rb, line 98
def ip_info_of(ifaddr)
  return if ifaddr.addr.nil? || ifaddr.netmask.nil?

  add_binding(ifaddr.name, ifaddr)
rescue StandardError => e
  @log.debug("Could not read binding data, got #{e}")
end
mac(ifaddr) click to toggle source
# File lib/facter/util/linux/socket_parser.rb, line 29
def mac(ifaddr)
  return unless @interfaces[ifaddr.name][:mac].nil?

  mac = search_for_mac(ifaddr)
  @interfaces[ifaddr.name][:mac] = mac if mac
end
mac_from(ifaddr) click to toggle source
# File lib/facter/util/linux/socket_parser.rb, line 81
def mac_from(ifaddr)
  if Socket.const_defined? :PF_LINK
    ifaddr.addr&.getnameinfo&.first # sometimes it returns localhost or ip
  elsif Socket.const_defined? :PF_PACKET
    return if ifaddr.addr.nil?

    mac_from_sockaddr_of(ifaddr)
  end
rescue StandardError => e
  @log.debug("Could not read mac for interface #{ifaddr.name}, got #{e}")
end
mac_from_bonded_interface(interface_name) click to toggle source
# File lib/facter/util/linux/socket_parser.rb, line 42
def mac_from_bonded_interface(interface_name)
  master = bond_master_of(interface_name)
  return unless master

  output = Facter::Util::FileHelper.safe_read("/proc/net/bonding/#{master}", nil)
  return unless output

  found_match = false
  output.each_line do |line|
    if line.strip == "Slave Interface: #{interface_name}"
      found_match = true
    elsif line.include? 'Slave Interface'
      # if we reached the data block of another interface belonging to the bonded interface
      found_match = false
    end
    return Regexp.last_match(1) if found_match && line =~ /Permanent HW addr: (\S*)/
  end
end
mac_from_sockaddr_of(ifaddr) click to toggle source
# File lib/facter/util/linux/socket_parser.rb, line 93
def mac_from_sockaddr_of(ifaddr)
  result = ifaddr.addr.inspect_sockaddr
  result&.match(/hwaddr=([\h:]+)/)&.captures&.first
end
populate_interface_info(ifaddr) click to toggle source
# File lib/facter/util/linux/socket_parser.rb, line 21
def populate_interface_info(ifaddr)
  interface_name = ifaddr.name
  @interfaces[interface_name] = {} if @interfaces[interface_name].nil?

  mac(ifaddr)
  ip_info_of(ifaddr)
end
search_for_mac(ifaddr) click to toggle source
# File lib/facter/util/linux/socket_parser.rb, line 36
def search_for_mac(ifaddr)
  mac = mac_from_bonded_interface(ifaddr.name)
  mac ||= mac_from(ifaddr)
  mac if !mac.nil? && mac != '00:00:00:00:00:00' && mac =~ /^([0-9A-Fa-f]{2}[:-]){5,19}([0-9A-Fa-f]{2})$/
end