summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2020-03-28 11:28:05 +0100
committerChristian Poessinger <christian@poessinger.com>2020-03-28 12:05:41 +0100
commit822e171a0023c3f8f335cda08bcbf70b2d6d4070 (patch)
tree15bea8859399c540db517c46bd78e75a5e005e78 /python
parent0d1c8e4021b8da5c15883b860bd27d4e374bd045 (diff)
downloadvyos-1x-822e171a0023c3f8f335cda08bcbf70b2d6d4070.tar.gz
vyos-1x-822e171a0023c3f8f335cda08bcbf70b2d6d4070.zip
ipv6: T1831: migrate eui64 addressing to XML and python
Diffstat (limited to 'python')
-rw-r--r--python/vyos/ifconfig/interface.py38
-rw-r--r--python/vyos/util.py22
2 files changed, 58 insertions, 2 deletions
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index a2d202466..8b41d6158 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -21,10 +21,10 @@ import time
from copy import deepcopy
from vyos.validate import * # should not * include
-from vyos.config import Config # not used anymore
+from vyos.util import mac2eui64
from vyos import ConfigError
-from ipaddress import IPv4Network, IPv6Address
+from ipaddress import IPv4Network, IPv6Address, IPv6Network
from netifaces import ifaddresses, AF_INET, AF_INET6
from time import sleep
from os.path import isfile
@@ -393,6 +393,40 @@ class Interface(DHCP):
"""
return self.set_interface('ipv6_autoconf', autoconf)
+ def set_ipv6_eui64_address(self, prefix):
+ """
+ Extended Unique Identifier (EUI), as per RFC2373, allows a host to
+ assign iteslf a unique IPv6 address based on a given IPv6 prefix.
+
+ If prefix is passed address is assigned, if prefix is '' address is
+ removed from interface.
+ """
+ # if prefix is an empty string convert it to None so mac2eui64 works
+ # as expected
+ if not prefix:
+ prefix = None
+
+ eui64 = mac2eui64(self.get_mac(), prefix)
+
+ if not prefix:
+ # if prefix is empty - thus removed - we need to walk through all
+ # interface IPv6 addresses and find the one with the calculated
+ # EUI-64 identifier. The address is then removed
+ for addr in self.get_addr():
+ addr_wo_prefix = addr.split('/')[0]
+ if is_ipv6(addr_wo_prefix):
+ if eui64 in IPv6Address(addr_wo_prefix).exploded:
+ self.del_addr(addr)
+
+ return None
+
+ # calculate and add EUI-64 IPv6 address
+ if IPv6Network(prefix):
+ # we also need to take the subnet length into account
+ prefix = prefix.split('/')[1]
+ eui64 = f'{eui64}/{prefix}'
+ self.add_addr(eui64 )
+
def set_ipv6_forwarding(self, forwarding):
"""
Configure IPv6 interface-specific Host/Router behaviour.
diff --git a/python/vyos/util.py b/python/vyos/util.py
index e8727c192..635b11ee5 100644
--- a/python/vyos/util.py
+++ b/python/vyos/util.py
@@ -207,3 +207,25 @@ def is_admin() -> bool:
current_user = getuser()
(_, _, _, admin_group_members) = getgrnam('sudo')
return current_user in admin_group_members
+
+
+def mac2eui64(mac, prefix=None):
+ '''
+ Convert a MAC address to a EUI64 address or, with prefix provided, a full
+ IPv6 address.
+ Thankfully copied from https://gist.github.com/wido/f5e32576bb57b5cc6f934e177a37a0d3
+ '''
+ # http://tools.ietf.org/html/rfc4291#section-2.5.1
+ eui64 = re.sub(r'[.:-]', '', mac).lower()
+ eui64 = eui64[0:6] + 'fffe' + eui64[6:]
+ eui64 = hex(int(eui64[0:2], 16) ^ 2)[2:].zfill(2) + eui64[2:]
+
+ if prefix is None:
+ return ':'.join(re.findall(r'.{4}', eui64))
+ else:
+ try:
+ net = ip_network(prefix, strict=False)
+ euil = int('0x{0}'.format(eui64), 16)
+ return str(net[euil])
+ except: # pylint: disable=bare-except
+ return