module Facter::Resolvers::Aix::FfiHelper

Constants

KINFO_GET_AVENRUN
KINFO_READ
KINFO_RT
KINFO_RT_IFLIST

Public Class Methods

address_to_string(sockaddr, mask = nil) click to toggle source
# File lib/facter/resolvers/aix/ffi/ffi_helper.rb, line 126
def self.address_to_string(sockaddr, mask = nil)
  if sockaddr[:sa_family] == FFI::AF_INET
    in_addr_ip = FFI::SockaddrIn.new(sockaddr.to_ptr)

    if mask && sockaddr[:sa_family] == mask[:sa_family]
      in_addr_mask = FFI::SockaddrIn.new(mask.to_ptr)
      in_addr_ip[:sin_addr][:s_addr] &= in_addr_mask[:sin_addr][:s_addr]
    end

    buffer = ::FFI::MemoryPointer.new(:char, FFI::INET_ADDRSTRLEN)
    Libc.inet_ntop(FFI::AF_INET, in_addr_ip[:sin_addr].to_ptr, buffer, 16)

    buffer
  elsif sockaddr[:sa_family] == FFI::AF_INET6
    in_addr_ip = FFI::SockaddrIn6.new(sockaddr.to_ptr)
    if mask && sockaddr[:sa_family] == mask[:sa_family]
      in_addr_mask = FFI::SockaddrIn6.new(sockaddr.to_ptr)
      16.times do |i|
        in_addr_ip[:sin6_addr][:u6_addr8][i] &= in_addr_mask[:sin6_addr][:u6_addr8][i]
      end
    end

    buffer = ::FFI::MemoryPointer.new(:char, FFI::INET6_ADDRSTRLEN)
    Libc.inet_ntop(FFI::AF_INET6, in_addr_ip[:sin6_addr].to_ptr, buffer, 16)

    buffer
  end
end
log() click to toggle source
# File lib/facter/resolvers/aix/ffi/ffi_helper.rb, line 155
def self.log
  @log ||= Log.new(self)
end
read_interfaces() click to toggle source
# File lib/facter/resolvers/aix/ffi/ffi_helper.rb, line 39
def self.read_interfaces
  ksize = Libc.getkerninfo(KINFO_RT_IFLIST, nil, nil, 0)

  log.debug('getkerninfo call was unsuccessful') if ksize.zero?

  ksize_ptr = ::FFI::MemoryPointer.new(:int, ksize.size)
  ksize_ptr.write_int(ksize)

  result_ptr = ::FFI::MemoryPointer.new(:char, ksize)

  res = Libc.getkerninfo(KINFO_RT_IFLIST, result_ptr, ksize_ptr, 0)
  log.debug('getkerninfo call was unsuccessful') if res == -1

  cursor = 0

  interfaces = {}
  while cursor < ksize_ptr.read_int
    hdr = FFI::IfMsghdr.new(result_ptr + cursor)

    case hdr[:ifm_type]
    when FFI::RTM_IFINFO
      link_addr = FFI::SockaddrDl.new(hdr.to_ptr + hdr.size)

      interface_name = link_addr[:sdl_data].to_s[0, link_addr[:sdl_nlen]]
      interfaces[interface_name] ||= {}

    when FFI::RTM_NEWADDR
      addresses = {}
      addr_cursor = cursor + hdr.size
      FFI::RTAX_LIST.each do |key|
        xand = hdr[:ifm_addrs] & FFI::RTA_LIST[key]
        next unless xand != 0

        sockaddr = FFI::Sockaddr.new(result_ptr + addr_cursor)
        addresses[key] = sockaddr
        roundup_nr = roundup(sockaddr)
        addr_cursor += roundup_nr
      end

      family = FFI::AF_UNSPEC

      addresses.each_value do |addr|
        if family != FFI::AF_UNSPEC &&
           addr[:sa_family] != FFI::AF_UNSPEC &&
           family != addr[:sa_family]
          family = FFI::AF_MAX
          break
        end
        family = addr[:sa_family]
      end

      if addresses[FFI::RTAX_NETMASK][:sa_len]
        addresses[FFI::RTAX_NETMASK][:sa_family] = family
        netmask = address_to_string(addresses[FFI::RTAX_NETMASK])
      end

      address = address_to_string(addresses[FFI::RTAX_IFA]) if addresses[FFI::RTAX_IFA][:sa_len]

      if addresses[FFI::RTAX_NETMASK][:sa_len] && addresses[FFI::RTAX_IFA][:sa_len]
        network = address_to_string(addresses[FFI::RTAX_IFA], addresses[FFI::RTAX_NETMASK])
      end

      bindings = family == FFI::AF_INET ? :bindings : :bindings6
      interfaces[interface_name][bindings] ||= []
      interfaces[interface_name][bindings] << {
        netmask: netmask.read_string,
        address: address.read_string,
        network: network.read_string
      }
    else
      log.debug("got an unknown RT_IFLIST message: #{hdr[:ifm_type]}")
    end

    cursor += hdr[:ifm_msglen]
  end

  interfaces
end
read_load_averages() click to toggle source
# File lib/facter/resolvers/aix/ffi/ffi_helper.rb, line 29
def self.read_load_averages
  averages = ::FFI::MemoryPointer.new(:long_long, 3)
  averages_size = ::FFI::MemoryPointer.new(:int, 1)
  averages_size.write_int(averages.size)

  return if Libc.getkerninfo(KINFO_READ | KINFO_GET_AVENRUN, averages, averages_size, 0).negative?

  averages.read_array_of_long_long(3).map { |x| (x / 65_536.0) }
end
roundup(sockaddr) click to toggle source
# File lib/facter/resolvers/aix/ffi/ffi_helper.rb, line 118
def self.roundup(sockaddr)
  if sockaddr[:sa_len].positive?
    1 + ((sockaddr[:sa_len] - 1) | (1.size - 1))
  else
    1.size
  end
end