1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <netinet/ether.h>
23 #include <linux/netdevice.h>
27 #include "link-config.h"
28 #include "ethtool-util.h"
30 #include "libudev-private.h"
35 #include "path-util.h"
36 #include "conf-parser.h"
37 #include "conf-files.h"
38 #include "rtnl-util.h"
39 #include "network-internal.h"
41 struct link_config_ctx {
42 LIST_HEAD(link_config, links);
46 bool enable_name_policy;
50 usec_t link_dirs_ts_usec;
53 static const char* const link_dirs[] = {
54 "/etc/systemd/network",
55 "/run/systemd/network",
56 "/usr/lib/systemd/network",
58 "/lib/systemd/network",
62 static void link_config_free(link_config *link) {
68 free(link->match_mac);
69 free(link->match_path);
70 free(link->match_driver);
71 free(link->match_type);
72 free(link->match_name);
73 free(link->match_host);
74 free(link->match_virt);
75 free(link->match_kernel);
76 free(link->match_arch);
78 free(link->description);
80 free(link->name_policy);
87 DEFINE_TRIVIAL_CLEANUP_FUNC(link_config*, link_config_free);
89 static void link_configs_free(link_config_ctx *ctx) {
90 link_config *link, *link_next;
95 LIST_FOREACH_SAFE(links, link, link_next, ctx->links)
96 link_config_free(link);
99 void link_config_ctx_free(link_config_ctx *ctx) {
103 safe_close(ctx->ethtool_fd);
105 sd_rtnl_unref(ctx->rtnl);
107 link_configs_free(ctx);
114 DEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
116 int link_config_ctx_new(link_config_ctx **ret) {
117 _cleanup_(link_config_ctx_freep) link_config_ctx *ctx = NULL;
122 ctx = new0(link_config_ctx, 1);
126 LIST_HEAD_INIT(ctx->links);
128 ctx->ethtool_fd = -1;
130 ctx->enable_name_policy = true;
138 static int load_link(link_config_ctx *ctx, const char *filename) {
139 _cleanup_(link_config_freep) link_config *link = NULL;
140 _cleanup_fclose_ FILE *file = NULL;
146 file = fopen(filename, "re");
154 if (null_or_empty_fd(fileno(file))) {
155 log_debug("Skipping empty file: %s", filename);
159 link = new0(link_config, 1);
163 link->mac_policy = _MACPOLICY_INVALID;
164 link->wol = _WOL_INVALID;
165 link->duplex = _DUP_INVALID;
167 r = config_parse(NULL, filename, file,
168 "Match\0Link\0Ethernet\0",
169 config_item_perf_lookup, link_config_gperf_lookup,
170 false, false, true, link);
174 log_debug("Parsed configuration file %s", filename);
176 link->filename = strdup(filename);
178 LIST_PREPEND(links, ctx->links, link);
184 static bool enable_name_policy(void) {
185 _cleanup_free_ char *line = NULL;
186 const char *word, *state;
190 r = proc_cmdline(&line);
192 log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m");
196 FOREACH_WORD_QUOTED(word, l, line, state)
197 if (strneq(word, "net.ifnames=0", l))
203 int link_config_load(link_config_ctx *ctx) {
205 _cleanup_strv_free_ char **files;
208 link_configs_free(ctx);
210 if (!enable_name_policy()) {
211 ctx->enable_name_policy = false;
212 log_info("Network interface NamePolicy= disabled on kernel command line, ignoring.");
215 /* update timestamp */
216 paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
218 r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
220 return log_error_errno(r, "failed to enumerate link files: %m");
222 STRV_FOREACH_BACKWARDS(f, files) {
223 r = load_link(ctx, *f);
231 bool link_config_should_reload(link_config_ctx *ctx) {
232 return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false);
235 int link_config_get(link_config_ctx *ctx, struct udev_device *device,
239 LIST_FOREACH(links, link, ctx->links) {
240 const char* attr_value;
242 attr_value = udev_device_get_sysattr_value(device, "address");
244 if (net_match_config(link->match_mac, link->match_path, link->match_driver,
245 link->match_type, link->match_name, link->match_host,
246 link->match_virt, link->match_kernel, link->match_arch,
247 attr_value ? ether_aton(attr_value) : NULL,
248 udev_device_get_property_value(device, "ID_PATH"),
249 udev_device_get_driver(udev_device_get_parent(device)),
250 udev_device_get_property_value(device, "ID_NET_DRIVER"),
251 udev_device_get_devtype(device),
252 udev_device_get_sysname(device))) {
253 if (link->match_name) {
254 unsigned char name_assign_type = NET_NAME_UNKNOWN;
256 attr_value = udev_device_get_sysattr_value(device, "name_assign_type");
258 (void)safe_atou8(attr_value, &name_assign_type);
260 if (name_assign_type == NET_NAME_ENUM) {
261 log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
262 link->filename, udev_device_get_sysname(device));
266 } else if (name_assign_type == NET_NAME_RENAMED) {
267 log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
268 link->filename, udev_device_get_sysname(device));
274 log_debug("Config file %s applies to device %s",
275 link->filename, udev_device_get_sysname(device));
288 static bool mac_is_random(struct udev_device *device) {
293 /* if we can't get the assign type, assume it is not random */
294 s = udev_device_get_sysattr_value(device, "addr_assign_type");
298 r = safe_atou(s, &type);
302 return type == NET_ADDR_RANDOM;
305 static bool should_rename(struct udev_device *device, bool respect_predictable) {
310 /* if we can't get the assgin type, assume we should rename */
311 s = udev_device_get_sysattr_value(device, "name_assign_type");
315 r = safe_atou(s, &type);
321 case NET_NAME_RENAMED:
322 /* these were already named by userspace, do not touch again */
324 case NET_NAME_PREDICTABLE:
325 /* the kernel claims to have given a predictable name */
326 if (respect_predictable)
331 /* the name is known to be bad, or of an unknown type */
336 static int get_mac(struct udev_device *device, bool want_random,
337 struct ether_addr *mac) {
341 random_bytes(mac->ether_addr_octet, ETH_ALEN);
345 r = net_get_unique_predictable_data(device, result);
349 assert_cc(ETH_ALEN <= sizeof(result));
350 memcpy(mac->ether_addr_octet, result, ETH_ALEN);
353 /* see eth_random_addr in the kernel */
354 mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
355 mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
360 int link_config_apply(link_config_ctx *ctx, link_config *config,
361 struct udev_device *device, const char **name) {
362 const char *old_name;
363 const char *new_name = NULL;
364 struct ether_addr generated_mac;
365 struct ether_addr *mac = NULL;
366 bool respect_predictable = false;
374 old_name = udev_device_get_sysname(device);
378 r = ethtool_set_speed(&ctx->ethtool_fd, old_name, config->speed / 1024,
381 log_warning_errno(r, "Could not set speed or duplex of %s to %u Mbps (%s): %m",
382 old_name, config->speed / 1024,
383 duplex_to_string(config->duplex));
385 r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol);
387 log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m",
388 old_name, wol_to_string(config->wol));
390 ifindex = udev_device_get_ifindex(device);
392 log_warning("Could not find ifindex");
396 if (ctx->enable_name_policy && config->name_policy) {
399 for (policy = config->name_policy;
400 !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
402 case NAMEPOLICY_KERNEL:
403 respect_predictable = true;
405 case NAMEPOLICY_DATABASE:
406 new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE");
408 case NAMEPOLICY_ONBOARD:
409 new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
411 case NAMEPOLICY_SLOT:
412 new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
414 case NAMEPOLICY_PATH:
415 new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
418 new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC");
426 if (should_rename(device, respect_predictable)) {
427 /* if not set by policy, fall back manually set name */
429 new_name = config->name;
433 switch (config->mac_policy) {
434 case MACPOLICY_PERSISTENT:
435 if (mac_is_random(device)) {
436 r = get_mac(device, false, &generated_mac);
438 log_warning_errno(r, "Could not generate persistent MAC address for %s: %m", old_name);
442 mac = &generated_mac;
445 case MACPOLICY_RANDOM:
446 if (!mac_is_random(device)) {
447 r = get_mac(device, true, &generated_mac);
449 log_warning_errno(r, "Could not generate random MAC address for %s: %m", old_name);
453 mac = &generated_mac;
460 r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac,
463 return log_warning_errno(r, "Could not set Alias, MACAddress or MTU on %s: %m", old_name);
470 int link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) {
475 name = udev_device_get_sysname(device);
479 r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver);
487 static const char* const mac_policy_table[_MACPOLICY_MAX] = {
488 [MACPOLICY_PERSISTENT] = "persistent",
489 [MACPOLICY_RANDOM] = "random"
492 DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
493 DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy,
494 "Failed to parse MAC address policy");
496 static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
497 [NAMEPOLICY_KERNEL] = "kernel",
498 [NAMEPOLICY_DATABASE] = "database",
499 [NAMEPOLICY_ONBOARD] = "onboard",
500 [NAMEPOLICY_SLOT] = "slot",
501 [NAMEPOLICY_PATH] = "path",
502 [NAMEPOLICY_MAC] = "mac"
505 DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
506 DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy,
508 "Failed to parse interface name policy");