]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/udev/net/link-config.c
test: add shutdown test
[thirdparty/systemd.git] / src / udev / net / link-config.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <linux/netdevice.h>
4 #include <netinet/ether.h>
5 #include <unistd.h>
6
7 #include "sd-device.h"
8 #include "sd-netlink.h"
9
10 #include "alloc-util.h"
11 #include "arphrd-util.h"
12 #include "conf-files.h"
13 #include "conf-parser.h"
14 #include "creds-util.h"
15 #include "def.h"
16 #include "device-private.h"
17 #include "device-util.h"
18 #include "ethtool-util.h"
19 #include "fd-util.h"
20 #include "fileio.h"
21 #include "link-config.h"
22 #include "log-link.h"
23 #include "memory-util.h"
24 #include "net-condition.h"
25 #include "netif-util.h"
26 #include "netlink-util.h"
27 #include "parse-util.h"
28 #include "path-lookup.h"
29 #include "path-util.h"
30 #include "proc-cmdline.h"
31 #include "random-util.h"
32 #include "stat-util.h"
33 #include "string-table.h"
34 #include "string-util.h"
35 #include "strv.h"
36 #include "utf8.h"
37
38 struct LinkConfigContext {
39 LIST_HEAD(LinkConfig, configs);
40 int ethtool_fd;
41 bool enable_name_policy;
42 usec_t network_dirs_ts_usec;
43 };
44
45 static LinkConfig* link_config_free(LinkConfig *config) {
46 if (!config)
47 return NULL;
48
49 free(config->filename);
50
51 net_match_clear(&config->match);
52 condition_free_list(config->conditions);
53
54 free(config->description);
55 free(config->name_policy);
56 free(config->name);
57 strv_free(config->alternative_names);
58 free(config->alternative_names_policy);
59 free(config->alias);
60 free(config->wol_password_file);
61 erase_and_free(config->wol_password);
62
63 return mfree(config);
64 }
65
66 DEFINE_TRIVIAL_CLEANUP_FUNC(LinkConfig*, link_config_free);
67
68 static void link_configs_free(LinkConfigContext *ctx) {
69 LinkConfig *config, *config_next;
70
71 if (!ctx)
72 return;
73
74 LIST_FOREACH_SAFE(configs, config, config_next, ctx->configs)
75 link_config_free(config);
76 }
77
78 LinkConfigContext *link_config_ctx_free(LinkConfigContext *ctx) {
79 if (!ctx)
80 return NULL;
81
82 safe_close(ctx->ethtool_fd);
83 link_configs_free(ctx);
84 return mfree(ctx);
85 }
86
87 int link_config_ctx_new(LinkConfigContext **ret) {
88 _cleanup_(link_config_ctx_freep) LinkConfigContext *ctx = NULL;
89
90 if (!ret)
91 return -EINVAL;
92
93 ctx = new(LinkConfigContext, 1);
94 if (!ctx)
95 return -ENOMEM;
96
97 *ctx = (LinkConfigContext) {
98 .ethtool_fd = -1,
99 .enable_name_policy = true,
100 };
101
102 *ret = TAKE_PTR(ctx);
103
104 return 0;
105 }
106
107 static int link_parse_wol_password(LinkConfig *config, const char *str) {
108 _cleanup_(erase_and_freep) uint8_t *p = NULL;
109 int r;
110
111 assert(config);
112 assert(str);
113
114 assert_cc(sizeof(struct ether_addr) == SOPASS_MAX);
115
116 p = new(uint8_t, SOPASS_MAX);
117 if (!p)
118 return -ENOMEM;
119
120 /* Reuse parse_ether_addr(), as their formats are equivalent. */
121 r = parse_ether_addr(str, (struct ether_addr*) p);
122 if (r < 0)
123 return r;
124
125 erase_and_free(config->wol_password);
126 config->wol_password = TAKE_PTR(p);
127 return 0;
128 }
129
130 static int link_read_wol_password_from_file(LinkConfig *config) {
131 _cleanup_(erase_and_freep) char *password = NULL;
132 int r;
133
134 assert(config);
135
136 if (!config->wol_password_file)
137 return 0;
138
139 r = read_full_file_full(
140 AT_FDCWD, config->wol_password_file, UINT64_MAX, SIZE_MAX,
141 READ_FULL_FILE_SECURE | READ_FULL_FILE_WARN_WORLD_READABLE | READ_FULL_FILE_CONNECT_SOCKET,
142 NULL, &password, NULL);
143 if (r < 0)
144 return r;
145
146 return link_parse_wol_password(config, password);
147 }
148
149 static int link_read_wol_password_from_cred(LinkConfig *config) {
150 _cleanup_free_ char *base = NULL, *cred_name = NULL;
151 _cleanup_(erase_and_freep) char *password = NULL;
152 int r;
153
154 assert(config);
155 assert(config->filename);
156
157 if (config->wol == UINT32_MAX)
158 return 0; /* WakeOnLan= is not specified. */
159 if (!FLAGS_SET(config->wol, WAKE_MAGICSECURE))
160 return 0; /* secureon is not specified in WakeOnLan=. */
161 if (config->wol_password)
162 return 0; /* WakeOnLanPassword= is specified. */
163 if (config->wol_password_file)
164 return 0; /* a file name is specified in WakeOnLanPassword=, but failed to read it. */
165
166 r = path_extract_filename(config->filename, &base);
167 if (r < 0)
168 return r;
169
170 cred_name = strjoin(base, ".wol.password");
171 if (!cred_name)
172 return -ENOMEM;
173
174 r = read_credential(cred_name, (void**) &password, NULL);
175 if (r == -ENOENT)
176 r = read_credential("wol.password", (void**) &password, NULL);
177 if (r < 0)
178 return r;
179
180 return link_parse_wol_password(config, password);
181 }
182
183 static int link_adjust_wol_options(LinkConfig *config) {
184 int r;
185
186 assert(config);
187
188 r = link_read_wol_password_from_file(config);
189 if (r == -ENOMEM)
190 return log_oom();
191 if (r < 0)
192 log_warning_errno(r, "Failed to read WakeOnLan password from %s, ignoring: %m", config->wol_password_file);
193
194 r = link_read_wol_password_from_cred(config);
195 if (r == -ENOMEM)
196 return log_oom();
197 if (r < 0)
198 log_warning_errno(r, "Failed to read WakeOnLan password from credential, ignoring: %m");
199
200 if (config->wol != UINT32_MAX && config->wol_password)
201 /* Enable WAKE_MAGICSECURE flag when WakeOnLanPassword=. Note that when
202 * WakeOnLanPassword= is set without WakeOnLan=, then ethtool_set_wol() enables
203 * WAKE_MAGICSECURE flag and other flags are not changed. */
204 config->wol |= WAKE_MAGICSECURE;
205
206 return 0;
207 }
208
209 int link_load_one(LinkConfigContext *ctx, const char *filename) {
210 _cleanup_(link_config_freep) LinkConfig *config = NULL;
211 _cleanup_free_ char *name = NULL;
212 const char *dropin_dirname;
213 size_t i;
214 int r;
215
216 assert(ctx);
217 assert(filename);
218
219 r = null_or_empty_path(filename);
220 if (r == -ENOENT)
221 return 0;
222 if (r < 0)
223 return r;
224 if (r > 0) {
225 log_debug("Skipping empty file: %s", filename);
226 return 0;
227 }
228
229 name = strdup(filename);
230 if (!name)
231 return -ENOMEM;
232
233 config = new(LinkConfig, 1);
234 if (!config)
235 return -ENOMEM;
236
237 *config = (LinkConfig) {
238 .filename = TAKE_PTR(name),
239 .mac_address_policy = MAC_ADDRESS_POLICY_NONE,
240 .wol = UINT32_MAX, /* UINT32_MAX means do not change WOL setting. */
241 .duplex = _DUP_INVALID,
242 .port = _NET_DEV_PORT_INVALID,
243 .autonegotiation = -1,
244 .rx_flow_control = -1,
245 .tx_flow_control = -1,
246 .autoneg_flow_control = -1,
247 .txqueuelen = UINT32_MAX,
248 .coalesce.use_adaptive_rx_coalesce = -1,
249 .coalesce.use_adaptive_tx_coalesce = -1,
250 };
251
252 for (i = 0; i < ELEMENTSOF(config->features); i++)
253 config->features[i] = -1;
254
255 dropin_dirname = strjoina(basename(filename), ".d");
256 r = config_parse_many(
257 STRV_MAKE_CONST(filename),
258 (const char* const*) CONF_PATHS_STRV("systemd/network"),
259 dropin_dirname,
260 "Match\0Link\0",
261 config_item_perf_lookup, link_config_gperf_lookup,
262 CONFIG_PARSE_WARN, config, NULL);
263 if (r < 0)
264 return r;
265
266 if (net_match_is_empty(&config->match) && !config->conditions) {
267 log_warning("%s: No valid settings found in the [Match] section, ignoring file. "
268 "To match all interfaces, add OriginalName=* in the [Match] section.",
269 filename);
270 return 0;
271 }
272
273 if (!condition_test_list(config->conditions, environ, NULL, NULL, NULL)) {
274 log_debug("%s: Conditions do not match the system environment, skipping.", filename);
275 return 0;
276 }
277
278 if (IN_SET(config->mac_address_policy, MAC_ADDRESS_POLICY_PERSISTENT, MAC_ADDRESS_POLICY_RANDOM) &&
279 config->hw_addr.length > 0)
280 log_warning("%s: MACAddress= in [Link] section will be ignored when MACAddressPolicy= "
281 "is set to \"persistent\" or \"random\".",
282 filename);
283
284 r = link_adjust_wol_options(config);
285 if (r < 0)
286 return r;
287
288 log_debug("Parsed configuration file %s", filename);
289
290 LIST_PREPEND(configs, ctx->configs, TAKE_PTR(config));
291 return 0;
292 }
293
294 static bool enable_name_policy(void) {
295 bool b;
296
297 return proc_cmdline_get_bool("net.ifnames", &b) <= 0 || b;
298 }
299
300 static int device_unsigned_attribute(sd_device *device, const char *attr, unsigned *type) {
301 const char *s;
302 int r;
303
304 r = sd_device_get_sysattr_value(device, attr, &s);
305 if (r < 0)
306 return log_device_debug_errno(device, r, "Failed to query %s: %m", attr);
307
308 r = safe_atou(s, type);
309 if (r < 0)
310 return log_device_warning_errno(device, r, "Failed to parse %s \"%s\": %m", attr, s);
311
312 log_device_debug(device, "Device has %s=%u", attr, *type);
313 return 0;
314 }
315
316 int link_config_load(LinkConfigContext *ctx) {
317 _cleanup_strv_free_ char **files = NULL;
318 char **f;
319 int r;
320
321 link_configs_free(ctx);
322
323 if (!enable_name_policy()) {
324 ctx->enable_name_policy = false;
325 log_info("Network interface NamePolicy= disabled on kernel command line, ignoring.");
326 }
327
328 /* update timestamp */
329 paths_check_timestamp(NETWORK_DIRS, &ctx->network_dirs_ts_usec, true);
330
331 r = conf_files_list_strv(&files, ".link", NULL, 0, NETWORK_DIRS);
332 if (r < 0)
333 return log_error_errno(r, "failed to enumerate link files: %m");
334
335 STRV_FOREACH_BACKWARDS(f, files) {
336 r = link_load_one(ctx, *f);
337 if (r < 0)
338 log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
339 }
340
341 return 0;
342 }
343
344 bool link_config_should_reload(LinkConfigContext *ctx) {
345 return paths_check_timestamp(NETWORK_DIRS, &ctx->network_dirs_ts_usec, false);
346 }
347
348 Link *link_free(Link *link) {
349 if (!link)
350 return NULL;
351
352 sd_device_unref(link->device);
353 free(link->driver);
354 return mfree(link);
355 }
356
357 int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, Link **ret) {
358 _cleanup_(link_freep) Link *link = NULL;
359 int r;
360
361 assert(ctx);
362 assert(rtnl);
363 assert(device);
364 assert(ret);
365
366 link = new(Link, 1);
367 if (!link)
368 return -ENOMEM;
369
370 *link = (Link) {
371 .device = sd_device_ref(device),
372 };
373
374 r = sd_device_get_sysname(device, &link->ifname);
375 if (r < 0)
376 return r;
377
378 r = sd_device_get_ifindex(device, &link->ifindex);
379 if (r < 0)
380 return r;
381
382 r = sd_device_get_action(device, &link->action);
383 if (r < 0)
384 return r;
385
386 r = device_unsigned_attribute(device, "name_assign_type", &link->name_assign_type);
387 if (r < 0)
388 log_link_debug_errno(link, r, "Failed to get \"name_assign_type\" attribute, ignoring: %m");
389
390 r = device_unsigned_attribute(device, "addr_assign_type", &link->addr_assign_type);
391 if (r < 0)
392 log_link_debug_errno(link, r, "Failed to get \"addr_assign_type\" attribute, ignoring: %m");
393
394 r = rtnl_get_link_info(rtnl, link->ifindex, &link->iftype, &link->flags, &link->hw_addr, &link->permanent_hw_addr);
395 if (r < 0)
396 return r;
397
398 if (link->hw_addr.length > 0 && link->permanent_hw_addr.length == 0) {
399 r = ethtool_get_permanent_hw_addr(&ctx->ethtool_fd, link->ifname, &link->permanent_hw_addr);
400 if (r < 0)
401 log_link_debug_errno(link, r, "Failed to get permanent hardware address, ignoring: %m");
402 }
403
404 r = ethtool_get_driver(&ctx->ethtool_fd, link->ifname, &link->driver);
405 if (r < 0)
406 log_link_debug_errno(link, r, "Failed to get driver, ignoring: %m");
407
408 *ret = TAKE_PTR(link);
409 return 0;
410 }
411
412 int link_get_config(LinkConfigContext *ctx, Link *link) {
413 LinkConfig *config;
414 int r;
415
416 assert(ctx);
417 assert(link);
418
419 /* Do not configure loopback interfaces by .link files. */
420 if (link->flags & IFF_LOOPBACK)
421 return -ENOENT;
422
423 LIST_FOREACH(configs, config, ctx->configs) {
424 r = net_match_config(
425 &config->match,
426 link->device,
427 &link->hw_addr,
428 &link->permanent_hw_addr,
429 link->driver,
430 link->iftype,
431 link->ifname,
432 /* alternative_names = */ NULL,
433 /* wlan_iftype = */ 0,
434 /* ssid = */ NULL,
435 /* bssid = */ NULL);
436 if (r < 0)
437 return r;
438 if (r == 0)
439 continue;
440
441 if (config->match.ifname && !strv_contains(config->match.ifname, "*") && link->name_assign_type == NET_NAME_ENUM)
442 log_link_warning(link, "Config file %s is applied to device based on potentially unpredictable interface name.",
443 config->filename);
444 else
445 log_link_debug(link, "Config file %s is applied", config->filename);
446
447 link->config = config;
448 return 0;
449 }
450
451 return -ENOENT;
452 }
453
454 static int link_apply_ethtool_settings(Link *link, int *ethtool_fd) {
455 LinkConfig *config;
456 const char *name;
457 int r;
458
459 assert(link);
460 assert(link->config);
461 assert(ethtool_fd);
462
463 config = link->config;
464 name = link->ifname;
465
466 r = ethtool_set_glinksettings(ethtool_fd, name,
467 config->autonegotiation, config->advertise,
468 config->speed, config->duplex, config->port);
469 if (r < 0) {
470 if (config->autonegotiation >= 0)
471 log_link_warning_errno(link, r, "Could not %s auto negotiation, ignoring: %m",
472 enable_disable(config->autonegotiation));
473
474 if (!eqzero(config->advertise))
475 log_link_warning_errno(link, r, "Could not set advertise mode, ignoring: %m");
476
477 if (config->speed > 0)
478 log_link_warning_errno(link, r, "Could not set speed to %"PRIu64"Mbps, ignoring: %m",
479 DIV_ROUND_UP(config->speed, 1000000));
480
481 if (config->duplex >= 0)
482 log_link_warning_errno(link, r, "Could not set duplex to %s, ignoring: %m",
483 duplex_to_string(config->duplex));
484
485 if (config->port >= 0)
486 log_link_warning_errno(link, r, "Could not set port to '%s', ignoring: %m",
487 port_to_string(config->port));
488 }
489
490 r = ethtool_set_wol(ethtool_fd, name, config->wol, config->wol_password);
491 if (r < 0) {
492 _cleanup_free_ char *str = NULL;
493
494 (void) wol_options_to_string_alloc(config->wol, &str);
495 log_link_warning_errno(link, r, "Could not set WakeOnLan%s%s, ignoring: %m",
496 isempty(str) ? "" : " to ", strempty(str));
497 }
498
499 r = ethtool_set_features(ethtool_fd, name, config->features);
500 if (r < 0)
501 log_link_warning_errno(link, r, "Could not set offload features, ignoring: %m");
502
503 r = ethtool_set_channels(ethtool_fd, name, &config->channels);
504 if (r < 0)
505 log_link_warning_errno(link, r, "Could not set channels, ignoring: %m");
506
507 r = ethtool_set_nic_buffer_size(ethtool_fd, name, &config->ring);
508 if (r < 0)
509 log_link_warning_errno(link, r, "Could not set ring buffer, ignoring: %m");
510
511 r = ethtool_set_flow_control(ethtool_fd, name, config->rx_flow_control, config->tx_flow_control, config->autoneg_flow_control);
512 if (r < 0)
513 log_link_warning_errno(link, r, "Could not set flow control, ignoring: %m");
514
515 r = ethtool_set_nic_coalesce_settings(ethtool_fd, name, &config->coalesce);
516 if (r < 0)
517 log_link_warning_errno(link, r, "Could not set coalesce settings, ignoring: %m");
518
519 return 0;
520 }
521
522 static bool hw_addr_is_valid(Link *link, const struct hw_addr_data *hw_addr) {
523 assert(link);
524 assert(hw_addr);
525
526 switch (link->iftype) {
527 case ARPHRD_ETHER:
528 /* Refuse all zero and all 0xFF. */
529 assert(hw_addr->length == ETH_ALEN);
530 return !ether_addr_is_null(&hw_addr->ether) && !ether_addr_is_broadcast(&hw_addr->ether);
531
532 case ARPHRD_INFINIBAND:
533 /* The last 8 bytes cannot be zero*/
534 assert(hw_addr->length == INFINIBAND_ALEN);
535 return !memeqzero(hw_addr->bytes + INFINIBAND_ALEN - 8, 8);
536
537 default:
538 assert_not_reached();
539 }
540 }
541
542 static int link_generate_new_hw_addr(Link *link, struct hw_addr_data *ret) {
543 struct hw_addr_data hw_addr = HW_ADDR_NULL;
544 bool is_static = false;
545 uint8_t *p;
546 size_t len;
547 int r;
548
549 assert(link);
550 assert(link->config);
551 assert(link->device);
552 assert(ret);
553
554 if (link->hw_addr.length == 0)
555 goto finalize;
556
557 if (link->config->mac_address_policy == MAC_ADDRESS_POLICY_NONE) {
558 log_link_debug(link, "Using static MAC address.");
559 hw_addr = link->config->hw_addr;
560 is_static = true;
561 goto finalize;
562 }
563
564 if (!IN_SET(link->iftype, ARPHRD_ETHER, ARPHRD_INFINIBAND))
565 goto finalize;
566
567 switch (link->addr_assign_type) {
568 case NET_ADDR_SET:
569 log_link_debug(link, "MAC address on the device already set by userspace.");
570 goto finalize;
571 case NET_ADDR_STOLEN:
572 log_link_debug(link, "MAC address on the device already set based on another device.");
573 goto finalize;
574 case NET_ADDR_RANDOM:
575 case NET_ADDR_PERM:
576 break;
577 default:
578 log_link_warning(link, "Unknown addr_assign_type %u, ignoring", link->addr_assign_type);
579 goto finalize;
580 }
581
582 if ((link->config->mac_address_policy == MAC_ADDRESS_POLICY_RANDOM) == (link->addr_assign_type == NET_ADDR_RANDOM)) {
583 log_link_debug(link, "MAC address on the device already matches policy \"%s\".",
584 mac_address_policy_to_string(link->config->mac_address_policy));
585 goto finalize;
586 }
587
588 hw_addr = (struct hw_addr_data) {
589 .length = arphrd_to_hw_addr_len(link->iftype),
590 };
591
592 switch (link->iftype) {
593 case ARPHRD_ETHER:
594 p = hw_addr.bytes;
595 len = hw_addr.length;
596 break;
597 case ARPHRD_INFINIBAND:
598 p = hw_addr.bytes + INFINIBAND_ALEN - 8;
599 len = 8;
600 break;
601 default:
602 assert_not_reached();
603 }
604
605 if (link->config->mac_address_policy == MAC_ADDRESS_POLICY_RANDOM)
606 /* We require genuine randomness here, since we want to make sure we won't collide with other
607 * systems booting up at the very same time. We do allow RDRAND however, since this is not
608 * cryptographic key material. */
609 for (;;) {
610 r = genuine_random_bytes(p, len, RANDOM_ALLOW_RDRAND);
611 if (r < 0)
612 return log_link_warning_errno(link, r, "Failed to acquire random data to generate MAC address: %m");
613
614 if (hw_addr_is_valid(link, &hw_addr))
615 break;
616 }
617
618 else {
619 uint64_t result;
620
621 r = net_get_unique_predictable_data(link->device,
622 naming_scheme_has(NAMING_STABLE_VIRTUAL_MACS),
623 &result);
624 if (r < 0)
625 return log_link_warning_errno(link, r, "Could not generate persistent MAC address: %m");
626
627 assert(len <= sizeof(result));
628 memcpy(p, &result, len);
629 if (!hw_addr_is_valid(link, &hw_addr))
630 return log_link_warning_errno(link, SYNTHETIC_ERRNO(EINVAL),
631 "Could not generate valid persistent MAC address: %m");
632 }
633
634 finalize:
635
636 r = net_verify_hardware_address(link->ifname, is_static, link->iftype, &link->hw_addr, &hw_addr);
637 if (r < 0)
638 return r;
639
640 if (hw_addr_equal(&link->hw_addr, &hw_addr)) {
641 *ret = HW_ADDR_NULL;
642 return 0;
643 }
644
645 if (hw_addr.length > 0)
646 log_link_debug(link, "Applying %s MAC address: %s",
647 link->config->mac_address_policy == MAC_ADDRESS_POLICY_NONE ? "static" :
648 mac_address_policy_to_string(link->config->mac_address_policy),
649 HW_ADDR_TO_STR(&hw_addr));
650
651 *ret = hw_addr;
652 return 0;
653 }
654
655 static int link_apply_rtnl_settings(Link *link, sd_netlink **rtnl) {
656 struct hw_addr_data hw_addr = {};
657 LinkConfig *config;
658 int r;
659
660 assert(link);
661 assert(link->config);
662 assert(rtnl);
663
664 config = link->config;
665
666 (void) link_generate_new_hw_addr(link, &hw_addr);
667
668 r = rtnl_set_link_properties(rtnl, link->ifindex, config->alias, &hw_addr,
669 config->txqueues, config->rxqueues, config->txqueuelen,
670 config->mtu, config->gso_max_size, config->gso_max_segments);
671 if (r < 0)
672 log_link_warning_errno(link, r,
673 "Could not set Alias=, MACAddress=/MACAddressPolicy=, "
674 "TransmitQueues=, ReceiveQueues=, TransmitQueueLength=, MTUBytes=, "
675 "GenericSegmentOffloadMaxBytes= or GenericSegmentOffloadMaxSegments=, "
676 "ignoring: %m");
677
678 return 0;
679 }
680
681 static int link_generate_new_name(Link *link, bool enable_name_policy) {
682 LinkConfig *config;
683 sd_device *device;
684
685 assert(link);
686 assert(link->config);
687 assert(link->device);
688
689 config = link->config;
690 device = link->device;
691
692 if (link->action == SD_DEVICE_MOVE) {
693 log_link_debug(link, "Skipping to apply Name= and NamePolicy= on '%s' uevent.",
694 device_action_to_string(link->action));
695 goto no_rename;
696 }
697
698 if (IN_SET(link->name_assign_type, NET_NAME_USER, NET_NAME_RENAMED) &&
699 !naming_scheme_has(NAMING_ALLOW_RERENAMES)) {
700 log_link_debug(link, "Device already has a name given by userspace, not renaming.");
701 goto no_rename;
702 }
703
704 if (enable_name_policy && config->name_policy)
705 for (NamePolicy *policy = config->name_policy; *policy != _NAMEPOLICY_INVALID; policy++) {
706 const char *new_name = NULL;
707
708 switch (*policy) {
709 case NAMEPOLICY_KERNEL:
710 if (link->name_assign_type != NET_NAME_PREDICTABLE)
711 continue;
712
713 /* The kernel claims to have given a predictable name, keep it. */
714 log_link_debug(link, "Policy *%s*: keeping predictable kernel name",
715 name_policy_to_string(*policy));
716 goto no_rename;
717 case NAMEPOLICY_KEEP:
718 if (!IN_SET(link->name_assign_type, NET_NAME_USER, NET_NAME_RENAMED))
719 continue;
720
721 log_link_debug(link, "Policy *%s*: keeping existing userspace name",
722 name_policy_to_string(*policy));
723 goto no_rename;
724 case NAMEPOLICY_DATABASE:
725 (void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &new_name);
726 break;
727 case NAMEPOLICY_ONBOARD:
728 (void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &new_name);
729 break;
730 case NAMEPOLICY_SLOT:
731 (void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &new_name);
732 break;
733 case NAMEPOLICY_PATH:
734 (void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &new_name);
735 break;
736 case NAMEPOLICY_MAC:
737 (void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &new_name);
738 break;
739 default:
740 assert_not_reached();
741 }
742 if (ifname_valid(new_name)) {
743 log_link_debug(link, "Policy *%s* yields \"%s\".", name_policy_to_string(*policy), new_name);
744 link->new_name = new_name;
745 return 0;
746 }
747 }
748
749 if (link->config->name) {
750 log_link_debug(link, "Policies didn't yield a name, using specified Name=%s.", link->config->name);
751 link->new_name = link->config->name;
752 return 0;
753 }
754
755 log_link_debug(link, "Policies didn't yield a name and Name= is not given, not renaming.");
756 no_rename:
757 link->new_name = link->ifname;
758 return 0;
759 }
760
761 static int link_apply_alternative_names(Link *link, sd_netlink **rtnl) {
762 _cleanup_strv_free_ char **altnames = NULL, **current_altnames = NULL;
763 LinkConfig *config;
764 sd_device *device;
765 int r;
766
767 assert(link);
768 assert(link->config);
769 assert(link->device);
770 assert(rtnl);
771
772 config = link->config;
773 device = link->device;
774
775 if (config->alternative_names) {
776 altnames = strv_copy(config->alternative_names);
777 if (!altnames)
778 return log_oom();
779 }
780
781 if (config->alternative_names_policy)
782 for (NamePolicy *p = config->alternative_names_policy; *p != _NAMEPOLICY_INVALID; p++) {
783 const char *n = NULL;
784
785 switch (*p) {
786 case NAMEPOLICY_DATABASE:
787 (void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &n);
788 break;
789 case NAMEPOLICY_ONBOARD:
790 (void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &n);
791 break;
792 case NAMEPOLICY_SLOT:
793 (void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &n);
794 break;
795 case NAMEPOLICY_PATH:
796 (void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &n);
797 break;
798 case NAMEPOLICY_MAC:
799 (void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &n);
800 break;
801 default:
802 assert_not_reached();
803 }
804 if (!isempty(n)) {
805 r = strv_extend(&altnames, n);
806 if (r < 0)
807 return log_oom();
808 }
809 }
810
811 if (link->new_name)
812 strv_remove(altnames, link->new_name);
813 strv_remove(altnames, link->ifname);
814
815 r = rtnl_get_link_alternative_names(rtnl, link->ifindex, &current_altnames);
816 if (r < 0)
817 log_link_debug_errno(link, r, "Failed to get alternative names, ignoring: %m");
818
819 char **p;
820 STRV_FOREACH(p, current_altnames)
821 strv_remove(altnames, *p);
822
823 strv_uniq(altnames);
824 strv_sort(altnames);
825 r = rtnl_set_link_alternative_names(rtnl, link->ifindex, altnames);
826 if (r < 0)
827 log_link_full_errno(link, r == -EOPNOTSUPP ? LOG_DEBUG : LOG_WARNING, r,
828 "Could not set AlternativeName= or apply AlternativeNamesPolicy=, ignoring: %m");
829
830 return 0;
831 }
832
833 int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link) {
834 int r;
835
836 assert(ctx);
837 assert(rtnl);
838 assert(link);
839
840 if (!IN_SET(link->action, SD_DEVICE_ADD, SD_DEVICE_BIND, SD_DEVICE_MOVE)) {
841 log_link_debug(link, "Skipping to apply .link settings on '%s' uevent.",
842 device_action_to_string(link->action));
843
844 link->new_name = link->ifname;
845 return 0;
846 }
847
848 r = link_apply_ethtool_settings(link, &ctx->ethtool_fd);
849 if (r < 0)
850 return r;
851
852 r = link_apply_rtnl_settings(link, rtnl);
853 if (r < 0)
854 return r;
855
856 r = link_generate_new_name(link, ctx->enable_name_policy);
857 if (r < 0)
858 return r;
859
860 r = link_apply_alternative_names(link, rtnl);
861 if (r < 0)
862 return r;
863
864 return 0;
865 }
866
867 int config_parse_ifalias(
868 const char *unit,
869 const char *filename,
870 unsigned line,
871 const char *section,
872 unsigned section_line,
873 const char *lvalue,
874 int ltype,
875 const char *rvalue,
876 void *data,
877 void *userdata) {
878
879 char **s = data;
880
881 assert(filename);
882 assert(lvalue);
883 assert(rvalue);
884 assert(data);
885
886 if (!isempty(rvalue)) {
887 *s = mfree(*s);
888 return 0;
889 }
890
891 if (!ascii_is_valid(rvalue)) {
892 log_syntax(unit, LOG_WARNING, filename, line, 0,
893 "Interface alias is not ASCII clean, ignoring assignment: %s", rvalue);
894 return 0;
895 }
896
897 if (strlen(rvalue) >= IFALIASZ) {
898 log_syntax(unit, LOG_WARNING, filename, line, 0,
899 "Interface alias is too long, ignoring assignment: %s", rvalue);
900 return 0;
901 }
902
903 return free_and_strdup_warn(s, rvalue);
904 }
905
906 int config_parse_rx_tx_queues(
907 const char *unit,
908 const char *filename,
909 unsigned line,
910 const char *section,
911 unsigned section_line,
912 const char *lvalue,
913 int ltype,
914 const char *rvalue,
915 void *data,
916 void *userdata) {
917
918 uint32_t k, *v = data;
919 int r;
920
921 if (isempty(rvalue)) {
922 *v = 0;
923 return 0;
924 }
925
926 r = safe_atou32(rvalue, &k);
927 if (r < 0) {
928 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s=, ignoring assignment: %s.", lvalue, rvalue);
929 return 0;
930 }
931 if (k == 0 || k > 4096) {
932 log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid %s=, ignoring assignment: %s.", lvalue, rvalue);
933 return 0;
934 }
935
936 *v = k;
937 return 0;
938 }
939
940 int config_parse_txqueuelen(
941 const char *unit,
942 const char *filename,
943 unsigned line,
944 const char *section,
945 unsigned section_line,
946 const char *lvalue,
947 int ltype,
948 const char *rvalue,
949 void *data,
950 void *userdata) {
951
952 uint32_t k, *v = data;
953 int r;
954
955 if (isempty(rvalue)) {
956 *v = UINT32_MAX;
957 return 0;
958 }
959
960 r = safe_atou32(rvalue, &k);
961 if (r < 0) {
962 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s=, ignoring assignment: %s.", lvalue, rvalue);
963 return 0;
964 }
965 if (k == UINT32_MAX) {
966 log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid %s=, ignoring assignment: %s.", lvalue, rvalue);
967 return 0;
968 }
969
970 *v = k;
971 return 0;
972 }
973
974 int config_parse_wol_password(
975 const char *unit,
976 const char *filename,
977 unsigned line,
978 const char *section,
979 unsigned section_line,
980 const char *lvalue,
981 int ltype,
982 const char *rvalue,
983 void *data,
984 void *userdata) {
985
986 LinkConfig *config = userdata;
987 int r;
988
989 assert(filename);
990 assert(lvalue);
991 assert(rvalue);
992 assert(userdata);
993
994 if (isempty(rvalue)) {
995 config->wol_password = erase_and_free(config->wol_password);
996 config->wol_password_file = mfree(config->wol_password_file);
997 return 0;
998 }
999
1000 if (path_is_absolute(rvalue) && path_is_safe(rvalue)) {
1001 config->wol_password = erase_and_free(config->wol_password);
1002 return free_and_strdup_warn(&config->wol_password_file, rvalue);
1003 }
1004
1005 warn_file_is_world_accessible(filename, NULL, unit, line);
1006
1007 r = link_parse_wol_password(config, rvalue);
1008 if (r == -ENOMEM)
1009 return log_oom();
1010 if (r < 0) {
1011 log_syntax(unit, LOG_WARNING, filename, line, r,
1012 "Failed to parse %s=, ignoring assignment: %s.", lvalue, rvalue);
1013 return 0;
1014 }
1015
1016 config->wol_password_file = mfree(config->wol_password_file);
1017 return 0;
1018 }
1019
1020 static const char* const mac_address_policy_table[_MAC_ADDRESS_POLICY_MAX] = {
1021 [MAC_ADDRESS_POLICY_PERSISTENT] = "persistent",
1022 [MAC_ADDRESS_POLICY_RANDOM] = "random",
1023 [MAC_ADDRESS_POLICY_NONE] = "none",
1024 };
1025
1026 DEFINE_STRING_TABLE_LOOKUP(mac_address_policy, MACAddressPolicy);
1027 DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(
1028 config_parse_mac_address_policy,
1029 mac_address_policy,
1030 MACAddressPolicy,
1031 MAC_ADDRESS_POLICY_NONE,
1032 "Failed to parse MAC address policy");
1033
1034 DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy,
1035 _NAMEPOLICY_INVALID,
1036 "Failed to parse interface name policy");
1037
1038 DEFINE_CONFIG_PARSE_ENUMV(config_parse_alternative_names_policy, alternative_names_policy, NamePolicy,
1039 _NAMEPOLICY_INVALID,
1040 "Failed to parse alternative names policy");