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