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