Update LinuxNetwork to not use fcntl and ioctls
get_interfaces() updated to read /proc/net/dev. This means it no longer provides only interfaces that are up. get_iface_hwaddr() updated to read from /sys/class/net/<iface>/address. Added get_interface_facts() to pull in mac address and interface mtu. Can be used later for additional interface-facts. Added get_ipv6_facts(), which reads from /proc/net/if_inet6. get_network_facts() renamed to get_ipv4_facts(). It still calls ifconfig to determine ipv4 facts.
This commit is contained in:
parent
162b78ea5c
commit
0efc0bec89
1 changed files with 57 additions and 42 deletions
|
@ -384,6 +384,13 @@ class Network(Facts):
|
||||||
"""
|
"""
|
||||||
platform = 'Generic'
|
platform = 'Generic'
|
||||||
|
|
||||||
|
IPV6_SCOPE = { '0' : 'global',
|
||||||
|
'10' : 'host',
|
||||||
|
'20' : 'link',
|
||||||
|
'40' : 'admin',
|
||||||
|
'50' : 'site',
|
||||||
|
'80' : 'organization' }
|
||||||
|
|
||||||
def __new__(cls, *arguments, **keyword):
|
def __new__(cls, *arguments, **keyword):
|
||||||
subclass = cls
|
subclass = cls
|
||||||
for sc in Network.__subclasses__():
|
for sc in Network.__subclasses__():
|
||||||
|
@ -404,43 +411,48 @@ class LinuxNetwork(Network):
|
||||||
- interface_<name> dictionary of ipv4, ipv6, and mac address information.
|
- interface_<name> dictionary of ipv4, ipv6, and mac address information.
|
||||||
"""
|
"""
|
||||||
platform = 'Linux'
|
platform = 'Linux'
|
||||||
SIOCGIFCONF = 0x8912
|
|
||||||
SIOCGIFHWADDR = 0x8927
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Network.__init__(self)
|
Network.__init__(self)
|
||||||
|
|
||||||
def populate(self):
|
def populate(self):
|
||||||
self.get_network_facts()
|
self.facts['interfaces'] = self.get_interfaces()
|
||||||
|
self.get_interface_facts()
|
||||||
|
self.get_ipv4_facts()
|
||||||
|
self.get_ipv6_facts()
|
||||||
return self.facts
|
return self.facts
|
||||||
|
|
||||||
# get list of interfaces that are up
|
# get list of interfaces
|
||||||
def get_interfaces(self):
|
def get_interfaces(self):
|
||||||
length = 4096
|
names = []
|
||||||
offset = 32
|
data = get_file_content('/proc/net/dev')
|
||||||
step = 32
|
# Format of /proc/net/dev is:
|
||||||
if platform.architecture()[0] == '64bit':
|
# Inter-| Receive ...
|
||||||
offset = 16
|
# face |bytes ...
|
||||||
step = 40
|
# lo: 595059
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
for line in data.split('\n'):
|
||||||
names = array.array('B', '\0' * length)
|
if ':' in line:
|
||||||
bytelen = struct.unpack('iL', fcntl.ioctl(
|
names.append(line.split(':')[0].strip())
|
||||||
s.fileno(), LinuxNetwork.SIOCGIFCONF, struct.pack(
|
return names
|
||||||
'iL', length, names.buffer_info()[0])
|
|
||||||
))[0]
|
|
||||||
return [names.tostring()[i:i+offset].split('\0', 1)[0]
|
|
||||||
for i in range(0, bytelen, step)]
|
|
||||||
|
|
||||||
def get_iface_hwaddr(self, iface):
|
def get_iface_hwaddr(self, iface):
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
data = get_file_content('/sys/class/net/%s/address' % iface)
|
||||||
info = fcntl.ioctl(s.fileno(), LinuxNetwork.SIOCGIFHWADDR,
|
if data is None:
|
||||||
struct.pack('256s', iface[:15]))
|
return 'unknown'
|
||||||
return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]
|
else:
|
||||||
|
return data.strip()
|
||||||
|
|
||||||
def get_network_facts(self):
|
def get_interface_facts(self):
|
||||||
self.facts['interfaces'] = self.get_interfaces()
|
|
||||||
for iface in self.facts['interfaces']:
|
for iface in self.facts['interfaces']:
|
||||||
|
if iface not in self.facts:
|
||||||
|
self.facts[iface] = {}
|
||||||
self.facts[iface] = { 'macaddress': self.get_iface_hwaddr(iface) }
|
self.facts[iface] = { 'macaddress': self.get_iface_hwaddr(iface) }
|
||||||
|
if os.path.exists('/sys/class/net/%s/mtu' % iface):
|
||||||
|
mtu = get_file_content('/sys/class/net/%s/mtu' % iface)
|
||||||
|
self.facts[iface]['mtu'] = mtu.strip()
|
||||||
|
|
||||||
|
def get_ipv4_facts(self):
|
||||||
|
for iface in self.facts['interfaces']:
|
||||||
# This is lame, but there doesn't appear to be a good way
|
# This is lame, but there doesn't appear to be a good way
|
||||||
# to get all addresses for both IPv4 and IPv6.
|
# to get all addresses for both IPv4 and IPv6.
|
||||||
cmd = subprocess.Popen("/sbin/ifconfig %s" % iface, shell=True,
|
cmd = subprocess.Popen("/sbin/ifconfig %s" % iface, shell=True,
|
||||||
|
@ -468,24 +480,27 @@ class LinuxNetwork(Network):
|
||||||
ip = struct.unpack("!L", socket.inet_aton(self.facts[iface]['ipv4']['address']))[0]
|
ip = struct.unpack("!L", socket.inet_aton(self.facts[iface]['ipv4']['address']))[0]
|
||||||
mask = struct.unpack("!L", socket.inet_aton(self.facts[iface]['ipv4']['netmask']))[0]
|
mask = struct.unpack("!L", socket.inet_aton(self.facts[iface]['ipv4']['netmask']))[0]
|
||||||
self.facts[iface]['ipv4']['network'] = socket.inet_ntoa(struct.pack("!L", ip & mask))
|
self.facts[iface]['ipv4']['network'] = socket.inet_ntoa(struct.pack("!L", ip & mask))
|
||||||
if 'inet6 addr' in line:
|
|
||||||
(ip, prefix) = data[2].split('/')
|
def get_ipv6_facts(self):
|
||||||
scope = data[3].split(':')[1].lower()
|
data = get_file_content('/proc/net/if_inet6')
|
||||||
if 'ipv6' not in self.facts[iface]:
|
if data is None:
|
||||||
self.facts[iface]['ipv6'] = []
|
return
|
||||||
self.facts[iface]['ipv6'].append( { 'address': ip,
|
for line in data.split('\n'):
|
||||||
'prefix': prefix,
|
l = line.split()
|
||||||
'scope': scope } )
|
iface = l[5]
|
||||||
# Slightly different output in net-tools-1.60-134.20120127git
|
if 'ipv6' not in self.facts[iface]:
|
||||||
# Looks like
|
self.facts[iface]['ipv6'] = []
|
||||||
# inet6 fe80::21b:21ff:fe6e:5baa prefixlen 64 scopeid 0x20<link>
|
scope = l[3]
|
||||||
elif 'inet6 ' in line:
|
if Network.IPV6_SCOPE.has_key(l[3]):
|
||||||
if 'ipv6' not in self.facts[iface]:
|
scope = Network.IPV6_SCOPE[l[3]]
|
||||||
self.facts[iface]['ipv6'] = []
|
prefix = int(l[2], 16)
|
||||||
scope = data[5].split('<')[1][:-1]
|
str_addr = ':'.join( [ l[0][i:i+4] for i in range(0, len(l[0]), 4) ] )
|
||||||
self.facts[iface]['ipv6'].append( { 'address': data[1],
|
# Normalize ipv6 address from format in /proc/net/if_inet6
|
||||||
'prefix': data[3],
|
addr = socket.inet_ntop(socket.AF_INET6,
|
||||||
'scope': scope } )
|
socket.inet_pton(socket.AF_INET6, str_addr))
|
||||||
|
self.facts[iface]['ipv6'].append( { 'address': addr,
|
||||||
|
'prefix': prefix,
|
||||||
|
'scope': scope } )
|
||||||
|
|
||||||
class Virtual(Facts):
|
class Virtual(Facts):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in a new issue