diff options
Diffstat (limited to 'python/vyos/validate.py')
| -rw-r--r-- | python/vyos/validate.py | 68 | 
1 files changed, 21 insertions, 47 deletions
| diff --git a/python/vyos/validate.py b/python/vyos/validate.py index d18785aaf..d3e6e9087 100644 --- a/python/vyos/validate.py +++ b/python/vyos/validate.py @@ -43,57 +43,31 @@ def _are_same_ip(one, two):      s_two = AF_INET if is_ipv4(two) else AF_INET6      return inet_pton(f_one, one) == inet_pton(f_one, two) -def is_intf_addr_assigned(intf, address) -> bool: -    """ -    Verify if the given IPv4/IPv6 address is assigned to specific interface. +def is_intf_addr_assigned(ifname, addr, netns=None): +    """Verify if the given IPv4/IPv6 address is assigned to specific interface.      It can check both a single IP address (e.g. 192.0.2.1 or a assigned CIDR      address 192.0.2.1/24.      """ -    from vyos.template import is_ipv4 - -    from netifaces import ifaddresses -    from netifaces import AF_INET -    from netifaces import AF_INET6 - -    # check if the requested address type is configured at all -    # { -    # 17: [{'addr': '08:00:27:d9:5b:04', 'broadcast': 'ff:ff:ff:ff:ff:ff'}], -    # 2:  [{'addr': '10.0.2.15', 'netmask': '255.255.255.0', 'broadcast': '10.0.2.255'}], -    # 10: [{'addr': 'fe80::a00:27ff:fed9:5b04%eth0', 'netmask': 'ffff:ffff:ffff:ffff::'}] -    # } -    try: -        addresses = ifaddresses(intf) -    except ValueError as e: -        print(e) -        return False - -    # determine IP version (AF_INET or AF_INET6) depending on passed address -    addr_type = AF_INET if is_ipv4(address) else AF_INET6 - -    # Check every IP address on this interface for a match -    netmask = None -    if '/' in address: -        address, netmask = address.split('/') -    for ip in addresses.get(addr_type, []): -        # ip can have the interface name in the 'addr' field, we need to remove it -        # {'addr': 'fe80::a00:27ff:fec5:f821%eth2', 'netmask': 'ffff:ffff:ffff:ffff::'} -        ip_addr = ip['addr'].split('%')[0] - -        if not _are_same_ip(address, ip_addr): -            continue - -        # we do not have a netmask to compare against, they are the same -        if not netmask: -            return True - -        prefixlen = '' -        if is_ipv4(ip_addr): -            prefixlen = sum([bin(int(_)).count('1') for _ in ip['netmask'].split('.')]) -        else: -            prefixlen = sum([bin(int(_,16)).count('1') for _ in ip['netmask'].split('/')[0].split(':') if _]) +    import json +    import jmespath +    from vyos.util import rc_cmd +    from ipaddress import ip_interface -        if str(prefixlen) == netmask: -            return True +    within_netns = f'ip netns exec {netns}' if netns else '' +    rc, out = rc_cmd(f'{within_netns} ip --json address show dev {ifname}') +    if rc == 0: +        json_out = json.loads(out) +        addresses = jmespath.search("[].addr_info[].{family: family, address: local, prefixlen: prefixlen}", json_out) +        for address_info in addresses: +            family = address_info['family'] +            address = address_info['address'] +            prefixlen = address_info['prefixlen'] +            # Remove the interface name if present in the given address +            if '%' in addr: +                addr = addr.split('%')[0] +            interface = ip_interface(f"{address}/{prefixlen}") +            if ip_interface(addr) == interface or address == addr: +                return True      return False | 
