/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <linux/netdevice.h>
#include <netinet/ether.h>
#include "sd-device.h"
#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"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
-#include "util.h"
struct link_config_ctx {
LIST_HEAD(link_config, links);
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);
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;
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,
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;
}
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;
(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,
(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;
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)
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");
} 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);
}
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;
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] = {