diff options
author | Thomas Mangin <thomas.mangin@exa.net.uk> | 2020-03-30 22:31:29 +0100 |
---|---|---|
committer | Thomas Mangin <thomas.mangin@exa.net.uk> | 2020-03-30 22:31:29 +0100 |
commit | e2f80e57d9895d207edf0ad92c299dc7862087d6 (patch) | |
tree | f7f3fcb13a09d2632d7f5fa914ae2f2e35dcee19 | |
parent | 272d6a0968fb22bda0c82068ed1cbf7d9ddd3fd9 (diff) | |
download | vyos-1x-e2f80e57d9895d207edf0ad92c299dc7862087d6.tar.gz vyos-1x-e2f80e57d9895d207edf0ad92c299dc7862087d6.zip |
validate: T2182: IPv6 are not normalised when compared
Adding an already existing IP address on an interface would cause
the 'ip addr add' command to fail. To prevent this, the code checks
if the IP already exists on the interface.
The code was not normalising the different ways of
representing the IPv6 address (trailing 0, ::, etc.).
-rw-r--r-- | python/vyos/validate.py | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/python/vyos/validate.py b/python/vyos/validate.py index 0e6d34e7e..b110a62fa 100644 --- a/python/vyos/validate.py +++ b/python/vyos/validate.py @@ -13,6 +13,7 @@ # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see <http://www.gnu.org/licenses/>. +import socket import netifaces import ipaddress @@ -83,6 +84,8 @@ def is_intf_addr_assigned(intf, addr): print(e) return False + addr_host, addr_mask = addr.split('/') + 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]: @@ -92,23 +95,24 @@ def is_intf_addr_assigned(intf, addr): 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) - + # 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) + 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 + # the netmask are different + if prefixlen != addr_mask: + continue - elif ip['addr'] == addr: - return True + addr_af = socket.AF_INET if is_ipv4(addr_host) else socket.AF_INET6 + ip_af = socket.AF_INET if is_ipv4(ip['addr']) else socket.AF_INET6 + + # compare the binary representation of the IP + if socket.inet_pton(addr_af, addr_host) == socket.inet_pton(ip_af, ip['addr']): + return True return False |