]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/udev/net/link-config.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <netinet/ether.h>
23 #include "sd-netlink.h"
25 #include "alloc-util.h"
26 #include "conf-files.h"
27 #include "conf-parser.h"
28 #include "ethtool-util.h"
30 #include "libudev-private.h"
31 #include "link-config.h"
34 #include "netlink-util.h"
35 #include "network-internal.h"
36 #include "parse-util.h"
37 #include "path-util.h"
38 #include "proc-cmdline.h"
39 #include "random-util.h"
40 #include "stat-util.h"
41 #include "string-table.h"
42 #include "string-util.h"
46 struct link_config_ctx
{
47 LIST_HEAD(link_config
, links
);
51 bool enable_name_policy
;
55 usec_t link_dirs_ts_usec
;
58 static const char* const link_dirs
[] = {
59 "/etc/systemd/network",
60 "/run/systemd/network",
61 "/usr/lib/systemd/network",
63 "/lib/systemd/network",
67 static void link_config_free(link_config
*link
) {
73 free(link
->match_mac
);
74 strv_free(link
->match_path
);
75 strv_free(link
->match_driver
);
76 strv_free(link
->match_type
);
77 free(link
->match_name
);
78 free(link
->match_host
);
79 free(link
->match_virt
);
80 free(link
->match_kernel_cmdline
);
81 free(link
->match_kernel_version
);
82 free(link
->match_arch
);
84 free(link
->description
);
86 free(link
->name_policy
);
93 DEFINE_TRIVIAL_CLEANUP_FUNC(link_config
*, link_config_free
);
95 static void link_configs_free(link_config_ctx
*ctx
) {
96 link_config
*link
, *link_next
;
101 LIST_FOREACH_SAFE(links
, link
, link_next
, ctx
->links
)
102 link_config_free(link
);
105 void link_config_ctx_free(link_config_ctx
*ctx
) {
109 safe_close(ctx
->ethtool_fd
);
111 sd_netlink_unref(ctx
->rtnl
);
113 link_configs_free(ctx
);
120 DEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx
*, link_config_ctx_free
);
122 int link_config_ctx_new(link_config_ctx
**ret
) {
123 _cleanup_(link_config_ctx_freep
) link_config_ctx
*ctx
= NULL
;
128 ctx
= new0(link_config_ctx
, 1);
132 LIST_HEAD_INIT(ctx
->links
);
134 ctx
->ethtool_fd
= -1;
136 ctx
->enable_name_policy
= true;
144 static int load_link(link_config_ctx
*ctx
, const char *filename
) {
145 _cleanup_(link_config_freep
) link_config
*link
= NULL
;
146 _cleanup_fclose_
FILE *file
= NULL
;
152 file
= fopen(filename
, "re");
160 if (null_or_empty_fd(fileno(file
))) {
161 log_debug("Skipping empty file: %s", filename
);
165 link
= new0(link_config
, 1);
169 link
->mac_policy
= _MACPOLICY_INVALID
;
170 link
->wol
= _WOL_INVALID
;
171 link
->duplex
= _DUP_INVALID
;
172 link
->port
= _NET_DEV_PORT_INVALID
;
173 link
->autonegotiation
= -1;
175 memset(&link
->features
, 0xFF, sizeof(link
->features
));
177 r
= config_parse(NULL
, filename
, file
,
178 "Match\0Link\0Ethernet\0",
179 config_item_perf_lookup
, link_config_gperf_lookup
,
180 CONFIG_PARSE_WARN
, link
);
184 log_debug("Parsed configuration file %s", filename
);
186 if (link
->mtu
> UINT_MAX
|| link
->speed
> UINT_MAX
)
189 link
->filename
= strdup(filename
);
193 LIST_PREPEND(links
, ctx
->links
, link
);
199 static bool enable_name_policy(void) {
202 return proc_cmdline_get_bool("net.ifnames", &b
) <= 0 || b
;
205 int link_config_load(link_config_ctx
*ctx
) {
206 _cleanup_strv_free_
char **files
;
210 link_configs_free(ctx
);
212 if (!enable_name_policy()) {
213 ctx
->enable_name_policy
= false;
214 log_info("Network interface NamePolicy= disabled on kernel command line, ignoring.");
217 /* update timestamp */
218 paths_check_timestamp(link_dirs
, &ctx
->link_dirs_ts_usec
, true);
220 r
= conf_files_list_strv(&files
, ".link", NULL
, 0, link_dirs
);
222 return log_error_errno(r
, "failed to enumerate link files: %m");
224 STRV_FOREACH_BACKWARDS(f
, files
) {
225 r
= load_link(ctx
, *f
);
233 bool link_config_should_reload(link_config_ctx
*ctx
) {
234 return paths_check_timestamp(link_dirs
, &ctx
->link_dirs_ts_usec
, false);
237 int link_config_get(link_config_ctx
*ctx
, struct udev_device
*device
,
245 LIST_FOREACH(links
, link
, ctx
->links
) {
246 const char* attr_value
;
248 attr_value
= udev_device_get_sysattr_value(device
, "address");
250 if (net_match_config(link
->match_mac
, link
->match_path
, link
->match_driver
,
251 link
->match_type
, link
->match_name
, link
->match_host
,
252 link
->match_virt
, link
->match_kernel_cmdline
,
253 link
->match_kernel_version
, link
->match_arch
,
254 attr_value
? ether_aton(attr_value
) : NULL
,
255 udev_device_get_property_value(device
, "ID_PATH"),
256 udev_device_get_driver(udev_device_get_parent(device
)),
257 udev_device_get_property_value(device
, "ID_NET_DRIVER"),
258 udev_device_get_devtype(device
),
259 udev_device_get_sysname(device
))) {
260 if (link
->match_name
) {
261 unsigned char name_assign_type
= NET_NAME_UNKNOWN
;
263 attr_value
= udev_device_get_sysattr_value(device
, "name_assign_type");
265 (void) safe_atou8(attr_value
, &name_assign_type
);
267 if (name_assign_type
== NET_NAME_ENUM
) {
268 log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
269 link
->filename
, udev_device_get_sysname(device
));
273 } else if (name_assign_type
== NET_NAME_RENAMED
) {
274 log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
275 link
->filename
, udev_device_get_sysname(device
));
281 log_debug("Config file %s applies to device %s",
282 link
->filename
, udev_device_get_sysname(device
));
295 static bool mac_is_random(struct udev_device
*device
) {
300 /* if we can't get the assign type, assume it is not random */
301 s
= udev_device_get_sysattr_value(device
, "addr_assign_type");
305 r
= safe_atou(s
, &type
);
309 return type
== NET_ADDR_RANDOM
;
312 static bool should_rename(struct udev_device
*device
, bool respect_predictable
) {
317 /* if we can't get the assgin type, assume we should rename */
318 s
= udev_device_get_sysattr_value(device
, "name_assign_type");
322 r
= safe_atou(s
, &type
);
328 case NET_NAME_RENAMED
:
329 /* these were already named by userspace, do not touch again */
331 case NET_NAME_PREDICTABLE
:
332 /* the kernel claims to have given a predictable name */
333 if (respect_predictable
)
338 /* the name is known to be bad, or of an unknown type */
343 static int get_mac(struct udev_device
*device
, bool want_random
,
344 struct ether_addr
*mac
) {
348 random_bytes(mac
->ether_addr_octet
, ETH_ALEN
);
352 r
= net_get_unique_predictable_data(device
, &result
);
356 assert_cc(ETH_ALEN
<= sizeof(result
));
357 memcpy(mac
->ether_addr_octet
, &result
, ETH_ALEN
);
360 /* see eth_random_addr in the kernel */
361 mac
->ether_addr_octet
[0] &= 0xfe; /* clear multicast bit */
362 mac
->ether_addr_octet
[0] |= 0x02; /* set local assignment bit (IEEE802) */
367 int link_config_apply(link_config_ctx
*ctx
, link_config
*config
,
368 struct udev_device
*device
, const char **name
) {
369 bool respect_predictable
= false;
370 struct ether_addr generated_mac
;
371 struct ether_addr
*mac
= NULL
;
372 const char *new_name
= NULL
;
373 const char *old_name
;
382 old_name
= udev_device_get_sysname(device
);
386 r
= ethtool_set_glinksettings(&ctx
->ethtool_fd
, old_name
, config
);
389 if (config
->port
!= _NET_DEV_PORT_INVALID
)
390 log_warning_errno(r
, "Could not set port (%s) of %s: %m", port_to_string(config
->port
), old_name
);
392 speed
= DIV_ROUND_UP(config
->speed
, 1000000);
393 if (r
== -EOPNOTSUPP
)
394 r
= ethtool_set_speed(&ctx
->ethtool_fd
, old_name
, speed
, config
->duplex
);
397 log_warning_errno(r
, "Could not set speed or duplex of %s to %u Mbps (%s): %m",
398 old_name
, speed
, duplex_to_string(config
->duplex
));
401 r
= ethtool_set_wol(&ctx
->ethtool_fd
, old_name
, config
->wol
);
403 log_warning_errno(r
, "Could not set WakeOnLan of %s to %s: %m",
404 old_name
, wol_to_string(config
->wol
));
406 r
= ethtool_set_features(&ctx
->ethtool_fd
, old_name
, config
->features
);
408 log_warning_errno(r
, "Could not set offload features of %s: %m", old_name
);
410 ifindex
= udev_device_get_ifindex(device
);
412 log_warning("Could not find ifindex");
416 if (ctx
->enable_name_policy
&& config
->name_policy
) {
419 for (policy
= config
->name_policy
;
420 !new_name
&& *policy
!= _NAMEPOLICY_INVALID
; policy
++) {
422 case NAMEPOLICY_KERNEL
:
423 respect_predictable
= true;
425 case NAMEPOLICY_DATABASE
:
426 new_name
= udev_device_get_property_value(device
, "ID_NET_NAME_FROM_DATABASE");
428 case NAMEPOLICY_ONBOARD
:
429 new_name
= udev_device_get_property_value(device
, "ID_NET_NAME_ONBOARD");
431 case NAMEPOLICY_SLOT
:
432 new_name
= udev_device_get_property_value(device
, "ID_NET_NAME_SLOT");
434 case NAMEPOLICY_PATH
:
435 new_name
= udev_device_get_property_value(device
, "ID_NET_NAME_PATH");
438 new_name
= udev_device_get_property_value(device
, "ID_NET_NAME_MAC");
446 if (should_rename(device
, respect_predictable
)) {
447 /* if not set by policy, fall back manually set name */
449 new_name
= config
->name
;
453 switch (config
->mac_policy
) {
454 case MACPOLICY_PERSISTENT
:
455 if (mac_is_random(device
)) {
456 r
= get_mac(device
, false, &generated_mac
);
458 log_warning_errno(r
, "Could not generate persistent MAC address for %s: %m", old_name
);
462 mac
= &generated_mac
;
465 case MACPOLICY_RANDOM
:
466 if (!mac_is_random(device
)) {
467 r
= get_mac(device
, true, &generated_mac
);
469 log_warning_errno(r
, "Could not generate random MAC address for %s: %m", old_name
);
473 mac
= &generated_mac
;
481 r
= rtnl_set_link_properties(&ctx
->rtnl
, ifindex
, config
->alias
, mac
, config
->mtu
);
483 return log_warning_errno(r
, "Could not set Alias, MACAddress or MTU on %s: %m", old_name
);
490 int link_get_driver(link_config_ctx
*ctx
, struct udev_device
*device
, char **ret
) {
495 name
= udev_device_get_sysname(device
);
499 r
= ethtool_get_driver(&ctx
->ethtool_fd
, name
, &driver
);
507 static const char* const mac_policy_table
[_MACPOLICY_MAX
] = {
508 [MACPOLICY_PERSISTENT
] = "persistent",
509 [MACPOLICY_RANDOM
] = "random",
510 [MACPOLICY_NONE
] = "none"
513 DEFINE_STRING_TABLE_LOOKUP(mac_policy
, MACPolicy
);
514 DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy
, mac_policy
, MACPolicy
,
515 "Failed to parse MAC address policy");
517 static const char* const name_policy_table
[_NAMEPOLICY_MAX
] = {
518 [NAMEPOLICY_KERNEL
] = "kernel",
519 [NAMEPOLICY_DATABASE
] = "database",
520 [NAMEPOLICY_ONBOARD
] = "onboard",
521 [NAMEPOLICY_SLOT
] = "slot",
522 [NAMEPOLICY_PATH
] = "path",
523 [NAMEPOLICY_MAC
] = "mac"
526 DEFINE_STRING_TABLE_LOOKUP(name_policy
, NamePolicy
);
527 DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy
, name_policy
, NamePolicy
,
529 "Failed to parse interface name policy");