Esempio n. 1
0
 def syntax_check_localip_anycastip_equal(self, ifname, local_ip, anycast_ip):
     try:
         if local_ip and anycast_ip and ipnetwork.IPNetwork(local_ip) == ipnetwork.IPNetwork(anycast_ip):
             self.logger.warning('%s: vxlan-local-tunnelip and clagd-vxlan-anycast-ip are identical (%s)'
                                 % (ifname, local_ip))
             return False
     except Exception:
         pass
     return True
Esempio n. 2
0
class AddonWithIpBlackList(Addon):
    try:
        ip_blacklist = [ipnetwork.IPNetwork(ip).ip for ip in policymanager.policymanager_api.get_module_globals(
            module_name="address",
            attr="ip_blacklist"
        ) or []]
        __ip_blacklist_exception = None
    except Exception as e:
        __ip_blacklist_exception = e
        ip_blacklist = []

    def __init__(self):
        """
        If an exception occurred during the ip blacklist parsing we need to display it (once)
        Also we keep this as a class variable to share it between the address and addressvirtual module
        """
        super(AddonWithIpBlackList, self).__init__()

        if AddonWithIpBlackList.__ip_blacklist_exception:
            self.logger.warning("policy.d: address: 'ip_blacklist': %s" % AddonWithIpBlackList.__ip_blacklist_exception)
            AddonWithIpBlackList.__ip_blacklist_exception = None

    def ip_blacklist_check(self, ifname, ip):
        """
        Check if the ip address is not blacklisted (in ip_blacklist)

        :param ifname:
        :param ip:
        :return:
        """
        if ip.ip in AddonWithIpBlackList.ip_blacklist:
            raise Exception("%s: blacklisted ip address in use: %s" % (ifname, ip.ip))
Esempio n. 3
0
 def convert_user_config_to_ipnetwork(self, user_config, attr_name):
     """
     Ideally this convertion should be done by ifupdown2 at a lower level
     (after parsing /e/n/i) and should be done directly on each ifaceobj.
     """
     try:
         user_config[attr_name] = ipnetwork.IPNetwork(user_config[attr_name])
     except Exception:
         pass
