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