Created
April 20, 2010 21:13
-
-
Save erikh/373081 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'facter' | |
require 'stringio' | |
Interface = Struct.new( | |
:af_type, :address, :broadcast, :netmask, :mtu, | |
:status, :mac | |
) | |
module IFConfig | |
def ifconfig | |
interfaces = { } | |
output = "" | |
case Facter["Kernel"].value | |
when "Solaris", "Linux", "Darwin", /BSD/ | |
output = %x(/sbin/ifconfig -a) | |
else | |
fail "Couldn't figure out your system ifconfig" | |
end | |
unless $?.exitstatus == 0 | |
fail "Error getting data from ifconfig" | |
end | |
sio = StringIO.new(output) | |
case Facter["Kernel"].value | |
when "Linux" | |
interfaces = linux(sio) | |
when "Darwin", /BSD/ | |
interfaces = bsd(sio, Facter["Kernel"].value) | |
when "Solaris" | |
interfaces = solaris(sio) | |
end | |
return interfaces | |
end | |
module_function :ifconfig | |
def convert_hex_to_octet(hexmask) | |
hexmask.scan(/.{2}/).collect { |x| x.hex }.join(".") | |
end | |
def parse_af_lines(sio) | |
loop do | |
ch = sio.getc | |
if ch and (ch.chr == " " or ch == ?\t) | |
words = sio.readline.sub(/^\s+/, "").split(/\s+/) | |
yield words | |
else | |
sio.ungetc(ch) if ch | |
break | |
end | |
end | |
end | |
def linux(sio) | |
interfaces = { } | |
while(!sio.eof?) do | |
header = sio.readline | |
m = header.match(/^([^ ]+).*?HWaddr ([^ ]+)/) | |
# downed and special interfaces have a different syntax | |
m = header.match(/^([^ ]+)/) unless m | |
interface, | |
mac = m[1,2] | |
mtu = "" | |
status = "" | |
interfaces[interface] = [] | |
parse_af_lines(sio) do |words| | |
if words[0] =~ /^inet/ | |
my_int = Interface.new | |
interfaces[interface].push(my_int) | |
case words[0] | |
when "inet" | |
my_int.af_type = :inet | |
# linux chooses to insert bcast in the middle instead of append it like | |
# freebsd/solaris. | |
my_int.address = words[1].sub(/^addr:/, "") | |
my_int.broadcast = words[2] =~ /^Bcast:/ ? words[2].sub(/^Bcast:/, "") : nil | |
my_int.netmask = words[2] =~ /^Bcast:/ ? words[3].sub(/^Mask:/, "") : words[2].sub(/^Mask:/, "") | |
when "inet6" | |
my_int.af_type = :inet6 | |
my_int.address, | |
my_int.netmask = words[2].split(/\//) | |
my_int.broadcast = nil | |
end | |
elsif words[0] =~ /^UP/ | |
status = :active | |
mtu = words.find { |x| x =~ /^MTU/ } | |
mtu.sub!(/^MTU:/, "") | |
end | |
end | |
interfaces[interface].each do |x| | |
x.status = status.to_s.length ? :active : :down | |
x.mac = mac | |
x.mtu = mtu | |
if interface == "lo" | |
x.status = :active | |
x.mac = nil | |
end | |
end | |
sio.readline | |
end | |
return interfaces | |
end | |
module_function :linux | |
def bsd(sio, kernel) | |
interfaces = { } | |
while(!sio.eof?) do | |
header = sio.readline | |
m = header.match(/^([^:]+): .*?mtu (\d+)/) | |
status = "" | |
mac = "" | |
interface, | |
mtu = m[1,2] | |
interfaces[interface] = [] | |
parse_af_lines(sio) do |words| | |
if words[0] =~ /^inet/ | |
my_int = Interface.new | |
interfaces[interface].push(my_int) | |
my_int.af_type = case words[0] | |
when "inet" | |
:inet | |
when "inet6" | |
:inet6 | |
end | |
# ipv6 addresses in bsd have the interface | |
# appended after a % sign | |
my_int.address = words[1].sub(/%.*$/, "") | |
if words[0] == "inet" | |
my_int.netmask = convert_hex_to_octet(words[3].sub(/^0x/, "")) | |
my_int.broadcast = words[5] | |
elsif words[0] == "inet6" | |
my_int.netmask = words[3] | |
end | |
elsif words[0] =~ /^address/ | |
# openbsd puts the mac on it's own line | |
mac = words[1] | |
elsif words[0] =~ /^media/ | |
# darwin does not have "ethernet" in the media: line | |
status = words[5] | |
elsif words[0] =~ /^ether/ | |
mac = words[1] | |
elsif words[0] =~ /^status/ | |
# freebsd puts the status on it's own line. | |
# this only works because the status line is the last one. | |
status = words[1] | |
end # if words | |
end # parse_af_lines | |
# update the mac, media, and duplex in the interfaces structures. | |
interfaces[interface].each do |x| | |
x.mac = mac | |
x.status = case status | |
when "active" | |
:active | |
when "inactive" | |
:down | |
end | |
x.mtu = mtu | |
# force the loopback to have certain states | |
if interface == "lo0" | |
x.status = :active | |
x.mac = nil | |
x.mtu = nil | |
end | |
end # interfaces each | |
end # while | |
return interfaces | |
end | |
module_function :bsd | |
def solaris(sio) | |
interfaces = { } | |
while (!sio.eof?) | |
header = sio.readline | |
m = header.match(/([^ ]+) (.*?)mtu (\d+)/) | |
interface = m[1].sub(/:$/, "") | |
mtu = m[3] | |
status = m[2] =~ /RUNNING/ ? :active : :down | |
mac = "" | |
interfaces[interface] ||= [] | |
parse_af_lines(sio) do |words| | |
if words[0] =~ /^inet/ | |
my_int = Interface.new | |
interfaces[interface].push(my_int) | |
case words[0] | |
when "inet" | |
my_int.af_type = :inet | |
my_int.address = words[1] | |
my_int.netmask = words[3] | |
my_int.broadcast = words[5] | |
when "inet6" | |
my_int.af_type = :inet6 | |
my_int.address = words[1].sub(/\/.*$/, "") | |
my_int.netmask = words[1].sub(/^[^\/]+\//, "") | |
end | |
elsif words[0] =~ /^ether/ | |
mac = words[1] | |
end | |
end | |
interfaces[interface].each do |x| | |
x.status = status | |
x.mac = mac | |
x.mtu = mtu | |
if interface == "lo0" | |
x.status = :active | |
end | |
end | |
end | |
return interfaces | |
end | |
module_function :solaris | |
end | |
require 'pp' | |
include IFConfig | |
pp ifconfig | |
if File.exists? "openbsd_ifconfig.txt" | |
$stdout.puts | |
$stdout.puts "Running openbsd_ifconfig.txt" | |
$stdout.puts | |
pp bsd(File.open("openbsd_ifconfig.txt"), Facter["Kernel"].value) | |
end | |
if File.exists? "solaris_ifconfig.txt" | |
$stdout.puts | |
$stdout.puts "Running solaris_ifconfig.txt" | |
$stdout.puts | |
pp solaris(File.open("solaris_ifconfig.txt")) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment