diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/vyos/ifconfig/interface.py | 38 | ||||
| -rw-r--r-- | python/vyos/util.py | 22 | 
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 | 
