From 752229cf7ef080d7a5dd723e7d9b1aa13e44ecd0 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 4 Aug 2019 23:44:03 +0200 Subject: Python/VyOS validate: improve logic on is_ipv4() and is_ipv6() Previosly the check failed when a network statement was passed which contained host bits set e.g. 192.0.2.1/24. This no longer is an issue b/c this is a valid v4 address. Address is now split on / and validated. --- python/vyos/validate.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'python/vyos/validate.py') diff --git a/python/vyos/validate.py b/python/vyos/validate.py index 8def0a510..8f453f85d 100644 --- a/python/vyos/validate.py +++ b/python/vyos/validate.py @@ -18,22 +18,24 @@ import ipaddress def is_ipv4(addr): """ - Check addr if it is an IPv4 address/network. - - Return True/False + Check addr if it is an IPv4 address/network. Returns True/False """ - if ipaddress.ip_network(addr).version == 4: + + # With the below statement we can check for IPv4 networks and host + # addresses at the same time + if ipaddress.ip_address(addr.split(r'/')[0]).version == 4: return True else: return False def is_ipv6(addr): """ - Check addr if it is an IPv6 address/network. - - Return True/False + Check addr if it is an IPv6 address/network. Returns True/False """ - if ipaddress.ip_network(addr).version == 6: + + # With the below statement we can check for IPv4 networks and host + # addresses at the same time + if ipaddress.ip_network(addr.split(r'/')[0]).version == 6: return True else: return False -- cgit v1.2.3 From 6e9a0162f84a1baca9acf0ca675ab3c574c7e297 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 5 Aug 2019 01:15:20 +0200 Subject: Python/VyOS validate: add helper to check if an address belongs to a given interface --- python/vyos/validate.py | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'python/vyos/validate.py') diff --git a/python/vyos/validate.py b/python/vyos/validate.py index 8f453f85d..fb7fa3051 100644 --- a/python/vyos/validate.py +++ b/python/vyos/validate.py @@ -40,12 +40,9 @@ def is_ipv6(addr): else: return False -def is_addr_assigned(addr): +def is_intf_addr_assigned(intf, addr): """ - Verify if the given IPv4/IPv6 address is assigned to any interface on this - system. - - Return True/False + Verify if the given IPv4/IPv6 address is assigned to specific interface """ # determine IP version (AF_INET or AF_INET6) depending on passed address @@ -53,14 +50,31 @@ def is_addr_assigned(addr): if is_ipv6(addr): addr_type = netifaces.AF_INET6 - for interface in netifaces.interfaces(): - # check if the requested address type is configured at all - if addr_type in netifaces.ifaddresses(interface).keys(): - # Check every IP address on this interface for a match - for ip in netifaces.ifaddresses(interface)[addr_type]: - # Check if it matches to the address requested - if ip['addr'] == addr: - return True + # check if the requested address type is configured at all + try: + netifaces.ifaddresses(intf) + except ValueError as e: + print(e) + return False + + if addr_type in netifaces.ifaddresses(intf).keys(): + # Check every IP address on this interface for a match + for ip in netifaces.ifaddresses(intf)[addr_type]: + # Check if it matches to the address requested + if ip['addr'] == addr: + return True + + return False + +def is_addr_assigned(addr): + """ + Verify if the given IPv4/IPv6 address is assigned to any interface + """ + + for intf in netifaces.interfaces(): + tmp = is_intf_addr_assigned(intf, addr) + if tmp == True: + return True return False -- cgit v1.2.3 From d765eef461e53241cf57bcb6b409dc6fec0efc92 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 5 Aug 2019 11:28:23 +0200 Subject: Python/VyOS validate: extend is_intf_addr_assigned() 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. Used testbench: =============== 20: br0: mtu 1500 qdisc noop state DOWN group default qlen 1000 inet 192.0.2.1/24 brd 192.0.2.255 scope global br0 inet 192.0.3.1/24 brd 192.0.3.255 scope global br0 inet6 2001:db8:2::ffff/64 scope global tentative inet6 2001:db8:1::ffff/64 scope global tentative is_intf_addr_assigned('br0', '192.0.2.1/24') -> True is_intf_addr_assigned('br0', '192.0.2.1') -> True is_intf_addr_assigned('br0', '2001:db8:2::ffff/64') -> True is_intf_addr_assigned('br0', '2001:db8:2::ffff') -> True is_intf_addr_assigned('br0', '192.0.100.1/24') -> False is_intf_addr_assigned('br0', '192.0.100.1') -> False is_intf_addr_assigned('br0', '2001:db8:100::ffff/64') -> False is_intf_addr_assigned('br0', '2001:db8:100::ffff') -> False --- python/vyos/validate.py | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'python/vyos/validate.py') diff --git a/python/vyos/validate.py b/python/vyos/validate.py index fb7fa3051..97a401423 100644 --- a/python/vyos/validate.py +++ b/python/vyos/validate.py @@ -42,7 +42,9 @@ def is_ipv6(addr): def is_intf_addr_assigned(intf, addr): """ - Verify if the given IPv4/IPv6 address is assigned to specific interface + 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. """ # determine IP version (AF_INET or AF_INET6) depending on passed address @@ -61,8 +63,28 @@ def is_intf_addr_assigned(intf, addr): # Check every IP address on this interface for a match for ip in netifaces.ifaddresses(intf)[addr_type]: # Check if it matches to the address requested - if ip['addr'] == addr: - return True + # If passed address contains a '/' indicating a normalized IP + # address we have to take this into account, too + if r'/' in addr: + prefixlen = '' + if is_ipv6(addr): + # Note that currently expanded netmasks are not supported. That means + # 2001:db00::0/24 is a valid argument while 2001:db00::0/ffff:ff00:: not. + # see https://docs.python.org/3/library/ipaddress.html + bits = bin( int(ip['netmask'].replace(':',''), 16) ).count('1') + prefixlen = '/' + str(bits) + + else: + prefixlen = '/' + str(ipaddress.IPv4Network('0.0.0.0/' + ip['netmask']).prefixlen) + + # construct temporary variable holding IPv6 address and netmask + # in CIDR notation + tmp = ip['addr'] + prefixlen + if addr == tmp: + return True + + elif ip['addr'] == addr: + return True return False -- cgit v1.2.3