]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/udev/net/link-config.c
udev-ctrl: update log messages
[thirdparty/systemd.git] / src / udev / net / link-config.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
af6f0d42 2
43b3a5ef
TG
3#include <netinet/ether.h>
4
e5eadf53 5#include "sd-device.h"
07630cea 6#include "sd-netlink.h"
af6f0d42 7
b5efdb8a 8#include "alloc-util.h"
07630cea
LP
9#include "conf-files.h"
10#include "conf-parser.h"
b220632c 11#include "device-util.h"
a5010333 12#include "ethtool-util.h"
3ffd4af2 13#include "fd-util.h"
07630cea 14#include "link-config.h"
af6f0d42 15#include "log.h"
07630cea 16#include "missing.h"
1c4baffc 17#include "netlink-util.h"
c6f7c917 18#include "network-internal.h"
6bedfcbb 19#include "parse-util.h"
07630cea 20#include "path-util.h"
4e731273 21#include "proc-cmdline.h"
3df3e884 22#include "random-util.h"
8fcde012 23#include "stat-util.h"
8b43440b 24#include "string-table.h"
07630cea
LP
25#include "string-util.h"
26#include "strv.h"
27#include "util.h"
af6f0d42
TG
28
29struct link_config_ctx {
30 LIST_HEAD(link_config, links);
31
a5010333
TG
32 int ethtool_fd;
33
f6194225
TG
34 bool enable_name_policy;
35
1c4baffc 36 sd_netlink *rtnl;
43b3a5ef 37
97f2d76d 38 usec_t link_dirs_ts_usec;
af6f0d42
TG
39};
40
2ad8416d
ZJS
41static const char* const link_dirs[] = {
42 "/etc/systemd/network",
43 "/run/systemd/network",
44 "/usr/lib/systemd/network",
349cc4a5 45#if HAVE_SPLIT_USR
2ad8416d
ZJS
46 "/lib/systemd/network",
47#endif
48 NULL};
49
9a4b012e
TG
50static void link_config_free(link_config *link) {
51 if (!link)
52 return;
5b9d4dc0 53
9a4b012e
TG
54 free(link->filename);
55
e90d0374 56 set_free_free(link->match_mac);
43d60b77
TG
57 strv_free(link->match_path);
58 strv_free(link->match_driver);
59 strv_free(link->match_type);
9a4b012e
TG
60 free(link->match_name);
61 free(link->match_host);
62 free(link->match_virt);
5022f08a
LP
63 free(link->match_kernel_cmdline);
64 free(link->match_kernel_version);
9a4b012e
TG
65 free(link->match_arch);
66
67 free(link->description);
68 free(link->mac);
69 free(link->name_policy);
70 free(link->name);
71 free(link->alias);
72
73 free(link);
af6f0d42
TG
74}
75
9a4b012e
TG
76DEFINE_TRIVIAL_CLEANUP_FUNC(link_config*, link_config_free);
77
af6f0d42
TG
78static void link_configs_free(link_config_ctx *ctx) {
79 link_config *link, *link_next;
80
81 if (!ctx)
82 return;
83
9a4b012e
TG
84 LIST_FOREACH_SAFE(links, link, link_next, ctx->links)
85 link_config_free(link);
af6f0d42
TG
86}
87
88void link_config_ctx_free(link_config_ctx *ctx) {
89 if (!ctx)
90 return;
91
03e334a1 92 safe_close(ctx->ethtool_fd);
43b3a5ef 93
1c4baffc 94 sd_netlink_unref(ctx->rtnl);
43b3a5ef 95
af6f0d42
TG
96 link_configs_free(ctx);
97
98 free(ctx);
99
100 return;
101}
102
9a4b012e
TG
103DEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free);
104
105int link_config_ctx_new(link_config_ctx **ret) {
106 _cleanup_(link_config_ctx_freep) link_config_ctx *ctx = NULL;
107
108 if (!ret)
109 return -EINVAL;
110
111 ctx = new0(link_config_ctx, 1);
112 if (!ctx)
113 return -ENOMEM;
114
115 LIST_HEAD_INIT(ctx->links);
116
117 ctx->ethtool_fd = -1;
118
119 ctx->enable_name_policy = true;
120
1cc6c93a 121 *ret = TAKE_PTR(ctx);
9a4b012e
TG
122
123 return 0;
124}
125
af6f0d42 126static int load_link(link_config_ctx *ctx, const char *filename) {
9a4b012e 127 _cleanup_(link_config_freep) link_config *link = NULL;
6e37cd2f 128 _cleanup_fclose_ FILE *file = NULL;
cc2ff878 129 int i;
af6f0d42
TG
130 int r;
131
187dc6e5
TA
132 assert(ctx);
133 assert(filename);
134
af6f0d42
TG
135 file = fopen(filename, "re");
136 if (!file) {
137 if (errno == ENOENT)
138 return 0;
139 else
ecb08ec6 140 return -errno;
af6f0d42
TG
141 }
142
ed88bcfb
ZJS
143 if (null_or_empty_fd(fileno(file))) {
144 log_debug("Skipping empty file: %s", filename);
145 return 0;
146 }
147
af6f0d42 148 link = new0(link_config, 1);
ecb08ec6
ZJS
149 if (!link)
150 return log_oom();
af6f0d42 151
5fde13d7
TG
152 link->mac_policy = _MACPOLICY_INVALID;
153 link->wol = _WOL_INVALID;
154 link->duplex = _DUP_INVALID;
593022fa 155 link->port = _NET_DEV_PORT_INVALID;
a39f92d3 156 link->autonegotiation = -1;
5fde13d7 157
cc2ff878
TH
158 for (i = 0; i < (int)ELEMENTSOF(link->features); i++)
159 link->features[i] = -1;
50725d10 160
e9f3d2d5
ZJS
161 r = config_parse(NULL, filename, file,
162 "Match\0Link\0Ethernet\0",
163 config_item_perf_lookup, link_config_gperf_lookup,
bcde742e 164 CONFIG_PARSE_WARN, link);
36f822c4 165 if (r < 0)
ecb08ec6 166 return r;
36f822c4 167 else
98a375f6 168 log_debug("Parsed configuration file %s", filename);
af6f0d42 169
4e964aa0 170 if (link->speed > UINT_MAX)
dab495dc
TG
171 return -ERANGE;
172
af6f0d42 173 link->filename = strdup(filename);
c805d41c
LP
174 if (!link->filename)
175 return log_oom();
af6f0d42
TG
176
177 LIST_PREPEND(links, ctx->links, link);
ecb08ec6 178 link = NULL;
af6f0d42
TG
179
180 return 0;
af6f0d42
TG
181}
182
f6194225 183static bool enable_name_policy(void) {
1d84ad94 184 bool b;
f6194225 185
1d84ad94 186 return proc_cmdline_get_bool("net.ifnames", &b) <= 0 || b;
f6194225
TG
187}
188
af6f0d42 189int link_config_load(link_config_ctx *ctx) {
edf029b7
TG
190 _cleanup_strv_free_ char **files;
191 char **f;
a39f92d3 192 int r;
af6f0d42
TG
193
194 link_configs_free(ctx);
195
f6194225
TG
196 if (!enable_name_policy()) {
197 ctx->enable_name_policy = false;
3f85ef0f 198 log_info("Network interface NamePolicy= disabled on kernel command line, ignoring.");
f6194225
TG
199 }
200
97f2d76d 201 /* update timestamp */
2ad8416d 202 paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
af6f0d42 203
b5084605 204 r = conf_files_list_strv(&files, ".link", NULL, 0, link_dirs);
f647962d
MS
205 if (r < 0)
206 return log_error_errno(r, "failed to enumerate link files: %m");
af6f0d42
TG
207
208 STRV_FOREACH_BACKWARDS(f, files) {
209 r = load_link(ctx, *f);
210 if (r < 0)
211 return r;
212 }
213
214 return 0;
215}
216
217bool link_config_should_reload(link_config_ctx *ctx) {
2ad8416d 218 return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false);
af6f0d42
TG
219}
220
e5eadf53 221int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret) {
af6f0d42
TG
222 link_config *link;
223
3b64e4d4
TG
224 assert(ctx);
225 assert(device);
226 assert(ret);
227
af6f0d42 228 LIST_FOREACH(links, link, ctx->links) {
e5eadf53
YW
229 const char *address = NULL, *id_path = NULL, *parent_driver = NULL, *id_net_driver = NULL, *devtype = NULL, *sysname = NULL;
230 sd_device *parent;
7eb08da4 231
e5eadf53
YW
232 (void) sd_device_get_sysattr_value(device, "address", &address);
233 (void) sd_device_get_property_value(device, "ID_PATH", &id_path);
234 if (sd_device_get_parent(device, &parent) >= 0)
235 (void) sd_device_get_driver(parent, &parent_driver);
236 (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &id_net_driver);
237 (void) sd_device_get_devtype(device, &devtype);
238 (void) sd_device_get_sysname(device, &sysname);
b3e01314 239
edbb03e9 240 if (net_match_config(link->match_mac, link->match_path, link->match_driver,
7eb08da4 241 link->match_type, link->match_name, link->match_host,
5022f08a
LP
242 link->match_virt, link->match_kernel_cmdline,
243 link->match_kernel_version, link->match_arch,
e5eadf53
YW
244 address ? ether_aton(address) : NULL,
245 id_path,
246 parent_driver,
247 id_net_driver,
248 devtype,
249 sysname)) {
32bc8adc
TG
250 if (link->match_name) {
251 unsigned char name_assign_type = NET_NAME_UNKNOWN;
e5eadf53 252 const char *attr_value;
32bc8adc 253
e5eadf53 254 if (sd_device_get_sysattr_value(device, "name_assign_type", &attr_value) >= 0)
dc751688 255 (void) safe_atou8(attr_value, &name_assign_type);
32bc8adc
TG
256
257 if (name_assign_type == NET_NAME_ENUM) {
ca6038b8 258 log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
e5eadf53 259 link->filename, sysname);
32bc8adc
TG
260 *ret = link;
261
262 return 0;
263 } else if (name_assign_type == NET_NAME_RENAMED) {
264 log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
e5eadf53 265 link->filename, sysname);
32bc8adc 266
ca6038b8 267 continue;
32bc8adc 268 }
ca6038b8 269 }
32bc8adc 270
ca6038b8 271 log_debug("Config file %s applies to device %s",
e5eadf53 272 link->filename, sysname);
32bc8adc 273
ca6038b8
TG
274 *ret = link;
275
276 return 0;
af6f0d42
TG
277 }
278 }
279
be32eb9b
TG
280 *ret = NULL;
281
af6f0d42
TG
282 return -ENOENT;
283}
284
e5eadf53 285static bool mac_is_random(sd_device *device) {
16b9b87a 286 const char *s;
f1ac7002
TG
287 unsigned type;
288 int r;
16b9b87a 289
3c9b8860 290 /* if we can't get the assign type, assume it is not random */
e5eadf53 291 if (sd_device_get_sysattr_value(device, "addr_assign_type", &s) < 0)
3c9b8860
TG
292 return false;
293
f1ac7002
TG
294 r = safe_atou(s, &type);
295 if (r < 0)
296 return false;
16b9b87a 297
04b67d49
TG
298 return type == NET_ADDR_RANDOM;
299}
300
e5eadf53 301static bool should_rename(sd_device *device, bool respect_predictable) {
04b67d49
TG
302 const char *s;
303 unsigned type;
304 int r;
305
3c9b8860 306 /* if we can't get the assgin type, assume we should rename */
e5eadf53 307 if (sd_device_get_sysattr_value(device, "name_assign_type", &s) < 0)
3c9b8860
TG
308 return true;
309
04b67d49
TG
310 r = safe_atou(s, &type);
311 if (r < 0)
312 return true;
313
314 switch (type) {
04b67d49 315 case NET_NAME_PREDICTABLE:
3c9b8860 316 /* the kernel claims to have given a predictable name */
04b67d49 317 if (respect_predictable)
3c9b8860 318 return false;
4831981d 319 _fallthrough_;
04b67d49 320 default:
3c9b8860
TG
321 /* the name is known to be bad, or of an unknown type */
322 return true;
04b67d49 323 }
16b9b87a
TG
324}
325
e5eadf53 326static int get_mac(sd_device *device, bool want_random,
464cf22f 327 struct ether_addr *mac) {
9bf3b535 328 int r;
16b9b87a 329
16b9b87a 330 if (want_random)
9bf3b535 331 random_bytes(mac->ether_addr_octet, ETH_ALEN);
16b9b87a 332 else {
dbe81cbd 333 uint64_t result;
9bf3b535 334
e5eadf53 335 r = net_get_unique_predictable_data(device, &result);
16b9b87a 336 if (r < 0)
55428d84 337 return r;
16b9b87a 338
9bf3b535 339 assert_cc(ETH_ALEN <= sizeof(result));
dbe81cbd 340 memcpy(mac->ether_addr_octet, &result, ETH_ALEN);
16b9b87a
TG
341 }
342
343 /* see eth_random_addr in the kernel */
3c9b8860
TG
344 mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
345 mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
16b9b87a 346
16b9b87a
TG
347 return 0;
348}
349
464cf22f 350int link_config_apply(link_config_ctx *ctx, link_config *config,
e5eadf53 351 sd_device *device, const char **name) {
a39f92d3 352 bool respect_predictable = false;
5fde13d7 353 struct ether_addr generated_mac;
16b9b87a 354 struct ether_addr *mac = NULL;
a39f92d3
SS
355 const char *new_name = NULL;
356 const char *old_name;
357 unsigned speed;
43b3a5ef 358 int r, ifindex;
af6f0d42 359
3e137a1b
TG
360 assert(ctx);
361 assert(config);
362 assert(device);
363 assert(name);
364
e5eadf53
YW
365 r = sd_device_get_sysname(device, &old_name);
366 if (r < 0)
367 return r;
af6f0d42 368
593022fa 369 r = ethtool_set_glinksettings(&ctx->ethtool_fd, old_name, config);
a39f92d3
SS
370 if (r < 0) {
371
bb79318e
SS
372 if (config->port != _NET_DEV_PORT_INVALID)
373 log_warning_errno(r, "Could not set port (%s) of %s: %m", port_to_string(config->port), old_name);
374
5dd10118 375 if (!eqzero(config->advertise))
2d18ac44 376 log_warning_errno(r, "Could not set advertise mode: %m"); /* TODO: include modes in the log message. */
a39f92d3 377
6cf0a204 378 if (config->speed) {
6cf0a204
SS
379 speed = DIV_ROUND_UP(config->speed, 1000000);
380 if (r == -EOPNOTSUPP) {
381 r = ethtool_set_speed(&ctx->ethtool_fd, old_name, speed, config->duplex);
382 if (r < 0)
383 log_warning_errno(r, "Could not set speed of %s to %u Mbps: %m", old_name, speed);
384 }
385 }
386
387 if (config->duplex !=_DUP_INVALID)
388 log_warning_errno(r, "Could not set duplex of %s to (%s): %m", old_name, duplex_to_string(config->duplex));
a39f92d3 389 }
a5010333 390
aedca892 391 r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol);
5fde13d7 392 if (r < 0)
755bde37
LP
393 log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m",
394 old_name, wol_to_string(config->wol));
af6f0d42 395
50725d10
SS
396 r = ethtool_set_features(&ctx->ethtool_fd, old_name, config->features);
397 if (r < 0)
398 log_warning_errno(r, "Could not set offload features of %s: %m", old_name);
399
5f945202
SS
400 if (config->channels.rx_count_set || config->channels.tx_count_set || config->channels.other_count_set || config->channels.combined_count_set) {
401 r = ethtool_set_channels(&ctx->ethtool_fd, old_name, &config->channels);
402 if (r < 0)
403 log_warning_errno(r, "Could not set channels of %s: %m", old_name);
404 }
405
e5eadf53
YW
406 r = sd_device_get_ifindex(device, &ifindex);
407 if (r < 0)
b220632c 408 return log_device_warning_errno(device, r, "Could not find ifindex: %m");
43b3a5ef 409
f6194225 410 if (ctx->enable_name_policy && config->name_policy) {
5fde13d7 411 NamePolicy *policy;
daeb71a3 412
68ba3877
TG
413 for (policy = config->name_policy;
414 !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
5fde13d7 415 switch (*policy) {
04b67d49
TG
416 case NAMEPOLICY_KERNEL:
417 respect_predictable = true;
418 break;
e51660ae 419 case NAMEPOLICY_DATABASE:
e5eadf53 420 (void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &new_name);
e51660ae 421 break;
5fde13d7 422 case NAMEPOLICY_ONBOARD:
e5eadf53 423 (void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &new_name);
daeb71a3 424 break;
5fde13d7 425 case NAMEPOLICY_SLOT:
e5eadf53 426 (void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &new_name);
daeb71a3 427 break;
5fde13d7 428 case NAMEPOLICY_PATH:
e5eadf53 429 (void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &new_name);
daeb71a3 430 break;
5fde13d7 431 case NAMEPOLICY_MAC:
e5eadf53 432 (void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &new_name);
daeb71a3 433 break;
5fde13d7
TG
434 default:
435 break;
436 }
daeb71a3
TG
437 }
438 }
439
55b6530b
MTL
440 if (!new_name && should_rename(device, respect_predictable))
441 new_name = config->name;
04b67d49 442
5fde13d7
TG
443 switch (config->mac_policy) {
444 case MACPOLICY_PERSISTENT:
92d927f8 445 if (mac_is_random(device)) {
5fde13d7 446 r = get_mac(device, false, &generated_mac);
1c25683e
TG
447 if (r == -ENOENT) {
448 log_warning_errno(r, "Could not generate persistent MAC address for %s: %m", old_name);
a669ea98 449 break;
1c25683e 450 } else if (r < 0)
16b9b87a 451 return r;
5fde13d7 452 mac = &generated_mac;
16b9b87a 453 }
5fde13d7
TG
454 break;
455 case MACPOLICY_RANDOM:
16b9b87a 456 if (!mac_is_random(device)) {
5fde13d7 457 r = get_mac(device, true, &generated_mac);
1c25683e
TG
458 if (r == -ENOENT) {
459 log_warning_errno(r, "Could not generate random MAC address for %s: %m", old_name);
a669ea98 460 break;
1c25683e 461 } else if (r < 0)
16b9b87a 462 return r;
5fde13d7 463 mac = &generated_mac;
16b9b87a 464 }
5fde13d7 465 break;
66d3752e 466 case MACPOLICY_NONE:
5fde13d7
TG
467 default:
468 mac = config->mac;
16b9b87a
TG
469 }
470
dab495dc 471 r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac, config->mtu);
f647962d 472 if (r < 0)
7b72fe21 473 return log_warning_errno(r, "Could not set Alias=, MACAddress= or MTU= on %s: %m", old_name);
43b3a5ef 474
d95b83b8
TG
475 *name = new_name;
476
af6f0d42
TG
477 return 0;
478}
be32eb9b 479
e5eadf53 480int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret) {
847a8a5f 481 const char *name;
a7f7d1bd 482 char *driver = NULL;
847a8a5f
TG
483 int r;
484
e5eadf53
YW
485 r = sd_device_get_sysname(device, &name);
486 if (r < 0)
487 return r;
847a8a5f 488
aedca892 489 r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver);
847a8a5f
TG
490 if (r < 0)
491 return r;
492
493 *ret = driver;
494 return 0;
495}
496
2c5859af 497static const char* const mac_policy_table[_MACPOLICY_MAX] = {
be32eb9b 498 [MACPOLICY_PERSISTENT] = "persistent",
66d3752e
JK
499 [MACPOLICY_RANDOM] = "random",
500 [MACPOLICY_NONE] = "none"
be32eb9b
TG
501};
502
503DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
464cf22f
TG
504DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy,
505 "Failed to parse MAC address policy");
be32eb9b 506
2c5859af 507static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
04b67d49 508 [NAMEPOLICY_KERNEL] = "kernel",
e51660ae 509 [NAMEPOLICY_DATABASE] = "database",
be32eb9b
TG
510 [NAMEPOLICY_ONBOARD] = "onboard",
511 [NAMEPOLICY_SLOT] = "slot",
512 [NAMEPOLICY_PATH] = "path",
513 [NAMEPOLICY_MAC] = "mac"
514};
515
516DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
464cf22f
TG
517DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy,
518 _NAMEPOLICY_INVALID,
519 "Failed to parse interface name policy");