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 |