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>
28 #include "link-config.h"
29 #include "ethtool-util.h"
31 #include "libudev-private.h"
36 #include "path-util.h"
37 #include "conf-parser.h"
38 #include "conf-files.h"
41 #include "rtnl-util.h"
42 #include "network-internal.h"
43 #include "siphash24.h"
45 struct link_config_ctx {
46 LIST_HEAD(link_config, links);
50 bool enable_name_policy;
54 usec_t link_dirs_ts_usec;
57 static const char* const link_dirs[] = {
58 "/etc/systemd/network",
59 "/run/systemd/network",
60 "/usr/lib/systemd/network",
62 "/lib/systemd/network",
66 static void link_config_free(link_config *link) {
72 free(link->match_mac);
73 free(link->match_path);
74 free(link->match_driver);
75 free(link->match_type);
76 free(link->match_name);
77 free(link->match_host);
78 free(link->match_virt);
79 free(link->match_kernel);
80 free(link->match_arch);
82 free(link->description);
84 free(link->name_policy);
91 DEFINE_TRIVIAL_CLEANUP_FUNC(link_config*, link_config_free);
93 static void link_configs_free(link_config_ctx *ctx) {
94 link_config *link, *link_next;
99 LIST_FOREACH_SAFE(links, link, link_next, ctx->links)
100 link_config_free(link);
103 void link_config_ctx_free(link_config_ctx *ctx) {
107 safe_close(ctx->ethtool_fd);
109 sd_rtnl_unref(ctx->rtnl);
111 link_configs_free(ctx);
118 DEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
120 int link_config_ctx_new(link_config_ctx **ret) {
121 _cleanup_(link_config_ctx_freep) link_config_ctx *ctx = NULL;
126 ctx = new0(link_config_ctx, 1);
130 LIST_HEAD_INIT(ctx->links);
132 ctx->ethtool_fd = -1;
134 ctx->enable_name_policy = true;
142 static int load_link(link_config_ctx *ctx, const char *filename) {
143 _cleanup_(link_config_freep) link_config *link = NULL;
144 _cleanup_fclose_ FILE *file = NULL;
150 file = fopen(filename, "re");
158 if (null_or_empty_fd(fileno(file))) {
159 log_debug("Skipping empty file: %s", filename);
163 link = new0(link_config, 1);
167 link->mac_policy = _MACPOLICY_INVALID;
168 link->wol = _WOL_INVALID;
169 link->duplex = _DUP_INVALID;
171 r = config_parse(NULL, filename, file,
172 "Match\0Link\0Ethernet\0",
173 config_item_perf_lookup, link_config_gperf_lookup,
174 false, false, true, link);
178 log_debug("Parsed configuration file %s", filename);
180 link->filename = strdup(filename);
182 LIST_PREPEND(links, ctx->links, link);
188 static bool enable_name_policy(void) {
189 _cleanup_free_ char *line = NULL;
190 const char *word, *state;
194 r = proc_cmdline(&line);
196 log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m");
200 FOREACH_WORD_QUOTED(word, l, line, state)
201 if (strneq(word, "net.ifnames=0", l))
207 int link_config_load(link_config_ctx *ctx) {
209 _cleanup_strv_free_ char **files;
212 link_configs_free(ctx);
214 if (!enable_name_policy()) {
215 ctx->enable_name_policy = false;
216 log_info("Network interface NamePolicy= disabled on kernel command line, ignoring.");
219 /* update timestamp */
220 paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
222 r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
224 return log_error_errno(r, "failed to enumerate link files: %m");
226 STRV_FOREACH_BACKWARDS(f, files) {
227 r = load_link(ctx, *f);
235 bool link_config_should_reload(link_config_ctx *ctx) {
236 return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false);
239 int link_config_get(link_config_ctx *ctx, struct udev_device *device,
243 LIST_FOREACH(links, link, ctx->links) {
244 const char* attr_value;
246 attr_value = udev_device_get_sysattr_value(device, "address");
248 if (net_match_config(link->match_mac, link->match_path, link->match_driver,
249 link->match_type, link->match_name, link->match_host,
250 link->match_virt, link->match_kernel, link->match_arch,
251 attr_value ? ether_aton(attr_value) : NULL,
252 udev_device_get_property_value(device, "ID_PATH"),
253 udev_device_get_driver(udev_device_get_parent(device)),
254 udev_device_get_property_value(device, "ID_NET_DRIVER"),
255 udev_device_get_devtype(device),
256 udev_device_get_sysname(device))) {
257 if (link->match_name) {
258 unsigned char name_assign_type = NET_NAME_UNKNOWN;
260 attr_value = udev_device_get_sysattr_value(device, "name_assign_type");
262 (void)safe_atou8(attr_value, &name_assign_type);
264 if (name_assign_type == NET_NAME_ENUM) {
265 log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
266 link->filename, udev_device_get_sysname(device));
270 } else if (name_assign_type == NET_NAME_RENAMED) {
271 log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
272 link->filename, udev_device_get_sysname(device));
278 log_debug("Config file %s applies to device %s",
279 link->filename, udev_device_get_sysname(device));
292 static bool mac_is_random(struct udev_device *device) {
297 /* if we can't get the assign type, assume it is not random */
298 s = udev_device_get_sysattr_value(device, "addr_assign_type");
302 r = safe_atou(s, &type);
306 return type == NET_ADDR_RANDOM;
309 static bool should_rename(struct udev_device *device, bool respect_predictable) {
314 /* if we can't get the assgin type, assume we should rename */
315 s = udev_device_get_sysattr_value(device, "name_assign_type");
319 r = safe_atou(s, &type);
325 case NET_NAME_RENAMED:
326 /* these were already named by userspace, do not touch again */
328 case NET_NAME_PREDICTABLE:
329 /* the kernel claims to have given a predictable name */
330 if (respect_predictable)
335 /* the name is known to be bad, or of an unknown type */
340 static int get_mac(struct udev_device *device, bool want_random,
341 struct ether_addr *mac) {
345 random_bytes(mac->ether_addr_octet, ETH_ALEN);
349 r = net_get_unique_predictable_data(device, result);
353 assert_cc(ETH_ALEN <= sizeof(result));
354 memcpy(mac->ether_addr_octet, result, ETH_ALEN);
357 /* see eth_random_addr in the kernel */
358 mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
359 mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
364 int link_config_apply(link_config_ctx *ctx, link_config *config,
365 struct udev_device *device, const char **name) {
366 const char *old_name;
367 const char *new_name = NULL;
368 struct ether_addr generated_mac;
369 struct ether_addr *mac = NULL;
370 bool respect_predictable = false;
378 old_name = udev_device_get_sysname(device);
382 r = ethtool_set_speed(&ctx->ethtool_fd, old_name, config->speed / 1024,
385 log_warning_errno(r, "Could not set speed or duplex of %s to %u Mbps (%s): %m",
386 old_name, config->speed / 1024,
387 duplex_to_string(config->duplex));
389 r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol);
391 log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m",
392 old_name, wol_to_string(config->wol));
394 ifindex = udev_device_get_ifindex(device);
396 log_warning("Could not find ifindex");
400 if (ctx->enable_name_policy && config->name_policy) {
403 for (policy = config->name_policy;
404 !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
406 case NAMEPOLICY_KERNEL:
407 respect_predictable = true;
409 case NAMEPOLICY_DATABASE:
410 new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE");
412 case NAMEPOLICY_ONBOARD:
413 new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD");
415 case NAMEPOLICY_SLOT:
416 new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT");
418 case NAMEPOLICY_PATH:
419 new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH");
422 new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC");
430 if (should_rename(device, respect_predictable)) {
431 /* if not set by policy, fall back manually set name */
433 new_name = config->name;
437 switch (config->mac_policy) {
438 case MACPOLICY_PERSISTENT:
439 if (mac_is_random(device)) {
440 r = get_mac(device, false, &generated_mac);
445 mac = &generated_mac;
448 case MACPOLICY_RANDOM:
449 if (!mac_is_random(device)) {
450 r = get_mac(device, true, &generated_mac);
455 mac = &generated_mac;
462 r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac,
465 return log_warning_errno(r, "Could not set Alias, MACAddress or MTU on %s: %m", old_name);
472 int link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) {
477 name = udev_device_get_sysname(device);
481 r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver);
489 static const char* const mac_policy_table[_MACPOLICY_MAX] = {
490 [MACPOLICY_PERSISTENT] = "persistent",
491 [MACPOLICY_RANDOM] = "random"
494 DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
495 DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy,
496 "Failed to parse MAC address policy");
498 static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
499 [NAMEPOLICY_KERNEL] = "kernel",
500 [NAMEPOLICY_DATABASE] = "database",
501 [NAMEPOLICY_ONBOARD] = "onboard",
502 [NAMEPOLICY_SLOT] = "slot",
503 [NAMEPOLICY_PATH] = "path",
504 [NAMEPOLICY_MAC] = "mac"
507 DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
508 DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy,
510 "Failed to parse interface name policy");