A base module for collecting IP-related information from all kinds of platforms.
A map of all the different regexes that work for a given platform or set of platforms.
Convert an interface name into purely alphanumeric characters.
# File lib/facter/util/ip.rb, line 39 def self.alphafy(interface) interface.gsub(%r[^a-z0-9_]/, '_') end
# File lib/facter/util/ip.rb, line 43 def self.convert_from_hex?(kernel) kernels_to_convert = [:sunos, :openbsd, :netbsd, :freebsd, :darwin, :"hp-ux", :"gnu/kfreebsd", :dragonfly] kernels_to_convert.include?(kernel) end
# File lib/facter/util/ip.rb, line 74 def self.get_all_interface_output case Facter.value(:kernel) when 'Linux', 'OpenBSD', 'NetBSD', 'FreeBSD', 'Darwin', 'GNU/kFreeBSD', 'DragonFly' output = %x{/sbin/ifconfig -a} when 'SunOS' output = %x{/usr/sbin/ifconfig -a} when 'HP-UX' output = %x{/bin/netstat -in | sed -e 1d} when 'windows' output = %x#{ENV['SYSTEMROOT']}/system32/netsh interface ip show interface| output += %x#{ENV['SYSTEMROOT']}/system32/netsh interface ipv6 show interface| end output end
# File lib/facter/util/ip.rb, line 196 def self.get_arp_value(interface) arp = Facter::Util::Resolution.exec("arp -en -i #{interface} | sed -e 1d") if arp =~ %r^\S+\s+\w+\s+(\S+)\s+\w\s+\S+$/ return $1 end end
# File lib/facter/util/ip.rb, line 117 def self.get_bonding_master(interface) if Facter.value(:kernel) != 'Linux' return nil end # We need ip instead of ifconfig because it will show us # the bonding master device. if not FileTest.executable?("/sbin/ip") return nil end # A bonding interface can never be an alias interface. Alias # interfaces do have a colon in their name and the ip link show # command throws an error message when we pass it an alias # interface. if interface =~ %r:/ return nil end regex = %rSLAVE[,>].* (bond[0-9]+)/ ethbond = regex.match(%x{/sbin/ip link show #{interface}}) if ethbond device = ethbond[1] else device = nil end device end
# File lib/facter/util/ip.rb, line 143 def self.get_interface_value(interface, label) tmp1 = [] kernel = Facter.value(:kernel).downcase.to_sym # If it's not directly in the map or aliased in the map, then we don't know how to deal with it. unless map = REGEX_MAP[kernel] || REGEX_MAP.values.find { |tmp| tmp[:aliases] and tmp[:aliases].include?(kernel) } return [] end # Pull the correct regex out of the map. regex = map[label.to_sym] # Linux changes the MAC address reported via ifconfig when an ethernet interface # becomes a slave of a bonding device to the master MAC address. # We have to dig a bit to get the original/real MAC address of the interface. bonddev = get_bonding_master(interface) if label == 'macaddress' and bonddev bondinfo = IO.readlines("/proc/net/bonding/#{bonddev}") hwaddrre = %r^Slave Interface: #{interface}\n[^\n].+?\nPermanent HW addr: (([0-9a-fA-F]{2}:?)*)$/ value = hwaddrre.match(bondinfo.to_s)[1].upcase else output_int = get_output_for_interface_and_label(interface, label) output_int.each_line do |s| if s =~ regex value = $1 if label == 'netmask' && convert_from_hex?(kernel) value = value.scan(%r../).collect do |byte| byte.to_i(16) end.join('.') end tmp1.push(value) end end if tmp1 value = tmp1.shift end end end
# File lib/facter/util/ip.rb, line 60 def self.get_interfaces return [] unless output = Facter::Util::IP.get_all_interface_output() # windows interface names contain spaces and are quoted and can appear multiple # times as ipv4 and ipv6 return output.scan(%r\s* connected\s*(\S.*)/).flatten.uniq if Facter.value(:kernel) == 'windows' # Our regex appears to be stupid, in that it leaves colons sitting # at the end of interfaces. So, we have to trim those trailing # characters. I tried making the regex better but supporting all # platforms with a single regex is probably a bit too much. output.scan(%r^\S+/).collect { |i| i.sub(%r:$/, '') }.uniq end
# File lib/facter/util/ip.rb, line 183 def self.get_network_value(interface) require 'ipaddr' ipaddress = get_interface_value(interface, "ipaddress") netmask = get_interface_value(interface, "netmask") if ipaddress && netmask ip = IPAddr.new(ipaddress, Socket::AF_INET) subnet = IPAddr.new(netmask, Socket::AF_INET) network = ip.mask(subnet.to_s).to_s end end
# File lib/facter/util/ip.rb, line 106 def self.get_output_for_interface_and_label(interface, label) return get_single_interface_output(interface) unless Facter.value(:kernel) == 'windows' if label == 'ipaddress6' output = %x#{ENV['SYSTEMROOT']}/system32/netsh interface ipv6 show address \"#{interface}\"| else output = %x#{ENV['SYSTEMROOT']}/system32/netsh interface ip show address \"#{interface}\"| end output end
# File lib/facter/util/ip.rb, line 89 def self.get_single_interface_output(interface) output = "" case Facter.value(:kernel) when 'Linux', 'OpenBSD', 'NetBSD', 'FreeBSD', 'Darwin', 'GNU/kFreeBSD', 'DragonFly' output = %x{/sbin/ifconfig #{interface}} when 'SunOS' output = %x{/usr/sbin/ifconfig #{interface}} when 'HP-UX' mac = "" ifc = %x{/usr/sbin/ifconfig #{interface}} %x{/usr/sbin/lanscan}.scan(%r(\dx\S+).*UP\s+(\w+\d+)/).each {|i| mac = i[0] if i.include?(interface) } mac = mac.sub(%r0x(\S+)/,'\1').scan(%r../).join(":") output = ifc + "\n" + mac end output end
# File lib/facter/util/ip.rb, line 48 def self.supported_platforms REGEX_MAP.inject([]) do |result, tmp| key, map = tmp if map[:aliases] result += map[:aliases] else result << key end result end end