]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/udev/net/link-config.c
udev: introduce NAMING_STABLE_VIRTUAL_MACS (retroactively)
[thirdparty/systemd.git] / src / udev / net / link-config.c
index b54090046e71a826357882bc83f377e973368e8e..b983f28f2fbb058328456027567b0350ce76f955 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <linux/netdevice.h>
 #include <netinet/ether.h>
 
 #include "sd-device.h"
@@ -14,7 +15,7 @@
 #include "fd-util.h"
 #include "link-config.h"
 #include "log.h"
-#include "missing_network.h"
+#include "memory-util.h"
 #include "naming-scheme.h"
 #include "netlink-util.h"
 #include "network-internal.h"
@@ -26,7 +27,6 @@
 #include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
-#include "util.h"
 
 struct link_config_ctx {
         LIST_HEAD(link_config, links);
@@ -50,12 +50,8 @@ static void link_config_free(link_config *link) {
         strv_free(link->match_path);
         strv_free(link->match_driver);
         strv_free(link->match_type);
-        free(link->match_name);
-        free(link->match_host);
-        free(link->match_virt);
-        free(link->match_kernel_cmdline);
-        free(link->match_kernel_version);
-        free(link->match_arch);
+        strv_free(link->match_name);
+        condition_free_list(link->conditions);
 
         free(link->description);
         free(link->mac);
@@ -93,8 +89,6 @@ void link_config_ctx_free(link_config_ctx *ctx) {
         return;
 }
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
-
 int link_config_ctx_new(link_config_ctx **ret) {
         _cleanup_(link_config_ctx_freep) link_config_ctx *ctx = NULL;
 
@@ -116,39 +110,43 @@ int link_config_ctx_new(link_config_ctx **ret) {
         return 0;
 }
 
-static int load_link(link_config_ctx *ctx, const char *filename) {
+int link_load_one(link_config_ctx *ctx, const char *filename) {
         _cleanup_(link_config_freep) link_config *link = NULL;
         _cleanup_fclose_ FILE *file = NULL;
-        int i;
+        _cleanup_free_ char *name = NULL;
+        size_t i;
         int r;
 
         assert(ctx);
         assert(filename);
 
         file = fopen(filename, "re");
-        if (!file) {
-                if (errno == ENOENT)
-                        return 0;
-                else
-                        return -errno;
-        }
+        if (!file)
+                return errno == ENOENT ? 0 : -errno;
 
         if (null_or_empty_fd(fileno(file))) {
                 log_debug("Skipping empty file: %s", filename);
                 return 0;
         }
 
-        link = new0(link_config, 1);
+        name = strdup(filename);
+        if (!name)
+                return -ENOMEM;
+
+        link = new(link_config, 1);
         if (!link)
-                return log_oom();
+                return -ENOMEM;
 
-        link->mac_policy = _MACPOLICY_INVALID;
-        link->wol = _WOL_INVALID;
-        link->duplex = _DUP_INVALID;
-        link->port = _NET_DEV_PORT_INVALID;
-        link->autonegotiation = -1;
+        *link = (link_config) {
+                .filename = TAKE_PTR(name),
+                .mac_address_policy = _MAC_ADDRESS_POLICY_INVALID,
+                .wol = _WOL_INVALID,
+                .duplex = _DUP_INVALID,
+                .port = _NET_DEV_PORT_INVALID,
+                .autonegotiation = -1,
+        };
 
-        for (i = 0; i < (int)ELEMENTSOF(link->features); i++)
+        for (i = 0; i < ELEMENTSOF(link->features); i++)
                 link->features[i] = -1;
 
         r = config_parse(NULL, filename, file,
@@ -157,19 +155,26 @@ static int load_link(link_config_ctx *ctx, const char *filename) {
                          CONFIG_PARSE_WARN, link);
         if (r < 0)
                 return r;
-        else
-                log_debug("Parsed configuration file %s", filename);
 
         if (link->speed > UINT_MAX)
                 return -ERANGE;
 
-        link->filename = strdup(filename);
-        if (!link->filename)
-                return log_oom();
+        if (set_isempty(link->match_mac) && strv_isempty(link->match_path) &&
+            strv_isempty(link->match_driver) && strv_isempty(link->match_type) &&
+            strv_isempty(link->match_name) && !link->conditions)
+                log_warning("%s: No valid settings found in the [Match] section. "
+                            "The file will match all interfaces. "
+                            "If that is intended, please add OriginalName=* in the [Match] section.",
+                            filename);
+
+        if (!condition_test_list(link->conditions, NULL, NULL, NULL)) {
+                log_debug("%s: Conditions do not match the system environment, skipping.", filename);
+                return 0;
+        }
 
-        LIST_PREPEND(links, ctx->links, link);
-        link = NULL;
+        log_debug("Parsed configuration file %s", filename);
 
+        LIST_PREPEND(links, ctx->links, TAKE_PTR(link));
         return 0;
 }
 
@@ -215,9 +220,9 @@ int link_config_load(link_config_ctx *ctx) {
                 return log_error_errno(r, "failed to enumerate link files: %m");
 
         STRV_FOREACH_BACKWARDS(f, files) {
-                r = load_link(ctx, *f);
+                r = link_load_one(ctx, *f);
                 if (r < 0)
-                        return r;
+                        log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
         }
 
         return 0;
@@ -244,9 +249,7 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
                 (void) sd_device_get_sysname(device, &sysname);
 
                 if (net_match_config(link->match_mac, link->match_path, link->match_driver,
-                                     link->match_type, link->match_name, link->match_host,
-                                     link->match_virt, link->match_kernel_cmdline,
-                                     link->match_kernel_version, link->match_arch,
+                                     link->match_type, link->match_name,
                                      address ? ether_aton(address) : NULL,
                                      id_path,
                                      id_net_driver,
@@ -257,7 +260,7 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
 
                                 (void) link_unsigned_attribute(device, "name_assign_type", &name_assign_type);
 
-                                if (name_assign_type == NET_NAME_ENUM) {
+                                if (name_assign_type == NET_NAME_ENUM && !strv_contains(link->match_name, "*")) {
                                         log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
                                                     link->filename, sysname);
                                         *ret = link;
@@ -283,12 +286,12 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
         return -ENOENT;
 }
 
-static int get_mac(sd_device *device, MACPolicy policy, struct ether_addr *mac) {
+static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr *mac) {
         unsigned addr_type;
-        bool want_random = policy == MACPOLICY_RANDOM;
+        bool want_random = policy == MAC_ADDRESS_POLICY_RANDOM;
         int r;
 
-        assert(IN_SET(policy, MACPOLICY_RANDOM, MACPOLICY_PERSISTENT));
+        assert(IN_SET(policy, MAC_ADDRESS_POLICY_RANDOM, MAC_ADDRESS_POLICY_PERSISTENT));
 
         r = link_unsigned_attribute(device, "addr_assign_type", &addr_type);
         if (r < 0)
@@ -307,7 +310,7 @@ static int get_mac(sd_device *device, MACPolicy policy, struct ether_addr *mac)
 
         if (want_random == (addr_type == NET_ADDR_RANDOM))
                 return log_device_debug(device, "MAC on the device already matches policy *%s*",
-                                        mac_policy_to_string(policy));
+                                        mac_address_policy_to_string(policy));
 
         if (want_random) {
                 log_device_debug(device, "Using random bytes to generate MAC");
@@ -315,10 +318,13 @@ static int get_mac(sd_device *device, MACPolicy policy, struct ether_addr *mac)
         } else {
                 uint64_t result;
 
-                r = net_get_unique_predictable_data(device, &result);
+                r = net_get_unique_predictable_data(device,
+                                                    naming_scheme_has(NAMING_STABLE_VIRTUAL_MACS),
+                                                    &result);
                 if (r < 0)
                         return log_device_warning_errno(device, r, "Could not generate persistent MAC: %m");
 
+                log_device_debug(device, "Using generated persistent MAC address");
                 assert_cc(ETH_ALEN <= sizeof(result));
                 memcpy(mac->ether_addr_octet, &result, ETH_ALEN);
         }
@@ -447,8 +453,8 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
                 log_device_debug(device, "Policies didn't yield a name and Name= is not given, not renaming.");
  no_rename:
 
-        if (IN_SET(config->mac_policy, MACPOLICY_PERSISTENT, MACPOLICY_RANDOM)) {
-                if (get_mac(device, config->mac_policy, &generated_mac) > 0)
+        if (IN_SET(config->mac_address_policy, MAC_ADDRESS_POLICY_PERSISTENT, MAC_ADDRESS_POLICY_RANDOM)) {
+                if (get_mac(device, config->mac_address_policy, &generated_mac) > 0)
                         mac = &generated_mac;
         } else
                 mac = config->mac;
@@ -479,14 +485,14 @@ int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret) {
         return 0;
 }
 
-static const char* const mac_policy_table[_MACPOLICY_MAX] = {
-        [MACPOLICY_PERSISTENT] = "persistent",
-        [MACPOLICY_RANDOM] = "random",
-        [MACPOLICY_NONE] = "none",
+static const char* const mac_address_policy_table[_MAC_ADDRESS_POLICY_MAX] = {
+        [MAC_ADDRESS_POLICY_PERSISTENT] = "persistent",
+        [MAC_ADDRESS_POLICY_RANDOM] = "random",
+        [MAC_ADDRESS_POLICY_NONE] = "none",
 };
 
-DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy,
+DEFINE_STRING_TABLE_LOOKUP(mac_address_policy, MACAddressPolicy);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_address_policy, mac_address_policy, MACAddressPolicy,
                          "Failed to parse MAC address policy");
 
 static const char* const name_policy_table[_NAMEPOLICY_MAX] = {