diff options
-rwxr-xr-x | client/ipa-client-install | 45 | ||||
-rw-r--r-- | freeipa.spec.in | 5 | ||||
-rw-r--r-- | ipaplatform/base/paths.py | 1 | ||||
-rw-r--r-- | ipapython/ipautil.py | 35 |
4 files changed, 40 insertions, 46 deletions
diff --git a/client/ipa-client-install b/client/ipa-client-install index be203586a..c38843f85 100755 --- a/client/ipa-client-install +++ b/client/ipa-client-install @@ -33,6 +33,7 @@ try: from optparse import SUPPRESS_HELP, OptionGroup, OptionValueError import dns import gssapi + import netifaces import nss.nss as nss import SSSDConfig @@ -1526,39 +1527,31 @@ def unconfigure_nisdomain(): def get_iface_from_ip(ip_addr): - result = ipautil.run([paths.IP, '-oneline', 'address', 'show'], - capture_output=True) - for line in result.output.split('\n'): - fields = line.split() - if len(fields) < 6: - continue - if fields[2] not in ['inet', 'inet6']: - continue - (ip, mask) = fields[3].rsplit('/', 1) - if ip == ip_addr: - return fields[1] + for interface in netifaces.interfaces(): + if_addrs = netifaces.ifaddresses(interface) + for family in [netifaces.AF_INET, netifaces.AF_INET6]: + for ip in if_addrs.get(family, []): + if ip['addr'] == ip_addr: + return interface else: raise RuntimeError("IP %s not assigned to any interface." % ip_addr) def get_local_ipaddresses(iface=None): - args = [paths.IP, '-oneline', 'address', 'show'] if iface: - args += ['dev', iface] - result = ipautil.run(args, capture_output=True) - lines = result.output.split('\n') + interfaces = [iface] + else: + interfaces = netifaces.interfaces() + ips = [] - for line in lines: - fields = line.split() - if len(fields) < 6: - continue - if fields[2] not in ['inet', 'inet6']: - continue - (ip, mask) = fields[3].rsplit('/', 1) - try: - ips.append(ipautil.CheckedIPAddress(ip)) - except ValueError: - continue + for interface in interfaces: + if_addrs = netifaces.ifaddresses(interface) + for family in [netifaces.AF_INET, netifaces.AF_INET6]: + for ip in if_addrs.get(family, []): + try: + ips.append(ipautil.CheckedIPAddress(ip['addr'])) + except ValueError: + continue return ips diff --git a/freeipa.spec.in b/freeipa.spec.in index b0861d865..1ded30488 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -103,6 +103,7 @@ BuildRequires: python-jwcrypto BuildRequires: custodia BuildRequires: libini_config-devel >= 1.2.0 BuildRequires: dbus-python +BuildRequires: python-netifaces >= 0.10.4 # Build dependencies for unit tests BuildRequires: libcmocka-devel @@ -478,7 +479,6 @@ Provides: python2-ipaplatform = %{version}-%{release} Requires: %{name}-common = %{version}-%{release} Requires: python-gssapi >= 1.1.2 Requires: gnupg -Requires: iproute Requires: keyutils Requires: pyOpenSSL Requires: python-nss >= 0.16 @@ -500,6 +500,7 @@ Requires: python-ldap >= 2.4.15 Requires: python-requests Requires: python-custodia Requires: python-dns >= 1.11.1 +Requires: python-netifaces >= 0.10.4 Conflicts: %{alt_name}-python < %{version} @@ -526,7 +527,6 @@ Provides: python3-ipaplatform = %{version}-%{release} Requires: %{name}-common = %{version}-%{release} Requires: python3-gssapi >= 1.1.2 Requires: gnupg -Requires: iproute Requires: keyutils Requires: python3-pyOpenSSL Requires: python3-nss >= 0.16 @@ -548,6 +548,7 @@ Requires: python3-pyldap >= 2.4.15 Requires: python3-custodia Requires: python3-requests Requires: python3-dns >= 1.11.1 +Requires: python3-netifaces >= 0.10.4 %description -n python3-ipalib IPA is an integrated solution to provide centrally managed Identity (users, diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py index 1b79015e4..4aa55d870 100644 --- a/ipaplatform/base/paths.py +++ b/ipaplatform/base/paths.py @@ -140,7 +140,6 @@ class BasePathNamespace(object): CACERT_P12 = "/root/cacert.p12" ROOT_IPA_CSR = "/root/ipa.csr" NAMED_PID = "/run/named/named.pid" - IP = "/sbin/ip" NOLOGIN = "/sbin/nologin" SBIN_REBOOT = "/sbin/reboot" SBIN_RESTORECON = "/sbin/restorecon" diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py index d705c51f8..e595d80ca 100644 --- a/ipapython/ipautil.py +++ b/ipapython/ipautil.py @@ -32,6 +32,7 @@ import socket import re import datetime import netaddr +import netifaces import time import gssapi import pwd @@ -151,24 +152,24 @@ class CheckedIPAddress(netaddr.IPAddress): if match_local: if addr.version == 4: - family = 'inet' + family = netifaces.AF_INET elif addr.version == 6: - family = 'inet6' - - result = run( - [paths.IP, '-family', family, '-oneline', 'address', 'show'], - capture_output=True) - lines = result.output.split('\n') - for line in lines: - fields = line.split() - if len(fields) < 4: - continue - - ifnet = netaddr.IPNetwork(fields[3]) - if ifnet == net or (net is None and ifnet.ip == addr): - net = ifnet - iface = fields[1] - break + family = netifaces.AF_INET6 + else: + raise ValueError( + "Unsupported address family ({})".format(addr.version) + ) + + for interface in netifaces.interfaces(): + for ifdata in netifaces.ifaddresses(interface).get(family, []): + ifnet = netaddr.IPNetwork('{addr}/{netmask}'.format( + addr=ifdata['addr'], + netmask=ifdata['netmask'] + )) + if ifnet == net or (net is None and ifnet.ip == addr): + net = ifnet + iface = interface + break if iface is None: raise ValueError('No network interface matches the provided IP address and netmask') |