chiark / gitweb /
udev: net_setup - clarify reason for failure of persistent mac address policy
[elogind.git] / src / udev / net / link-config.c
index 5aefb7d415e4dc2fd4fcfe192502494b7c0d9fe0..8b3dc45d4e00b83bdeaf166dccd77f395c1c249a 100644 (file)
@@ -20,6 +20,7 @@
 ***/
 
 #include <netinet/ether.h>
+#include <linux/netdevice.h>
 
 #include "sd-id128.h"
 
@@ -62,48 +63,41 @@ static const char* const link_dirs[] = {
 #endif
         NULL};
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
-#define _cleanup_link_config_ctx_free_ _cleanup_(link_config_ctx_freep)
-
-int link_config_ctx_new(link_config_ctx **ret) {
-        _cleanup_link_config_ctx_free_ link_config_ctx *ctx = NULL;
-
-        if (!ret)
-                return -EINVAL;
-
-        ctx = new0(link_config_ctx, 1);
-        if (!ctx)
-                return -ENOMEM;
-
-        LIST_HEAD_INIT(ctx->links);
-
-        ctx->ethtool_fd = -1;
-
-        ctx->enable_name_policy = true;
-
-        *ret = ctx;
-        ctx = NULL;
+static void link_config_free(link_config *link) {
+        if (!link)
+                return;
 
-        return 0;
+        free(link->filename);
+
+        free(link->match_mac);
+        free(link->match_path);
+        free(link->match_driver);
+        free(link->match_type);
+        free(link->match_name);
+        free(link->match_host);
+        free(link->match_virt);
+        free(link->match_kernel);
+        free(link->match_arch);
+
+        free(link->description);
+        free(link->mac);
+        free(link->name_policy);
+        free(link->name);
+        free(link->alias);
+
+        free(link);
 }
 
+DEFINE_TRIVIAL_CLEANUP_FUNC(link_config*, link_config_free);
+
 static void link_configs_free(link_config_ctx *ctx) {
         link_config *link, *link_next;
 
         if (!ctx)
                 return;
 
-        LIST_FOREACH_SAFE(links, link, link_next, ctx->links) {
-                free(link->filename);
-                free(link->match_path);
-                free(link->match_driver);
-                free(link->match_type);
-                free(link->description);
-                free(link->alias);
-                free(link->name_policy);
-
-                free(link);
-        }
+        LIST_FOREACH_SAFE(links, link, link_next, ctx->links)
+                link_config_free(link);
 }
 
 void link_config_ctx_free(link_config_ctx *ctx) {
@@ -121,8 +115,32 @@ 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;
+
+        if (!ret)
+                return -EINVAL;
+
+        ctx = new0(link_config_ctx, 1);
+        if (!ctx)
+                return -ENOMEM;
+
+        LIST_HEAD_INIT(ctx->links);
+
+        ctx->ethtool_fd = -1;
+
+        ctx->enable_name_policy = true;
+
+        *ret = ctx;
+        ctx = NULL;
+
+        return 0;
+}
+
 static int load_link(link_config_ctx *ctx, const char *filename) {
-        _cleanup_free_ link_config *link = NULL;
+        _cleanup_(link_config_freep) link_config *link = NULL;
         _cleanup_fclose_ FILE *file = NULL;
         int r;
 
@@ -175,7 +193,7 @@ static bool enable_name_policy(void) {
 
         r = proc_cmdline(&line);
         if (r < 0) {
-                log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
+                log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m");
                 return true;
         }
 
@@ -202,10 +220,8 @@ int link_config_load(link_config_ctx *ctx) {
         paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
 
         r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
-        if (r < 0) {
-                log_error("failed to enumerate link files: %s", strerror(-r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "failed to enumerate link files: %m");
 
         STRV_FOREACH_BACKWARDS(f, files) {
                 r = load_link(ctx, *f);
@@ -225,21 +241,45 @@ int link_config_get(link_config_ctx *ctx, struct udev_device *device,
         link_config *link;
 
         LIST_FOREACH(links, link, ctx->links) {
-                const char* attr_value = udev_device_get_sysattr_value(device, "address");
+                const char* attr_value;
+
+                attr_value = udev_device_get_sysattr_value(device, "address");
 
                 if (net_match_config(link->match_mac, link->match_path, link->match_driver,
-                                     link->match_type, NULL, link->match_host,
+                                     link->match_type, link->match_name, link->match_host,
                                      link->match_virt, link->match_kernel, link->match_arch,
                                      attr_value ? ether_aton(attr_value) : NULL,
                                      udev_device_get_property_value(device, "ID_PATH"),
                                      udev_device_get_driver(udev_device_get_parent(device)),
                                      udev_device_get_property_value(device, "ID_NET_DRIVER"),
                                      udev_device_get_devtype(device),
-                                     NULL)) {
+                                     udev_device_get_sysname(device))) {
+                        if (link->match_name) {
+                                unsigned char name_assign_type = NET_NAME_UNKNOWN;
+
+                                attr_value = udev_device_get_sysattr_value(device, "name_assign_type");
+                                if (attr_value)
+                                        (void)safe_atou8(attr_value, &name_assign_type);
+
+                                if (name_assign_type == NET_NAME_ENUM) {
+                                        log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
+                                                  link->filename, udev_device_get_sysname(device));
+                                        *ret = link;
+
+                                        return 0;
+                                } else if (name_assign_type == NET_NAME_RENAMED) {
+                                        log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
+                                                  link->filename, udev_device_get_sysname(device));
+
+                                        continue;
+                                }
+                        }
+
                         log_debug("Config file %s applies to device %s",
-                                  link->filename,
-                                  udev_device_get_sysname(device));
+                                  link->filename,  udev_device_get_sysname(device));
+
                         *ret = link;
+
                         return 0;
                 }
         }
@@ -342,14 +382,14 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
         r = ethtool_set_speed(&ctx->ethtool_fd, old_name, config->speed / 1024,
                               config->duplex);
         if (r < 0)
-                log_warning("Could not set speed or duplex of %s to %u Mbps (%s): %s",
-                            old_name, config->speed / 1024,
-                            duplex_to_string(config->duplex), strerror(-r));
+                log_warning_errno(r, "Could not set speed or duplex of %s to %u Mbps (%s): %m",
+                                  old_name, config->speed / 1024,
+                                  duplex_to_string(config->duplex));
 
         r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol);
         if (r < 0)
-                log_warning("Could not set WakeOnLan of %s to %s: %s",
-                            old_name, wol_to_string(config->wol), strerror(-r));
+                log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m",
+                                  old_name, wol_to_string(config->wol));
 
         ifindex = udev_device_get_ifindex(device);
         if (ifindex <= 0) {
@@ -398,9 +438,10 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
                 case MACPOLICY_PERSISTENT:
                         if (mac_is_random(device)) {
                                 r = get_mac(device, false, &generated_mac);
-                                if (r == -ENOENT)
+                                if (r == -ENOENT) {
+                                        log_warning_errno(r, "Could not generate persistent MAC address for %s: %m", old_name);
                                         break;
-                                else if (r < 0)
+                                else if (r < 0)
                                         return r;
                                 mac = &generated_mac;
                         }
@@ -408,9 +449,10 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
                 case MACPOLICY_RANDOM:
                         if (!mac_is_random(device)) {
                                 r = get_mac(device, true, &generated_mac);
-                                if (r == -ENOENT)
+                                if (r == -ENOENT) {
+                                        log_warning_errno(r, "Could not generate random MAC address for %s: %m", old_name);
                                         break;
-                                else if (r < 0)
+                                else if (r < 0)
                                         return r;
                                 mac = &generated_mac;
                         }
@@ -421,11 +463,8 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
 
         r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac,
                                      config->mtu);
-        if (r < 0) {
-                log_warning("Could not set Alias, MACAddress or MTU on %s: %s",
-                            old_name, strerror(-r));
-                return r;
-        }
+        if (r < 0)
+                return log_warning_errno(r, "Could not set Alias, MACAddress or MTU on %s: %m", old_name);
 
         *name = new_name;