]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/udev/net/link-config.c
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"
31 #include "sd-netlink.h"
35 #include "path-util.h"
36 #include "conf-parser.h"
37 #include "conf-files.h"
38 #include "netlink-util.h"
39 #include "network-internal.h"
40 #include "random-util.h"
42 struct link_config_ctx
{
43 LIST_HEAD(link_config
, links
);
47 bool enable_name_policy
;
51 usec_t link_dirs_ts_usec
;
54 static const char* const link_dirs
[] = {
55 "/etc/systemd/network",
56 "/run/systemd/network",
57 "/usr/lib/systemd/network",
59 "/lib/systemd/network",
63 static void link_config_free(link_config
*link
) {
69 free(link
->match_mac
);
70 strv_free(link
->match_path
);
71 strv_free(link
->match_driver
);
72 strv_free(link
->match_type
);
73 free(link
->match_name
);
74 free(link
->match_host
);
75 free(link
->match_virt
);
76 free(link
->match_kernel
);
77 free(link
->match_arch
);
79 free(link
->description
);
81 free(link
->name_policy
);
88 DEFINE_TRIVIAL_CLEANUP_FUNC(link_config
*, link_config_free
);
90 static void link_configs_free(link_config_ctx
*ctx
) {
91 link_config
*link
, *link_next
;
96 LIST_FOREACH_SAFE(links
, link
, link_next
, ctx
->links
)
97 link_config_free(link
);
100 void link_config_ctx_free(link_config_ctx
*ctx
) {
104 safe_close(ctx
->ethtool_fd
);
106 sd_netlink_unref(ctx
->rtnl
);
108 link_configs_free(ctx
);
115 DEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx
*, link_config_ctx_free
);
117 int link_config_ctx_new(link_config_ctx
**ret
) {
118 _cleanup_(link_config_ctx_freep
) link_config_ctx
*ctx
= NULL
;
123 ctx
= new0(link_config_ctx
, 1);
127 LIST_HEAD_INIT(ctx
->links
);
129 ctx
->ethtool_fd
= -1;
131 ctx
->enable_name_policy
= true;
139 static int load_link(link_config_ctx
*ctx
, const char *filename
) {
140 _cleanup_(link_config_freep
) link_config
*link
= NULL
;
141 _cleanup_fclose_
FILE *file
= NULL
;
147 file
= fopen(filename
, "re");
155 if (null_or_empty_fd(fileno(file
))) {
156 log_debug("Skipping empty file: %s", filename
);
160 link
= new0(link_config
, 1);
164 link
->mac_policy
= _MACPOLICY_INVALID
;
165 link
->wol
= _WOL_INVALID
;
166 link
->duplex
= _DUP_INVALID
;
168 r
= config_parse(NULL
, filename
, file
,
169 "Match\0Link\0Ethernet\0",
170 config_item_perf_lookup
, link_config_gperf_lookup
,
171 false, false, true, link
);
175 log_debug("Parsed configuration file %s", filename
);
177 if (link
->mtu
> UINT_MAX
|| link
->speed
> UINT_MAX
)
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
,
247 LIST_FOREACH(links
, link
, ctx
->links
) {
248 const char* attr_value
;
250 attr_value
= udev_device_get_sysattr_value(device
, "address");
252 if (net_match_config(link
->match_mac
, link
->match_path
, link
->match_driver
,
253 link
->match_type
, link
->match_name
, link
->match_host
,
254 link
->match_virt
, link
->match_kernel
, link
->match_arch
,
255 attr_value
? ether_aton(attr_value
) : NULL
,
256 udev_device_get_property_value(device
, "ID_PATH"),
257 udev_device_get_driver(udev_device_get_parent(device
)),
258 udev_device_get_property_value(device
, "ID_NET_DRIVER"),
259 udev_device_get_devtype(device
),
260 udev_device_get_sysname(device
))) {
261 if (link
->match_name
) {
262 unsigned char name_assign_type
= NET_NAME_UNKNOWN
;
264 attr_value
= udev_device_get_sysattr_value(device
, "name_assign_type");
266 (void) safe_atou8(attr_value
, &name_assign_type
);
268 if (name_assign_type
== NET_NAME_ENUM
) {
269 log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
270 link
->filename
, udev_device_get_sysname(device
));
274 } else if (name_assign_type
== NET_NAME_RENAMED
) {
275 log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
276 link
->filename
, udev_device_get_sysname(device
));
282 log_debug("Config file %s applies to device %s",
283 link
->filename
, udev_device_get_sysname(device
));
296 static bool mac_is_random(struct udev_device
*device
) {
301 /* if we can't get the assign type, assume it is not random */
302 s
= udev_device_get_sysattr_value(device
, "addr_assign_type");
306 r
= safe_atou(s
, &type
);
310 return type
== NET_ADDR_RANDOM
;
313 static bool should_rename(struct udev_device
*device
, bool respect_predictable
) {
318 /* if we can't get the assgin type, assume we should rename */
319 s
= udev_device_get_sysattr_value(device
, "name_assign_type");
323 r
= safe_atou(s
, &type
);
329 case NET_NAME_RENAMED
:
330 /* these were already named by userspace, do not touch again */
332 case NET_NAME_PREDICTABLE
:
333 /* the kernel claims to have given a predictable name */
334 if (respect_predictable
)
339 /* the name is known to be bad, or of an unknown type */
344 static int get_mac(struct udev_device
*device
, bool want_random
,
345 struct ether_addr
*mac
) {
349 random_bytes(mac
->ether_addr_octet
, ETH_ALEN
);
353 r
= net_get_unique_predictable_data(device
, result
);
357 assert_cc(ETH_ALEN
<= sizeof(result
));
358 memcpy(mac
->ether_addr_octet
, result
, ETH_ALEN
);
361 /* see eth_random_addr in the kernel */
362 mac
->ether_addr_octet
[0] &= 0xfe; /* clear multicast bit */
363 mac
->ether_addr_octet
[0] |= 0x02; /* set local assignment bit (IEEE802) */
368 int link_config_apply(link_config_ctx
*ctx
, link_config
*config
,
369 struct udev_device
*device
, const char **name
) {
370 const char *old_name
;
371 const char *new_name
= NULL
;
372 struct ether_addr generated_mac
;
373 struct ether_addr
*mac
= NULL
;
374 bool respect_predictable
= false;
382 old_name
= udev_device_get_sysname(device
);
386 r
= ethtool_set_speed(&ctx
->ethtool_fd
, old_name
, config
->speed
/ 1024, config
->duplex
);
388 log_warning_errno(r
, "Could not set speed or duplex of %s to %zu Mbps (%s): %m",
389 old_name
, config
->speed
/ 1024,
390 duplex_to_string(config
->duplex
));
392 r
= ethtool_set_wol(&ctx
->ethtool_fd
, old_name
, config
->wol
);
394 log_warning_errno(r
, "Could not set WakeOnLan of %s to %s: %m",
395 old_name
, wol_to_string(config
->wol
));
397 ifindex
= udev_device_get_ifindex(device
);
399 log_warning("Could not find ifindex");
403 if (ctx
->enable_name_policy
&& config
->name_policy
) {
406 for (policy
= config
->name_policy
;
407 !new_name
&& *policy
!= _NAMEPOLICY_INVALID
; policy
++) {
409 case NAMEPOLICY_KERNEL
:
410 respect_predictable
= true;
412 case NAMEPOLICY_DATABASE
:
413 new_name
= udev_device_get_property_value(device
, "ID_NET_NAME_FROM_DATABASE");
415 case NAMEPOLICY_ONBOARD
:
416 new_name
= udev_device_get_property_value(device
, "ID_NET_NAME_ONBOARD");
418 case NAMEPOLICY_SLOT
:
419 new_name
= udev_device_get_property_value(device
, "ID_NET_NAME_SLOT");
421 case NAMEPOLICY_PATH
:
422 new_name
= udev_device_get_property_value(device
, "ID_NET_NAME_PATH");
425 new_name
= udev_device_get_property_value(device
, "ID_NET_NAME_MAC");
433 if (should_rename(device
, respect_predictable
)) {
434 /* if not set by policy, fall back manually set name */
436 new_name
= config
->name
;
440 switch (config
->mac_policy
) {
441 case MACPOLICY_PERSISTENT
:
442 if (mac_is_random(device
)) {
443 r
= get_mac(device
, false, &generated_mac
);
445 log_warning_errno(r
, "Could not generate persistent MAC address for %s: %m", old_name
);
449 mac
= &generated_mac
;
452 case MACPOLICY_RANDOM
:
453 if (!mac_is_random(device
)) {
454 r
= get_mac(device
, true, &generated_mac
);
456 log_warning_errno(r
, "Could not generate random MAC address for %s: %m", old_name
);
460 mac
= &generated_mac
;
468 r
= rtnl_set_link_properties(&ctx
->rtnl
, ifindex
, config
->alias
, mac
, config
->mtu
);
470 return log_warning_errno(r
, "Could not set Alias, MACAddress or MTU on %s: %m", old_name
);
477 int link_get_driver(link_config_ctx
*ctx
, struct udev_device
*device
, char **ret
) {
482 name
= udev_device_get_sysname(device
);
486 r
= ethtool_get_driver(&ctx
->ethtool_fd
, name
, &driver
);
494 static const char* const mac_policy_table
[_MACPOLICY_MAX
] = {
495 [MACPOLICY_PERSISTENT
] = "persistent",
496 [MACPOLICY_RANDOM
] = "random",
497 [MACPOLICY_NONE
] = "none"
500 DEFINE_STRING_TABLE_LOOKUP(mac_policy
, MACPolicy
);
501 DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy
, mac_policy
, MACPolicy
,
502 "Failed to parse MAC address policy");
504 static const char* const name_policy_table
[_NAMEPOLICY_MAX
] = {
505 [NAMEPOLICY_KERNEL
] = "kernel",
506 [NAMEPOLICY_DATABASE
] = "database",
507 [NAMEPOLICY_ONBOARD
] = "onboard",
508 [NAMEPOLICY_SLOT
] = "slot",
509 [NAMEPOLICY_PATH
] = "path",
510 [NAMEPOLICY_MAC
] = "mac"
513 DEFINE_STRING_TABLE_LOOKUP(name_policy
, NamePolicy
);
514 DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy
, name_policy
, NamePolicy
,
516 "Failed to parse interface name policy");