Esempio n. 4
0
    def __config_vxlan_local_tunnelip(self, ifname, ifaceobj, link_exists, user_request_vxlan_info_data, cached_vxlan_ifla_info_data):
        """
        Get vxlan-local-tunnelip user config or policy, validate ip address format and insert in netlink dict
        :param ifname:
        :param ifaceobj:
        :param link_exists:
        :param user_request_vxlan_info_data:
        :param cached_vxlan_ifla_info_data:
        :return:
        """
        local = ifaceobj.get_attr_value_first("vxlan-local-tunnelip")

        if not local and self._vxlan_local_tunnelip:
            local = self._vxlan_local_tunnelip

        if link_exists:
            # on ifreload do not overwrite anycast_ip to individual ip
            # if clagd has modified
            running_localtunnelip = cached_vxlan_ifla_info_data.get(Link.IFLA_VXLAN_LOCAL)

            if self._clagd_vxlan_anycast_ip and running_localtunnelip:
                anycastip = ipnetwork.IPNetwork(self._clagd_vxlan_anycast_ip)
                if anycastip == running_localtunnelip:
                    local = running_localtunnelip

        if not local:
            local = policymanager.policymanager_api.get_attr_default(
                module_name=self.__class__.__name__,
                attr="vxlan-local-tunnelip"
            )

        if local:
            try:
                local = ipnetwork.IPv4Address(local)

                if local.initialized_with_prefixlen:
                    self.logger.warning("%s: vxlan-local-tunnelip %s: netmask ignored" % (ifname, local))

            except Exception as e:
                raise Exception("%s: invalid vxlan-local-tunnelip %s: %s" % (ifname, local, str(e)))

        cached_ifla_vxlan_local = cached_vxlan_ifla_info_data.get(Link.IFLA_VXLAN_LOCAL)

        if local:
            if local != cached_ifla_vxlan_local:
                self.logger.info("%s: set vxlan-local-tunnelip %s" % (ifname, local))
                user_request_vxlan_info_data[Link.IFLA_VXLAN_LOCAL] = local

                # if both local-ip and anycast-ip are identical the function prints a warning
                self.syntax_check_localip_anycastip_equal(ifname, local, self._clagd_vxlan_anycast_ip)
        elif cached_ifla_vxlan_local:
            self.logger.info("%s: removing vxlan-local-tunnelip (cache %s)" % (ifname, cached_ifla_vxlan_local))
            user_request_vxlan_info_data[Link.IFLA_VXLAN_LOCAL] = None

        return local
    def translate_addrvirtual_user_config_to_list(self, ifaceobj,
                                                  address_virtual_list):
        """
        # Translate:
        #       address-virtual 00:11:22:33:44:01 2001:0db8::0370:7334/64 11.0.1.1/24 11.0.1.2/24
        # To:
        # [
        #   {
        #        "ifname": "macvlan_ifname",
        #        "hwaddress": "macvlan_hwaddress",
        #        "ips": [str(IPNetwork), ]
        #    },
        # ]
        """
        user_config_list = []

        if not address_virtual_list:
            return user_config_list

        macvlan_prefix = self._get_macvlan_prefix(ifaceobj)

        for index, addr_virtual in enumerate(address_virtual_list):
            av_attrs = addr_virtual.split()
            mac = av_attrs[0]
            if mac:
                mac = mac.lower()

            if not self.check_mac_address(ifaceobj, mac):
                continue

            config = {
                "ifname": "%s%d" % (macvlan_prefix, index),
                "mode": "private"
            }

            if mac != "none":
                config["hwaddress"] = mac
                config["hwaddress_int"] = utils.mac_str_to_int(mac)

            ip_network_obj_list = []
            for ip in av_attrs[1:]:
                ip_network_obj_list.append(ipnetwork.IPNetwork(ip))

            config["ips"] = ip_network_obj_list
            user_config_list.append(config)

        return user_config_list
