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