]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/udev/net/link-config.c
Merge pull request #15238 from rpls/canfd
[thirdparty/systemd.git] / src / udev / net / link-config.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
af6f0d42 2
01234e1f 3#include <linux/netdevice.h>
43b3a5ef
TG
4#include <netinet/ether.h>
5
e5eadf53 6#include "sd-device.h"
07630cea 7#include "sd-netlink.h"
af6f0d42 8
b5efdb8a 9#include "alloc-util.h"
07630cea
LP
10#include "conf-files.h"
11#include "conf-parser.h"
dc0d4078 12#include "def.h"
b220632c 13#include "device-util.h"
a5010333 14#include "ethtool-util.h"
3ffd4af2 15#include "fd-util.h"
07630cea 16#include "link-config.h"
af6f0d42 17#include "log.h"
0a970718 18#include "memory-util.h"
b355d0c9 19#include "netif-naming-scheme.h"
1c4baffc 20#include "netlink-util.h"
c6f7c917 21#include "network-internal.h"
6bedfcbb 22#include "parse-util.h"
b0c82192 23#include "path-lookup.h"
07630cea 24#include "path-util.h"
4e731273 25#include "proc-cmdline.h"
3df3e884 26#include "random-util.h"
8fcde012 27#include "stat-util.h"
8b43440b 28#include "string-table.h"
07630cea
LP
29#include "string-util.h"
30#include "strv.h"
af6f0d42
TG
31
32struct link_config_ctx {
33 LIST_HEAD(link_config, links);
34
a5010333
TG
35 int ethtool_fd;
36
f6194225
TG
37 bool enable_name_policy;
38
1c4baffc 39 sd_netlink *rtnl;
43b3a5ef 40
dc0d4078 41 usec_t network_dirs_ts_usec;
af6f0d42
TG
42};
43
9a4b012e
TG
44static void link_config_free(link_config *link) {
45 if (!link)
46 return;
5b9d4dc0 47
9a4b012e
TG
48 free(link->filename);
49
e90d0374 50 set_free_free(link->match_mac);
4bb7cc82 51 set_free_free(link->match_permanent_mac);
43d60b77
TG
52 strv_free(link->match_path);
53 strv_free(link->match_driver);
54 strv_free(link->match_type);
391f6bc1 55 strv_free(link->match_name);
44005bfb 56 strv_free(link->match_property);
c4f58dea 57 condition_free_list(link->conditions);
9a4b012e
TG
58
59 free(link->description);
60 free(link->mac);
61 free(link->name_policy);
62 free(link->name);
a5053a15 63 strv_free(link->alternative_names);
ef1d2c07 64 free(link->alternative_names_policy);
9a4b012e
TG
65 free(link->alias);
66
67 free(link);
af6f0d42
TG
68}
69
9a4b012e
TG
70DEFINE_TRIVIAL_CLEANUP_FUNC(link_config*, link_config_free);
71
af6f0d42
TG
72static void link_configs_free(link_config_ctx *ctx) {
73 link_config *link, *link_next;
74
75 if (!ctx)
76 return;
77
9a4b012e
TG
78 LIST_FOREACH_SAFE(links, link, link_next, ctx->links)
79 link_config_free(link);
af6f0d42
TG
80}
81
82void link_config_ctx_free(link_config_ctx *ctx) {
83 if (!ctx)
84 return;
85
03e334a1 86 safe_close(ctx->ethtool_fd);
43b3a5ef 87
1c4baffc 88 sd_netlink_unref(ctx->rtnl);
43b3a5ef 89
af6f0d42
TG
90 link_configs_free(ctx);
91
92 free(ctx);
93
94 return;
95}
96
9a4b012e
TG
97int link_config_ctx_new(link_config_ctx **ret) {
98 _cleanup_(link_config_ctx_freep) link_config_ctx *ctx = NULL;
99
100 if (!ret)
101 return -EINVAL;
102
103 ctx = new0(link_config_ctx, 1);
104 if (!ctx)
105 return -ENOMEM;
106
107 LIST_HEAD_INIT(ctx->links);
108
109 ctx->ethtool_fd = -1;
110
111 ctx->enable_name_policy = true;
112
1cc6c93a 113 *ret = TAKE_PTR(ctx);
9a4b012e
TG
114
115 return 0;
116}
117
a378400b 118int link_load_one(link_config_ctx *ctx, const char *filename) {
9a4b012e 119 _cleanup_(link_config_freep) link_config *link = NULL;
6e37cd2f 120 _cleanup_fclose_ FILE *file = NULL;
6cdab9f1 121 _cleanup_free_ char *name = NULL;
79a60834 122 size_t i;
af6f0d42
TG
123 int r;
124
187dc6e5
TA
125 assert(ctx);
126 assert(filename);
127
af6f0d42 128 file = fopen(filename, "re");
f2d251cd
YW
129 if (!file)
130 return errno == ENOENT ? 0 : -errno;
af6f0d42 131
ed88bcfb
ZJS
132 if (null_or_empty_fd(fileno(file))) {
133 log_debug("Skipping empty file: %s", filename);
134 return 0;
135 }
136
6cdab9f1
YW
137 name = strdup(filename);
138 if (!name)
139 return -ENOMEM;
140
141 link = new(link_config, 1);
ecb08ec6 142 if (!link)
e8a42907 143 return -ENOMEM;
af6f0d42 144
6cdab9f1
YW
145 *link = (link_config) {
146 .filename = TAKE_PTR(name),
54ed9f88 147 .mac_address_policy = _MAC_ADDRESS_POLICY_INVALID,
6cdab9f1
YW
148 .wol = _WOL_INVALID,
149 .duplex = _DUP_INVALID,
150 .port = _NET_DEV_PORT_INVALID,
151 .autonegotiation = -1,
a34811e4
YW
152 .rx_flow_control = -1,
153 .tx_flow_control = -1,
154 .autoneg_flow_control = -1,
6cdab9f1 155 };
5fde13d7 156
79a60834 157 for (i = 0; i < ELEMENTSOF(link->features); i++)
cc2ff878 158 link->features[i] = -1;
50725d10 159
e9f3d2d5 160 r = config_parse(NULL, filename, file,
c6b3370a 161 "Match\0Link\0",
e9f3d2d5 162 config_item_perf_lookup, link_config_gperf_lookup,
bcde742e 163 CONFIG_PARSE_WARN, link);
36f822c4 164 if (r < 0)
ecb08ec6 165 return r;
af6f0d42 166
4bb7cc82
YW
167 if (set_isempty(link->match_mac) && set_isempty(link->match_permanent_mac) &&
168 strv_isempty(link->match_path) && strv_isempty(link->match_driver) && strv_isempty(link->match_type) &&
dade7349
ZJS
169 strv_isempty(link->match_name) && strv_isempty(link->match_property) && !link->conditions) {
170 log_warning("%s: No valid settings found in the [Match] section, ignoring file. "
171 "To match all interfaces, add OriginalName=* in the [Match] section.",
84ea567e 172 filename);
dade7349
ZJS
173 return 0;
174 }
84ea567e 175
c4f58dea 176 if (!condition_test_list(link->conditions, NULL, NULL, NULL)) {
176d9c0e
YW
177 log_debug("%s: Conditions do not match the system environment, skipping.", filename);
178 return 0;
179 }
180
6cdab9f1 181 log_debug("Parsed configuration file %s", filename);
af6f0d42 182
4b4a6c9b 183 LIST_PREPEND(links, ctx->links, TAKE_PTR(link));
af6f0d42 184 return 0;
af6f0d42
TG
185}
186
f6194225 187static bool enable_name_policy(void) {
1d84ad94 188 bool b;
f6194225 189
1d84ad94 190 return proc_cmdline_get_bool("net.ifnames", &b) <= 0 || b;
f6194225
TG
191}
192
015b097c 193static int link_unsigned_attribute(sd_device *device, const char *attr, unsigned *type) {
0b189e8f
ZJS
194 const char *s;
195 int r;
196
015b097c 197 r = sd_device_get_sysattr_value(device, attr, &s);
0b189e8f 198 if (r < 0)
015b097c 199 return log_device_debug_errno(device, r, "Failed to query %s: %m", attr);
0b189e8f
ZJS
200
201 r = safe_atou(s, type);
202 if (r < 0)
015b097c 203 return log_device_warning_errno(device, r, "Failed to parse %s \"%s\": %m", attr, s);
0b189e8f 204
015b097c 205 log_device_debug(device, "Device has %s=%u", attr, *type);
0b189e8f
ZJS
206 return 0;
207}
208
af6f0d42 209int link_config_load(link_config_ctx *ctx) {
edf029b7
TG
210 _cleanup_strv_free_ char **files;
211 char **f;
a39f92d3 212 int r;
af6f0d42
TG
213
214 link_configs_free(ctx);
215
f6194225
TG
216 if (!enable_name_policy()) {
217 ctx->enable_name_policy = false;
3f85ef0f 218 log_info("Network interface NamePolicy= disabled on kernel command line, ignoring.");
f6194225
TG
219 }
220
97f2d76d 221 /* update timestamp */
dc0d4078 222 paths_check_timestamp(NETWORK_DIRS, &ctx->network_dirs_ts_usec, true);
af6f0d42 223
dc0d4078 224 r = conf_files_list_strv(&files, ".link", NULL, 0, NETWORK_DIRS);
f647962d
MS
225 if (r < 0)
226 return log_error_errno(r, "failed to enumerate link files: %m");
af6f0d42
TG
227
228 STRV_FOREACH_BACKWARDS(f, files) {
a378400b 229 r = link_load_one(ctx, *f);
af6f0d42 230 if (r < 0)
e8a42907 231 log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
af6f0d42
TG
232 }
233
234 return 0;
235}
236
237bool link_config_should_reload(link_config_ctx *ctx) {
dc0d4078 238 return paths_check_timestamp(NETWORK_DIRS, &ctx->network_dirs_ts_usec, false);
af6f0d42
TG
239}
240
e5eadf53 241int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret) {
4bb7cc82 242 struct ether_addr permanent_mac = {};
ef62949a 243 unsigned short iftype = 0;
af6f0d42 244 link_config *link;
4bb7cc82 245 const char *name;
ef62949a 246 int ifindex, r;
af6f0d42 247
3b64e4d4
TG
248 assert(ctx);
249 assert(device);
250 assert(ret);
251
4bb7cc82
YW
252 r = sd_device_get_sysname(device, &name);
253 if (r < 0)
254 return r;
255
ef62949a
YW
256 r = sd_device_get_ifindex(device, &ifindex);
257 if (r < 0)
258 return r;
259
260 r = rtnl_get_link_iftype(&ctx->rtnl, ifindex, &iftype);
261 if (r < 0)
262 return r;
263
4bb7cc82
YW
264 r = ethtool_get_permanent_macaddr(&ctx->ethtool_fd, name, &permanent_mac);
265 if (r < 0)
266 log_device_debug_errno(device, r, "Failed to get permanent MAC address, ignoring: %m");
267
af6f0d42 268 LIST_FOREACH(links, link, ctx->links) {
4bb7cc82 269 if (net_match_config(link->match_mac, link->match_permanent_mac, link->match_path, link->match_driver,
78404d22 270 link->match_type, link->match_name, link->match_property, NULL, NULL, NULL,
ef62949a 271 iftype, device, NULL, &permanent_mac, NULL, NULL, 0, NULL, NULL)) {
56637e5c 272 if (link->match_name && !strv_contains(link->match_name, "*")) {
015b097c 273 unsigned name_assign_type = NET_NAME_UNKNOWN;
32bc8adc 274
015b097c 275 (void) link_unsigned_attribute(device, "name_assign_type", &name_assign_type);
32bc8adc 276
56637e5c 277 if (name_assign_type == NET_NAME_ENUM) {
b38de0e9
YW
278 log_device_warning(device, "Config file %s applies to device based on potentially unpredictable interface name",
279 link->filename);
32bc8adc
TG
280 *ret = link;
281
282 return 0;
283 } else if (name_assign_type == NET_NAME_RENAMED) {
b38de0e9
YW
284 log_device_warning(device, "Config file %s matches device based on renamed interface name, ignoring",
285 link->filename);
32bc8adc 286
ca6038b8 287 continue;
32bc8adc 288 }
ca6038b8 289 }
32bc8adc 290
b38de0e9 291 log_device_debug(device, "Config file %s is applied", link->filename);
32bc8adc 292
ca6038b8 293 *ret = link;
ca6038b8 294 return 0;
af6f0d42
TG
295 }
296 }
297
be32eb9b 298 *ret = NULL;
af6f0d42
TG
299 return -ENOENT;
300}
301
54ed9f88 302static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr *mac) {
015b097c 303 unsigned addr_type;
54ed9f88 304 bool want_random = policy == MAC_ADDRESS_POLICY_RANDOM;
f1ac7002 305 int r;
16b9b87a 306
54ed9f88 307 assert(IN_SET(policy, MAC_ADDRESS_POLICY_RANDOM, MAC_ADDRESS_POLICY_PERSISTENT));
3c9b8860 308
015b097c 309 r = link_unsigned_attribute(device, "addr_assign_type", &addr_type);
f1ac7002 310 if (r < 0)
015b097c
ZJS
311 return r;
312 switch (addr_type) {
313 case NET_ADDR_SET:
314 return log_device_debug(device, "MAC on the device already set by userspace");
315 case NET_ADDR_STOLEN:
316 return log_device_debug(device, "MAC on the device already set based on another device");
317 case NET_ADDR_RANDOM:
318 case NET_ADDR_PERM:
319 break;
320 default:
321 return log_device_warning(device, "Unknown addr_assign_type %u, ignoring", addr_type);
322 }
04b67d49 323
015b097c
ZJS
324 if (want_random == (addr_type == NET_ADDR_RANDOM))
325 return log_device_debug(device, "MAC on the device already matches policy *%s*",
54ed9f88 326 mac_address_policy_to_string(policy));
16b9b87a 327
015b097c
ZJS
328 if (want_random) {
329 log_device_debug(device, "Using random bytes to generate MAC");
9bf3b535 330 random_bytes(mac->ether_addr_octet, ETH_ALEN);
015b097c 331 } else {
dbe81cbd 332 uint64_t result;
9bf3b535 333
96848152
ZJS
334 r = net_get_unique_predictable_data(device,
335 naming_scheme_has(NAMING_STABLE_VIRTUAL_MACS),
336 &result);
16b9b87a 337 if (r < 0)
015b097c 338 return log_device_warning_errno(device, r, "Could not generate persistent MAC: %m");
16b9b87a 339
96848152 340 log_device_debug(device, "Using generated persistent MAC address");
9bf3b535 341 assert_cc(ETH_ALEN <= sizeof(result));
dbe81cbd 342 memcpy(mac->ether_addr_octet, &result, ETH_ALEN);
16b9b87a
TG
343 }
344
345 /* see eth_random_addr in the kernel */
3c9b8860
TG
346 mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
347 mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
015b097c 348 return 1;
16b9b87a
TG
349}
350
464cf22f 351int link_config_apply(link_config_ctx *ctx, link_config *config,
e5eadf53 352 sd_device *device, const char **name) {
ef1d2c07 353 _cleanup_strv_free_ char **altnames = NULL;
5fde13d7 354 struct ether_addr generated_mac;
16b9b87a 355 struct ether_addr *mac = NULL;
a39f92d3
SS
356 const char *new_name = NULL;
357 const char *old_name;
0b189e8f
ZJS
358 unsigned speed, name_type = NET_NAME_UNKNOWN;
359 NamePolicy policy;
43b3a5ef 360 int r, ifindex;
af6f0d42 361
3e137a1b
TG
362 assert(ctx);
363 assert(config);
364 assert(device);
365 assert(name);
366
e5eadf53
YW
367 r = sd_device_get_sysname(device, &old_name);
368 if (r < 0)
369 return r;
af6f0d42 370
5c2316c6
YW
371 r = ethtool_set_glinksettings(&ctx->ethtool_fd, old_name,
372 config->autonegotiation, config->advertise,
373 config->speed, config->duplex, config->port);
a39f92d3
SS
374 if (r < 0) {
375
bb79318e 376 if (config->port != _NET_DEV_PORT_INVALID)
49c603bd 377 log_warning_errno(r, "Could not set port (%s) of %s: %m", port_to_string(config->port), old_name);
bb79318e 378
5dd10118 379 if (!eqzero(config->advertise))
2d18ac44 380 log_warning_errno(r, "Could not set advertise mode: %m"); /* TODO: include modes in the log message. */
a39f92d3 381
6cf0a204 382 if (config->speed) {
6cf0a204
SS
383 speed = DIV_ROUND_UP(config->speed, 1000000);
384 if (r == -EOPNOTSUPP) {
385 r = ethtool_set_speed(&ctx->ethtool_fd, old_name, speed, config->duplex);
386 if (r < 0)
387 log_warning_errno(r, "Could not set speed of %s to %u Mbps: %m", old_name, speed);
388 }
389 }
390
6eee8857
YW
391 if (config->duplex != _DUP_INVALID)
392 log_warning_errno(r, "Could not set duplex of %s to %s: %m", old_name, duplex_to_string(config->duplex));
a39f92d3 393 }
a5010333 394
aedca892 395 r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol);
5fde13d7 396 if (r < 0)
755bde37
LP
397 log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m",
398 old_name, wol_to_string(config->wol));
af6f0d42 399
50725d10
SS
400 r = ethtool_set_features(&ctx->ethtool_fd, old_name, config->features);
401 if (r < 0)
402 log_warning_errno(r, "Could not set offload features of %s: %m", old_name);
403
5f945202
SS
404 if (config->channels.rx_count_set || config->channels.tx_count_set || config->channels.other_count_set || config->channels.combined_count_set) {
405 r = ethtool_set_channels(&ctx->ethtool_fd, old_name, &config->channels);
406 if (r < 0)
407 log_warning_errno(r, "Could not set channels of %s: %m", old_name);
408 }
409
224ded67
SS
410 if (config->ring.rx_pending_set || config->ring.tx_pending_set) {
411 r = ethtool_set_nic_buffer_size(&ctx->ethtool_fd, old_name, &config->ring);
412 if (r < 0)
413 log_warning_errno(r, "Could not set ring buffer of %s: %m", old_name);
414 }
415
a34811e4
YW
416 r = ethtool_set_flow_control(&ctx->ethtool_fd, old_name, config->rx_flow_control, config->tx_flow_control, config->autoneg_flow_control);
417 if (r < 0)
418 log_warning_errno(r, "Could not set flow control of %s: %m", old_name);
419
e5eadf53
YW
420 r = sd_device_get_ifindex(device, &ifindex);
421 if (r < 0)
b220632c 422 return log_device_warning_errno(device, r, "Could not find ifindex: %m");
43b3a5ef 423
015b097c 424 (void) link_unsigned_attribute(device, "name_assign_type", &name_type);
0b189e8f 425
73d2bb08
ZJS
426 if (IN_SET(name_type, NET_NAME_USER, NET_NAME_RENAMED)
427 && !naming_scheme_has(NAMING_ALLOW_RERENAMES)) {
428 log_device_debug(device, "Device already has a name given by userspace, not renaming.");
429 goto no_rename;
430 }
431
0b189e8f 432 if (ctx->enable_name_policy && config->name_policy)
78f8849f 433 for (NamePolicy *p = config->name_policy; *p != _NAMEPOLICY_INVALID; p++) {
0b189e8f
ZJS
434 policy = *p;
435
436 switch (policy) {
437 case NAMEPOLICY_KERNEL:
438 if (name_type != NET_NAME_PREDICTABLE)
439 continue;
440
441 /* The kernel claims to have given a predictable name, keep it. */
442 log_device_debug(device, "Policy *%s*: keeping predictable kernel name",
443 name_policy_to_string(policy));
444 goto no_rename;
3907446f
ZJS
445 case NAMEPOLICY_KEEP:
446 if (!IN_SET(name_type, NET_NAME_USER, NET_NAME_RENAMED))
447 continue;
448
449 log_device_debug(device, "Policy *%s*: keeping existing userspace name",
450 name_policy_to_string(policy));
451 goto no_rename;
0b189e8f
ZJS
452 case NAMEPOLICY_DATABASE:
453 (void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &new_name);
454 break;
455 case NAMEPOLICY_ONBOARD:
456 (void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &new_name);
457 break;
458 case NAMEPOLICY_SLOT:
459 (void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &new_name);
460 break;
461 case NAMEPOLICY_PATH:
462 (void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &new_name);
463 break;
464 case NAMEPOLICY_MAC:
465 (void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &new_name);
466 break;
467 default:
468 assert_not_reached("invalid policy");
5fde13d7 469 }
78f8849f
YW
470 if (ifname_valid(new_name))
471 break;
daeb71a3 472 }
daeb71a3 473
0b189e8f
ZJS
474 if (new_name)
475 log_device_debug(device, "Policy *%s* yields \"%s\".", name_policy_to_string(policy), new_name);
476 else if (config->name) {
477 new_name = config->name;
478 log_device_debug(device, "Policies didn't yield a name, using specified Name=%s.", new_name);
ed308023 479 } else
0b189e8f
ZJS
480 log_device_debug(device, "Policies didn't yield a name and Name= is not given, not renaming.");
481 no_rename:
04b67d49 482
54ed9f88
ZJS
483 if (IN_SET(config->mac_address_policy, MAC_ADDRESS_POLICY_PERSISTENT, MAC_ADDRESS_POLICY_RANDOM)) {
484 if (get_mac(device, config->mac_address_policy, &generated_mac) > 0)
015b097c
ZJS
485 mac = &generated_mac;
486 } else
487 mac = config->mac;
16b9b87a 488
dab495dc 489 r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac, config->mtu);
f647962d 490 if (r < 0)
7b72fe21 491 return log_warning_errno(r, "Could not set Alias=, MACAddress= or MTU= on %s: %m", old_name);
43b3a5ef 492
ef1d2c07
YW
493 if (config->alternative_names) {
494 altnames = strv_copy(config->alternative_names);
495 if (!altnames)
496 return log_oom();
497 }
498
499 if (config->alternative_names_policy)
500 for (NamePolicy *p = config->alternative_names_policy; *p != _NAMEPOLICY_INVALID; p++) {
501 const char *n;
502
503 switch (*p) {
504 case NAMEPOLICY_DATABASE:
505 (void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &n);
506 break;
507 case NAMEPOLICY_ONBOARD:
508 (void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &n);
509 break;
510 case NAMEPOLICY_SLOT:
511 (void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &n);
512 break;
513 case NAMEPOLICY_PATH:
514 (void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &n);
515 break;
516 case NAMEPOLICY_MAC:
517 (void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &n);
518 break;
519 default:
520 assert_not_reached("invalid policy");
521 }
522 if (!isempty(n)) {
523 r = strv_extend(&altnames, n);
524 if (r < 0)
525 return log_oom();
526 }
527 }
528
529 if (new_name)
530 strv_remove(altnames, new_name);
531 strv_remove(altnames, old_name);
532 strv_uniq(altnames);
4d016e96 533 strv_sort(altnames);
ef1d2c07
YW
534
535 r = rtnl_set_link_alternative_names(&ctx->rtnl, ifindex, altnames);
bb181dd4 536 if (r == -EOPNOTSUPP)
ef1d2c07 537 log_debug_errno(r, "Could not set AlternativeName= or apply AlternativeNamesPolicy= on %s, ignoring: %m", old_name);
bb181dd4 538 else if (r < 0)
ef1d2c07 539 return log_warning_errno(r, "Could not set AlternativeName= or apply AlternativeNamesPolicy= on %s: %m", old_name);
a5053a15 540
d95b83b8
TG
541 *name = new_name;
542
af6f0d42
TG
543 return 0;
544}
be32eb9b 545
e5eadf53 546int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret) {
847a8a5f 547 const char *name;
a7f7d1bd 548 char *driver = NULL;
847a8a5f
TG
549 int r;
550
e5eadf53
YW
551 r = sd_device_get_sysname(device, &name);
552 if (r < 0)
553 return r;
847a8a5f 554
aedca892 555 r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver);
847a8a5f
TG
556 if (r < 0)
557 return r;
558
559 *ret = driver;
560 return 0;
561}
562
54ed9f88
ZJS
563static const char* const mac_address_policy_table[_MAC_ADDRESS_POLICY_MAX] = {
564 [MAC_ADDRESS_POLICY_PERSISTENT] = "persistent",
565 [MAC_ADDRESS_POLICY_RANDOM] = "random",
566 [MAC_ADDRESS_POLICY_NONE] = "none",
be32eb9b
TG
567};
568
54ed9f88
ZJS
569DEFINE_STRING_TABLE_LOOKUP(mac_address_policy, MACAddressPolicy);
570DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_address_policy, mac_address_policy, MACAddressPolicy,
464cf22f 571 "Failed to parse MAC address policy");
be32eb9b 572
2c5859af 573static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
04b67d49 574 [NAMEPOLICY_KERNEL] = "kernel",
3907446f 575 [NAMEPOLICY_KEEP] = "keep",
e51660ae 576 [NAMEPOLICY_DATABASE] = "database",
be32eb9b
TG
577 [NAMEPOLICY_ONBOARD] = "onboard",
578 [NAMEPOLICY_SLOT] = "slot",
579 [NAMEPOLICY_PATH] = "path",
3907446f 580 [NAMEPOLICY_MAC] = "mac",
be32eb9b
TG
581};
582
583DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
464cf22f
TG
584DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy,
585 _NAMEPOLICY_INVALID,
586 "Failed to parse interface name policy");
ef1d2c07
YW
587
588static const char* const alternative_names_policy_table[_NAMEPOLICY_MAX] = {
589 [NAMEPOLICY_DATABASE] = "database",
590 [NAMEPOLICY_ONBOARD] = "onboard",
591 [NAMEPOLICY_SLOT] = "slot",
592 [NAMEPOLICY_PATH] = "path",
593 [NAMEPOLICY_MAC] = "mac",
594};
595
596DEFINE_STRING_TABLE_LOOKUP(alternative_names_policy, NamePolicy);
597DEFINE_CONFIG_PARSE_ENUMV(config_parse_alternative_names_policy, alternative_names_policy, NamePolicy,
598 _NAMEPOLICY_INVALID,
599 "Failed to parse alternative names policy");