Esempio n. 6
0
    def __config_vxlan_group(self, ifname, ifaceobj, link_exists, mcast_grp,
                             group, physdev, user_request_vxlan_info_data,
                             cached_vxlan_ifla_info_data):
        """
        vxlan-mcastgrp and vxlan-svcnodeip are mutually exclusive
        this function validates ip format for both attribute and tries to understand
        what the user really want (remote or group option).

        :param ifname:
        :param ifaceobj:
        :param mcast_grp:
        :param group:
        :param physdev:
        :param user_request_vxlan_info_data:
        :param cached_vxlan_ifla_info_data:
        :return:
        """
        if mcast_grp and group:
            self.log_error(
                "%s: both group (vxlan-mcastgrp %s) and "
                "remote (vxlan-svcnodeip %s) cannot be specified" %
                (ifname, mcast_grp, group), ifaceobj)

        attribute_name = "vxlan-svcnodeip"
        multicast_group_change = False

        if group:
            try:
                group = ipnetwork.IPv4Address(group)

                if group.initialized_with_prefixlen:
                    self.logger.warning(
                        "%s: vxlan-svcnodeip %s: netmask ignored" %
                        (ifname, group))

            except Exception as e:
                raise Exception("%s: invalid vxlan-svcnodeip %s: %s" %
                                (ifname, group, str(e)))

            if group.ip.is_multicast:
                self.logger.warning(
                    "%s: vxlan-svcnodeip %s: invalid group address, "
                    "for multicast IP please use attribute \"vxlan-mcastgrp\""
                    % (ifname, group))
                # if svcnodeip is used instead of mcastgrp we warn the user
                # if mcast_grp is not provided by the user we can instead
                # use the svcnodeip value
                if not physdev:
                    self.log_error(
                        "%s: vxlan: 'group' (vxlan-mcastgrp) requires 'vxlan-physdev' to be specified"
                        % (ifname))

        elif mcast_grp:
            try:
                mcast_grp = ipnetwork.IPv4Address(mcast_grp)

                if mcast_grp.initialized_with_prefixlen:
                    self.logger.warning(
                        "%s: vxlan-mcastgrp %s: netmask ignored" %
                        (ifname, mcast_grp))

            except Exception as e:
                raise Exception("%s: invalid vxlan-mcastgrp %s: %s" %
                                (ifname, mcast_grp, str(e)))

            if not mcast_grp.ip.is_multicast:
                self.logger.warning(
                    "%s: vxlan-mcastgrp %s: invalid group address, "
                    "for non-multicast IP please use attribute \"vxlan-svcnodeip\""
                    % (ifname, mcast_grp))
                # if mcastgrp is specified with a non-multicast address
                # we warn the user. If the svcnodeip wasn't specified by
                # the user we can use the mcastgrp value as svcnodeip
                if not group:
                    group = mcast_grp
                    mcast_grp = None
            else:
                attribute_name = "vxlan-mcastgrp"

            if mcast_grp:
                group = mcast_grp

                if not physdev:
                    self.log_error(
                        "%s: vxlan: 'group' (vxlan-mcastgrp) requires 'vxlan-physdev' to be specified"
                        % (ifname))

        cached_ifla_vxlan_group = cached_vxlan_ifla_info_data.get(
            Link.IFLA_VXLAN_GROUP)

        if group != cached_ifla_vxlan_group:

            if not group:
                group = ipnetwork.IPNetwork("0.0.0.0")
                attribute_name = "vxlan-svcnodeip/vxlan-mcastgrp"

            self.logger.info("%s: set %s %s" % (ifname, attribute_name, group))
            user_request_vxlan_info_data[Link.IFLA_VXLAN_GROUP] = group

            # if the mcastgrp address is changed we need to signal this to the upper function
            # in this case vxlan needs to be down before applying changes then up'd
            multicast_group_change = True

            if link_exists:
                if cached_ifla_vxlan_group:
                    self.logger.info(
                        "%s: vxlan-mcastgrp configuration changed (cache %s): flapping vxlan device required"
                        % (ifname, cached_ifla_vxlan_group))
                else:
                    self.logger.info(
                        "%s: vxlan-mcastgrp configuration changed: flapping vxlan device required"
                        % ifname)

        return group, multicast_group_change
    def translate_vrr_user_config_to_list(self,
                                          ifaceobj,
                                          vrr_config_list,
                                          ifquery=False):
        """
        If (IPv4 addresses provided):
            00:00:5e:00:01:<V>
        else if (IPv6 addresses provided):
            00:00:5e:00:02:<V>

        vrrp 1 10.0.0.15/24
        vrrp 1 2001:0db8::0370:7334/64

        # Translate:
        #       vrrp 255 10.0.0.15/24 10.0.0.2/1
        # To:
        # [
        #   {
        #        "ifname": "macvlan_ifname",
        #        "hwaddress": "macvlan_hwaddress",
        #        "mode": "macvlan_mode",
        #        "ips": [str(IPNetwork), ]
        #    },
        # ]
        """
        ifname = ifaceobj.name
        user_config_list = []

        for index, config in enumerate(vrr_config_list or []):
            vrrp_id, ip_addrs = config.split(" ", 1)
            hex_id = '%02x' % int(vrrp_id)
            ip4 = []
            ip6 = []

            for ip_addr in ip_addrs.split():
                ip_network_obj = ipnetwork.IPNetwork(ip_addr)
                is_ip6 = ip_network_obj.version == 6

                if is_ip6:
                    ip6.append(ip_network_obj)
                else:
                    ip4.append(ip_network_obj)

            macvlan_ip4_ifname = "%s%s" % (self.get_vrrp_prefix(ifname,
                                                                "4"), vrrp_id)
            macvlan_ip6_ifname = "%s%s" % (self.get_vrrp_prefix(ifname,
                                                                "6"), vrrp_id)

            if ip4 or ifquery:
                merged_with_existing_obj = False
                macvlan_ip4_mac = "00:00:5e:00:01:%s" % hex_id
                macvlan_ip4_mac_int = utils.mac_str_to_int(macvlan_ip4_mac)
                # if the vrr config is defined in different lines for the same ID
                # we need to save the ip4 and ip6 in the objects we previously
                # created, example:
                # vrrp 255 10.0.0.15/24 10.0.0.2/15
                # vrrp 255 fe80::a00:27ff:fe04:42/64
                for obj in user_config_list:
                    if obj.get("hwaddress_int") == macvlan_ip4_mac_int:
                        obj["ips"] += ip4
                        merged_with_existing_obj = True

                if not merged_with_existing_obj:
                    # if ip4 config wasn't merge with an existing object
                    # we need to insert it in our list
                    user_config_list.append({
                        "ifname": macvlan_ip4_ifname,
                        "hwaddress": macvlan_ip4_mac,
                        "hwaddress_int": macvlan_ip4_mac_int,
                        "mode": "bridge",
                        "ips": ip4,
                        "id": vrrp_id
                    })
            elif not ip4 and not ifquery:
                # special check to see if all ipv4 were removed from the vrrp
                # configuration, if so we need to remove the associated macvlan
                if self.cache.link_exists(macvlan_ip4_ifname):
                    self.netlink.link_del(macvlan_ip4_ifname)

            if ip6 or ifquery:
                merged_with_existing_obj = False
                macvlan_ip6_mac = "00:00:5e:00:02:%s" % hex_id
                macvlan_ip6_mac_int = utils.mac_str_to_int(macvlan_ip6_mac)
                # if the vrr config is defined in different lines for the same ID
                # we need to save the ip4 and ip6 in the objects we previously
                # created, example:
                # vrrp 255 10.0.0.15/24 10.0.0.2/15
                # vrrp 255 fe80::a00:27ff:fe04:42/64

                for obj in user_config_list:
                    if obj.get("hwaddress_int") == macvlan_ip6_mac_int:
                        obj["ips"] += ip6
                        merged_with_existing_obj = True

                if not merged_with_existing_obj:
                    # if ip6 config wasn't merge with an existing object
                    # we need to insert it in our list
                    user_config_list.append({
                        "ifname": macvlan_ip6_ifname,
                        "hwaddress": macvlan_ip6_mac,
                        "hwaddress_int": macvlan_ip6_mac_int,
                        "mode": "bridge",
                        "ips": ip6,
                        "id": vrrp_id
                    })
            elif not ip6 and not ifquery:
                # special check to see if all ipv6 were removed from the vrrp
                # configuration, if so we need to remove the associated macvlan
                if self.cache.link_exists(macvlan_ip6_ifname):
                    self.netlink.link_del(macvlan_ip6_ifname)

        if not ifquery:
            # check if vrrp attribute was removed/re-assigned
            old_vrr_ids = set()

            try:
                for old_ifaceobj in statemanager.statemanager_api.get_ifaceobjs(
                        ifname) or []:
                    for vrr_config in old_ifaceobj.get_attr_value(
                            "vrrp") or []:
                        try:
                            old_vrr_ids.add(vrr_config.split()[0])
                        except Exception:
                            continue

                if old_vrr_ids:

                    for config in user_config_list:
                        try:
                            old_vrr_ids.remove(config["id"])
                        except KeyError:
                            pass

                    for id_to_remove in old_vrr_ids:
                        macvlan_ip4_ifname = "%s%s" % (self.get_vrrp_prefix(
                            ifname, "4"), id_to_remove)
                        macvlan_ip6_ifname = "%s%s" % (self.get_vrrp_prefix(
                            ifname, "6"), id_to_remove)

                        if self.cache.link_exists(macvlan_ip4_ifname):
                            self.netlink.link_del(macvlan_ip4_ifname)

                        if self.cache.link_exists(macvlan_ip6_ifname):
                            self.netlink.link_del(macvlan_ip6_ifname)

            except Exception as e:
                self.logger.debug(
                    "%s: vrrp: failure while removing unused macvlan(s)" %
                    ifname)

        return user_config_list