Skip to content

Instantly share code, notes, and snippets.

@tommybotten
Created August 23, 2012 13:31
Show Gist options
  • Save tommybotten/3436634 to your computer and use it in GitHub Desktop.
Save tommybotten/3436634 to your computer and use it in GitHub Desktop.
Example to replace string search in facter in favor of system calls
#!/usr/bin/ruby
require 'socket'
# From bits/ioctls.h
SIOCGIFNETMASK = 0x891b # Netmask address
SIOCGIFHWADDR = 0x8927 # hardware address
SIOCGIFADDR = 0x8915 # PA address
SIOCGIFCONF = 0x8912 # iface list
class Interface
#def self.list
# sock = UDPSocket.new
#
# # Query to get size of the interface buffer
# buf = [0,0].pack('lQ')
# sock.ioctl(SIOCGIFCONF, buf)
# buf_size = buf.unpack('l').first
#
# # Generate a return buffer (must be a smarter way)
# data = ''
# for i in 1..buf_size
# data = data + "\0"
# end
#
# # Get interface data
# buf = [buf_size,data].pack("la#{buf_size}")
# sock.ioctl(SIOCGIFCONF, buf);
# sock.close
#
# # Unpack interface information (data part is an array of struct ifreq with the first
# # member is char ifrn_name[IFNAMSIZ] (16) and sizeof(struct ifreq) = 40)
# return buf
#end
def self.list
sock = UDPSocket.new
# Query to get size of the interface buffer
buf = [0,0].pack('lQ')
sock.ioctl(SIOCGIFCONF, buf)
buf_size = buf.unpack('l').first
# Generate a return buffer (must be a smarter way)
data = ''
for i in 1..buf_size
data = data + " "
end
# Get interface data
buf = [buf_size, data].pack("lP#{buf_size}")
sock.ioctl(SIOCGIFCONF, buf)
sock.close
# Unpack interface information (data part is an array of struct ifreq with the first
# member is char ifrn_name[IFNAMSIZ] (16) and sizeof(struct ifreq) = 40)
names = []
off = 0
while off < buf_size
name = data[off..off+16].unpack('a16').first
print("Name #{name}\n")
names << name
off += 40
end
return names
end
def self.hw_address(iface)
sock = UDPSocket.new
buf = [iface,""].pack('a16h16')
sock.ioctl(SIOCGIFHWADDR, buf);
sock.close
return buf[18..24].unpack("H2H2H2H2H2H2").join(":")
end
def self.netmask(iface)
sock = UDPSocket.new
buf = [iface,""].pack('a16h16')
sock.ioctl(SIOCGIFNETMASK, buf);
sock.close
return buf[20..23].unpack("CCCC").join(".")
end
def self.ip_address(iface)
sock = UDPSocket.new
buf = [iface,""].pack('a16h16')
sock.ioctl(SIOCGIFADDR, buf);
sock.close
buf[20..24].unpack("CCCC").join(".")
end
def self.list_all_ips
# Slow for some reason. 5ms for each iteration.
return Socket::getaddrinfo(Socket.gethostname, '', Socket::AF_INET).map { |x| x[3] }.uniq
end
end
puts Interface.list
@wconrad
Copy link

wconrad commented Aug 8, 2015

Perhaps data = ' ' * buf_size would do for the "must be a smarter way" section.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment