diff --git a/src/yunohost/monitor.py b/src/yunohost/monitor.py index ed13d532d..fc10a4fbc 100644 --- a/src/yunohost/monitor.py +++ b/src/yunohost/monitor.py @@ -164,6 +164,7 @@ def monitor_network(units=None, human_readable=False): units = ['check', 'usage', 'infos'] # Get network devices and their addresses + # TODO / FIXME : use functions in utils/network.py to manage this devices = {} output = subprocess.check_output('ip addr show'.split()) for d in re.split('^(?:[0-9]+: )', output, flags=re.MULTILINE): @@ -213,6 +214,7 @@ def monitor_network(units=None, human_readable=False): elif u == 'infos': p_ipv4 = get_public_ip() or 'unknown' + # TODO / FIXME : use functions in utils/network.py to manage this l_ip = 'unknown' for name, addrs in devices.items(): if name == 'lo': diff --git a/src/yunohost/utils/network.py b/src/yunohost/utils/network.py index e22d1644d..470354f63 100644 --- a/src/yunohost/utils/network.py +++ b/src/yunohost/utils/network.py @@ -19,10 +19,13 @@ """ import logging +import re +import subprocess from urllib import urlopen logger = logging.getLogger('yunohost.utils.network') + def get_public_ip(protocol=4): """Retrieve the public IP address from ip.yunohost.org""" @@ -37,3 +40,76 @@ def get_public_ip(protocol=4): return urlopen(url).read().strip() except IOError: return None + + +def get_network_interfaces(): + + # Get network devices and their addresses (raw infos from 'ip addr') + devices_raw = {} + output = subprocess.check_output('ip addr show'.split()) + for d in re.split('^(?:[0-9]+: )', output, flags=re.MULTILINE): + # Extract device name (1) and its addresses (2) + m = re.match('([^\s@]+)(?:@[\S]+)?: (.*)', d, flags=re.DOTALL) + if m: + devices_raw[m.group(1)] = m.group(2) + + # Parse relevant informations for each of them + devices = {name: _extract_inet(addrs) for name, addrs in devices_raw.items() if name != "lo"} + + return devices or "unknown" + + +def get_gateway(): + + output = subprocess.check_output('ip route show'.split()) + m = re.search('default via (.*) dev ([a-z]+[0-9]?)', output) + if not m: + return "unknown" + + addr = _extract_inet(m.group(1), True) + return addr.popitem()[1] if len(addr) == 1 else "unknown" + + +############################################################################### + + +def _extract_inet(string, skip_netmask=False, skip_loopback=True): + """ + Extract IP addresses (v4 and/or v6) from a string limited to one + address by protocol + + Keyword argument: + string -- String to search in + skip_netmask -- True to skip subnet mask extraction + skip_loopback -- False to include addresses reserved for the + loopback interface + + Returns: + A dict of {protocol: address} with protocol one of 'ipv4' or 'ipv6' + + """ + ip4_pattern = '((25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}' + ip6_pattern = '(((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)' + ip4_pattern += '/[0-9]{1,2})' if not skip_netmask else ')' + ip6_pattern += '/[0-9]{1,3})' if not skip_netmask else ')' + result = {} + + for m in re.finditer(ip4_pattern, string): + addr = m.group(1) + if skip_loopback and addr.startswith('127.'): + continue + + # Limit to only one result + result['ipv4'] = addr + break + + for m in re.finditer(ip6_pattern, string): + addr = m.group(1) + if skip_loopback and addr == '::1': + continue + + # Limit to only one result + result['ipv6'] = addr + break + + return result