puppetlabs/facter-ng

View on GitHub
lib/resolvers/windows/ffi/network_utils.rb

Summary

Maintainability
A
25 mins
Test Coverage
# frozen_string_literal: true

class NetworkUtils
  @log = Facter::Log.new(self)
  class << self
    def address_to_string(addr)
      return if addr[:lpSockaddr] == FFI::Pointer::NULL

      size = FFI::MemoryPointer.new(NetworkingFFI::INET6_ADDRSTRLEN + 1)
      buffer = FFI::MemoryPointer.new(:wchar, NetworkingFFI::INET6_ADDRSTRLEN + 1)
      error = nil
      3.times do
        error = NetworkingFFI::WSAAddressToStringW(addr[:lpSockaddr], addr[:iSockaddrLength],
                                                   FFI::Pointer::NULL, buffer, size)
        break if error.zero?
      end
      unless error.zero?
        @log.debug 'address to string translation failed!'
        return
      end
      extract_address(buffer)
    end

    def extract_address(addr)
      addr.read_wide_string_without_length.split('%').first
    end

    def ignored_ip_address(addr)
      addr.empty? || addr.start_with?('127.', '169.254.') || addr.start_with?('fe80') || addr.eql?('::1')
    end

    def find_mac_address(adapter)
      adapter[:PhysicalAddress].first(adapter[:PhysicalAddressLength])
                               .map { |e| format('%<mac_address>02x', mac_address: e.to_i) }
                               .join(':').upcase
    end

    def build_binding(addr, mask_length)
      ip = IPAddr.new(addr)
      mask = if ip.ipv6?
               IPAddr.new('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff').mask(mask_length)
             else
               IPAddr.new('255.255.255.255').mask(mask_length)
             end
      { address: addr, netmask: mask.to_s, network: ip.mask(mask_length).to_s }
    end

    def get_scope(sockaddr)
      require 'socket'
      scope6 = []
      addrinfo = Addrinfo.new(['AF_INET6', 0, nil, sockaddr], :INET6)

      scope6 << 'compat,' if addrinfo.ipv6_v4compat?
      scope6 << if addrinfo.ipv6_linklocal?
                  'link'
                elsif addrinfo.ipv6_sitelocal?
                  'site'
                elsif addrinfo.ipv6_loopback?
                  'host'
                else 'global'
                end
      scope6.join
    end
  end
end