1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <linux/netdevice.h>
4 #include <netinet/ether.h>
8 #include "sd-netlink.h"
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"
21 #include "link-config.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"
39 struct LinkConfigContext
{
40 LIST_HEAD(LinkConfig
, configs
);
42 Hashmap
*stats_by_path
;
45 static LinkConfig
* link_config_free(LinkConfig
*config
) {
49 free(config
->filename
);
50 strv_free(config
->dropins
);
52 net_match_clear(&config
->match
);
53 condition_free_list(config
->conditions
);
55 free(config
->description
);
56 free(config
->name_policy
);
58 strv_free(config
->alternative_names
);
59 free(config
->alternative_names_policy
);
61 free(config
->wol_password_file
);
62 erase_and_free(config
->wol_password
);
64 ordered_hashmap_free_with_destructor(config
->sr_iov_by_section
, sr_iov_free
);
69 DEFINE_TRIVIAL_CLEANUP_FUNC(LinkConfig
*, link_config_free
);
71 static void link_configs_free(LinkConfigContext
*ctx
) {
75 ctx
->stats_by_path
= hashmap_free(ctx
->stats_by_path
);
77 LIST_FOREACH(configs
, config
, ctx
->configs
)
78 link_config_free(config
);
81 LinkConfigContext
*link_config_ctx_free(LinkConfigContext
*ctx
) {
85 safe_close(ctx
->ethtool_fd
);
86 link_configs_free(ctx
);
90 int link_config_ctx_new(LinkConfigContext
**ret
) {
91 _cleanup_(link_config_ctx_freep
) LinkConfigContext
*ctx
= NULL
;
96 ctx
= new(LinkConfigContext
, 1);
100 *ctx
= (LinkConfigContext
) {
101 .ethtool_fd
= -EBADF
,
104 *ret
= TAKE_PTR(ctx
);
109 static int link_parse_wol_password(LinkConfig
*config
, const char *str
) {
110 _cleanup_(erase_and_freep
) uint8_t *p
= NULL
;
116 assert_cc(sizeof(struct ether_addr
) == SOPASS_MAX
);
118 p
= new(uint8_t, SOPASS_MAX
);
122 /* Reuse parse_ether_addr(), as their formats are equivalent. */
123 r
= parse_ether_addr(str
, (struct ether_addr
*) p
);
127 erase_and_free(config
->wol_password
);
128 config
->wol_password
= TAKE_PTR(p
);
132 static int link_read_wol_password_from_file(LinkConfig
*config
) {
133 _cleanup_(erase_and_freep
) char *password
= NULL
;
138 if (!config
->wol_password_file
)
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
);
148 return link_parse_wol_password(config
, password
);
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
;
157 assert(config
->filename
);
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. */
168 r
= path_extract_filename(config
->filename
, &base
);
172 cred_name
= strjoin(base
, ".wol.password");
176 r
= read_credential(cred_name
, (void**) &password
, NULL
);
178 r
= read_credential("wol.password", (void**) &password
, NULL
);
182 return link_parse_wol_password(config
, password
);
185 static int link_adjust_wol_options(LinkConfig
*config
) {
190 r
= link_read_wol_password_from_file(config
);
194 log_warning_errno(r
, "Failed to read WakeOnLan password from %s, ignoring: %m", config
->wol_password_file
);
196 r
= link_read_wol_password_from_cred(config
);
200 log_warning_errno(r
, "Failed to read WakeOnLan password from credential, ignoring: %m");
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
;
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
;
222 r
= null_or_empty_path(filename
);
224 return log_warning_errno(r
, "Failed to check if \"%s\" is empty: %m", filename
);
226 log_debug("Skipping empty file: %s", filename
);
230 name
= strdup(filename
);
234 config
= new(LinkConfig
, 1);
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
,
255 for (i
= 0; i
< ELEMENTSOF(config
->features
); i
++)
256 config
->features
[i
] = -1;
258 dropin_dirname
= strjoina(basename(filename
), ".d");
259 r
= config_parse_many(
260 STRV_MAKE_CONST(filename
),
267 config_item_perf_lookup
, link_config_gperf_lookup
,
268 CONFIG_PARSE_WARN
, config
, &stats_by_path
,
271 return r
; /* config_parse_many() logs internally. */
273 if (ctx
->stats_by_path
) {
274 r
= hashmap_move(ctx
->stats_by_path
, stats_by_path
);
276 log_warning_errno(r
, "Failed to save stats of '%s' and its drop-in configs, ignoring: %m", filename
);
278 ctx
->stats_by_path
= TAKE_PTR(stats_by_path
);
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.",
287 if (!condition_test_list(config
->conditions
, environ
, NULL
, NULL
, NULL
)) {
288 log_debug("%s: Conditions do not match the system environment, skipping.", filename
);
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\".",
298 r
= link_adjust_wol_options(config
);
300 return r
; /* link_adjust_wol_options() logs internally. */
302 r
= sr_iov_drop_invalid_sections(config
->sr_iov_num_vfs
, config
->sr_iov_by_section
);
304 return r
; /* sr_iov_drop_invalid_sections() logs internally. */
306 log_debug("Parsed configuration file \"%s\"", filename
);
308 LIST_PREPEND(configs
, ctx
->configs
, TAKE_PTR(config
));
312 static int device_unsigned_attribute(sd_device
*device
, const char *attr
, unsigned *type
) {
316 r
= sd_device_get_sysattr_value(device
, attr
, &s
);
318 return log_device_debug_errno(device
, r
, "Failed to query %s: %m", attr
);
320 r
= safe_atou(s
, type
);
322 return log_device_warning_errno(device
, r
, "Failed to parse %s \"%s\": %m", attr
, s
);
324 log_device_debug(device
, "Device has %s=%u", attr
, *type
);
328 int link_config_load(LinkConfigContext
*ctx
) {
329 _cleanup_strv_free_
char **files
= NULL
;
334 link_configs_free(ctx
);
336 r
= conf_files_list_strv(&files
, ".link", NULL
, 0, NETWORK_DIRS
);
338 return log_error_errno(r
, "failed to enumerate link files: %m");
340 STRV_FOREACH_BACKWARDS(f
, files
)
341 (void) link_load_one(ctx
, *f
);
346 bool link_config_should_reload(LinkConfigContext
*ctx
) {
347 _cleanup_hashmap_free_ Hashmap
*stats_by_path
= NULL
;
352 r
= config_get_stats_by_path(".link", NULL
, 0, NETWORK_DIRS
, /* check_dropins = */ true, &stats_by_path
);
354 log_warning_errno(r
, "Failed to get stats of .link files, ignoring: %m");
358 return !stats_by_path_equal(ctx
->stats_by_path
, stats_by_path
);
361 Link
*link_free(Link
*link
) {
365 sd_device_unref(link
->device
);
371 int link_new(LinkConfigContext
*ctx
, sd_netlink
**rtnl
, sd_device
*device
, Link
**ret
) {
372 _cleanup_(link_freep
) Link
*link
= NULL
;
385 .device
= sd_device_ref(device
),
388 r
= sd_device_get_sysname(device
, &link
->ifname
);
392 r
= sd_device_get_ifindex(device
, &link
->ifindex
);
396 r
= sd_device_get_action(device
, &link
->action
);
400 r
= device_unsigned_attribute(device
, "name_assign_type", &link
->name_assign_type
);
402 log_link_debug_errno(link
, r
, "Failed to get \"name_assign_type\" attribute, ignoring: %m");
404 r
= device_unsigned_attribute(device
, "addr_assign_type", &link
->addr_assign_type
);
406 log_link_debug_errno(link
, r
, "Failed to get \"addr_assign_type\" attribute, ignoring: %m");
408 r
= rtnl_get_link_info(rtnl
, link
->ifindex
, &link
->iftype
, &link
->flags
,
409 &link
->kind
, &link
->hw_addr
, &link
->permanent_hw_addr
);
413 if (link
->hw_addr
.length
> 0 && link
->permanent_hw_addr
.length
== 0) {
414 r
= ethtool_get_permanent_hw_addr(&ctx
->ethtool_fd
, link
->ifname
, &link
->permanent_hw_addr
);
416 log_link_debug_errno(link
, r
, "Failed to get permanent hardware address, ignoring: %m");
419 r
= ethtool_get_driver(&ctx
->ethtool_fd
, link
->ifname
, &link
->driver
);
421 log_link_debug_errno(link
, r
, "Failed to get driver, ignoring: %m");
423 *ret
= TAKE_PTR(link
);
427 int link_get_config(LinkConfigContext
*ctx
, Link
*link
) {
433 /* Do not configure loopback interfaces by .link files. */
434 if (link
->flags
& IFF_LOOPBACK
)
437 LIST_FOREACH(configs
, config
, ctx
->configs
) {
438 r
= net_match_config(
442 &link
->permanent_hw_addr
,
447 /* alternative_names = */ NULL
,
448 /* wlan_iftype = */ 0,
456 if (config
->match
.ifname
&& !strv_contains(config
->match
.ifname
, "*") && link
->name_assign_type
== NET_NAME_ENUM
)
457 log_link_warning(link
, "Config file %s is applied to device based on potentially unpredictable interface name.",
460 log_link_debug(link
, "Config file %s is applied", config
->filename
);
462 link
->config
= config
;
469 static int link_apply_ethtool_settings(Link
*link
, int *ethtool_fd
) {
475 assert(link
->config
);
478 config
= link
->config
;
481 r
= ethtool_set_glinksettings(ethtool_fd
, name
,
482 config
->autonegotiation
, config
->advertise
,
483 config
->speed
, config
->duplex
, config
->port
, config
->mdi
);
485 if (config
->autonegotiation
>= 0)
486 log_link_warning_errno(link
, r
, "Could not %s auto negotiation, ignoring: %m",
487 enable_disable(config
->autonegotiation
));
489 if (!eqzero(config
->advertise
))
490 log_link_warning_errno(link
, r
, "Could not set advertise mode, ignoring: %m");
492 if (config
->speed
> 0)
493 log_link_warning_errno(link
, r
, "Could not set speed to %"PRIu64
"Mbps, ignoring: %m",
494 DIV_ROUND_UP(config
->speed
, 1000000));
496 if (config
->duplex
>= 0)
497 log_link_warning_errno(link
, r
, "Could not set duplex to %s, ignoring: %m",
498 duplex_to_string(config
->duplex
));
500 if (config
->port
>= 0)
501 log_link_warning_errno(link
, r
, "Could not set port to '%s', ignoring: %m",
502 port_to_string(config
->port
));
504 if (config
->mdi
!= ETH_TP_MDI_INVALID
)
505 log_link_warning_errno(link
, r
, "Could not set MDI-X to '%s', ignoring: %m",
506 mdi_to_string(config
->mdi
));
509 r
= ethtool_set_wol(ethtool_fd
, name
, config
->wol
, config
->wol_password
);
511 _cleanup_free_
char *str
= NULL
;
513 (void) wol_options_to_string_alloc(config
->wol
, &str
);
514 log_link_warning_errno(link
, r
, "Could not set WakeOnLan%s%s, ignoring: %m",
515 isempty(str
) ? "" : " to ", strempty(str
));
518 r
= ethtool_set_features(ethtool_fd
, name
, config
->features
);
520 log_link_warning_errno(link
, r
, "Could not set offload features, ignoring: %m");
522 r
= ethtool_set_channels(ethtool_fd
, name
, &config
->channels
);
524 log_link_warning_errno(link
, r
, "Could not set channels, ignoring: %m");
526 r
= ethtool_set_nic_buffer_size(ethtool_fd
, name
, &config
->ring
);
528 log_link_warning_errno(link
, r
, "Could not set ring buffer, ignoring: %m");
530 r
= ethtool_set_flow_control(ethtool_fd
, name
, config
->rx_flow_control
, config
->tx_flow_control
, config
->autoneg_flow_control
);
532 log_link_warning_errno(link
, r
, "Could not set flow control, ignoring: %m");
534 r
= ethtool_set_nic_coalesce_settings(ethtool_fd
, name
, &config
->coalesce
);
536 log_link_warning_errno(link
, r
, "Could not set coalesce settings, ignoring: %m");
541 static bool hw_addr_is_valid(Link
*link
, const struct hw_addr_data
*hw_addr
) {
545 switch (link
->iftype
) {
547 /* Refuse all zero and all 0xFF. */
548 assert(hw_addr
->length
== ETH_ALEN
);
549 return !ether_addr_is_null(&hw_addr
->ether
) && !ether_addr_is_broadcast(&hw_addr
->ether
);
551 case ARPHRD_INFINIBAND
:
552 /* The last 8 bytes cannot be zero. */
553 assert(hw_addr
->length
== INFINIBAND_ALEN
);
554 return !memeqzero(hw_addr
->bytes
+ INFINIBAND_ALEN
- 8, 8);
557 assert_not_reached();
561 static int link_generate_new_hw_addr(Link
*link
, struct hw_addr_data
*ret
) {
562 struct hw_addr_data hw_addr
= HW_ADDR_NULL
;
563 bool is_static
= false;
569 assert(link
->config
);
570 assert(link
->device
);
573 if (link
->hw_addr
.length
== 0)
576 if (link
->config
->mac_address_policy
== MAC_ADDRESS_POLICY_NONE
) {
577 log_link_debug(link
, "Using static MAC address.");
578 hw_addr
= link
->config
->hw_addr
;
583 if (!IN_SET(link
->iftype
, ARPHRD_ETHER
, ARPHRD_INFINIBAND
))
586 switch (link
->addr_assign_type
) {
588 log_link_debug(link
, "MAC address on the device already set by userspace.");
590 case NET_ADDR_STOLEN
:
591 log_link_debug(link
, "MAC address on the device already set based on another device.");
593 case NET_ADDR_RANDOM
:
597 log_link_warning(link
, "Unknown addr_assign_type %u, ignoring", link
->addr_assign_type
);
601 if ((link
->config
->mac_address_policy
== MAC_ADDRESS_POLICY_RANDOM
) == (link
->addr_assign_type
== NET_ADDR_RANDOM
)) {
602 log_link_debug(link
, "MAC address on the device already matches policy \"%s\".",
603 mac_address_policy_to_string(link
->config
->mac_address_policy
));
607 hw_addr
= (struct hw_addr_data
) {
608 .length
= arphrd_to_hw_addr_len(link
->iftype
),
611 switch (link
->iftype
) {
614 len
= hw_addr
.length
;
616 case ARPHRD_INFINIBAND
:
617 p
= hw_addr
.bytes
+ INFINIBAND_ALEN
- 8;
621 assert_not_reached();
624 if (link
->config
->mac_address_policy
== MAC_ADDRESS_POLICY_RANDOM
)
625 /* We require genuine randomness here, since we want to make sure we won't collide with other
626 * systems booting up at the very same time. */
628 random_bytes(p
, len
);
629 if (hw_addr_is_valid(link
, &hw_addr
))
636 r
= net_get_unique_predictable_data(link
->device
,
637 naming_scheme_has(NAMING_STABLE_VIRTUAL_MACS
),
640 return log_link_warning_errno(link
, r
, "Could not generate persistent MAC address: %m");
642 assert(len
<= sizeof(result
));
643 memcpy(p
, &result
, len
);
644 if (!hw_addr_is_valid(link
, &hw_addr
))
645 return log_link_warning_errno(link
, SYNTHETIC_ERRNO(EINVAL
),
646 "Could not generate valid persistent MAC address: %m");
651 r
= net_verify_hardware_address(link
->ifname
, is_static
, link
->iftype
, &link
->hw_addr
, &hw_addr
);
655 if (hw_addr_equal(&link
->hw_addr
, &hw_addr
)) {
660 if (hw_addr
.length
> 0)
661 log_link_debug(link
, "Applying %s MAC address: %s",
662 link
->config
->mac_address_policy
== MAC_ADDRESS_POLICY_NONE
? "static" :
663 mac_address_policy_to_string(link
->config
->mac_address_policy
),
664 HW_ADDR_TO_STR(&hw_addr
));
670 static int link_apply_rtnl_settings(Link
*link
, sd_netlink
**rtnl
) {
671 struct hw_addr_data hw_addr
= {};
676 assert(link
->config
);
679 config
= link
->config
;
681 (void) link_generate_new_hw_addr(link
, &hw_addr
);
683 r
= rtnl_set_link_properties(rtnl
, link
->ifindex
, config
->alias
, &hw_addr
,
684 config
->txqueues
, config
->rxqueues
, config
->txqueuelen
,
685 config
->mtu
, config
->gso_max_size
, config
->gso_max_segments
);
687 log_link_warning_errno(link
, r
,
688 "Could not set Alias=, MACAddress=/MACAddressPolicy=, "
689 "TransmitQueues=, ReceiveQueues=, TransmitQueueLength=, MTUBytes=, "
690 "GenericSegmentOffloadMaxBytes= or GenericSegmentOffloadMaxSegments=, "
696 static bool enable_name_policy(void) {
697 static int cached
= -1;
704 r
= proc_cmdline_get_bool("net.ifnames", &b
);
706 log_warning_errno(r
, "Failed to parse net.ifnames= kernel command line option, ignoring: %m");
708 return (cached
= true);
711 log_info("Network interface NamePolicy= disabled on kernel command line.");
716 static int link_generate_new_name(Link
*link
) {
721 assert(link
->config
);
722 assert(link
->device
);
724 config
= link
->config
;
725 device
= link
->device
;
727 if (link
->action
!= SD_DEVICE_ADD
) {
728 log_link_debug(link
, "Skipping to apply Name= and NamePolicy= on '%s' uevent.",
729 device_action_to_string(link
->action
));
733 if (IN_SET(link
->name_assign_type
, NET_NAME_USER
, NET_NAME_RENAMED
) &&
734 !naming_scheme_has(NAMING_ALLOW_RERENAMES
)) {
735 log_link_debug(link
, "Device already has a name given by userspace, not renaming.");
739 if (enable_name_policy() && config
->name_policy
)
740 for (NamePolicy
*policy
= config
->name_policy
; *policy
!= _NAMEPOLICY_INVALID
; policy
++) {
741 const char *new_name
= NULL
;
744 case NAMEPOLICY_KERNEL
:
745 if (link
->name_assign_type
!= NET_NAME_PREDICTABLE
)
748 /* The kernel claims to have given a predictable name, keep it. */
749 log_link_debug(link
, "Policy *%s*: keeping predictable kernel name",
750 name_policy_to_string(*policy
));
752 case NAMEPOLICY_KEEP
:
753 if (!IN_SET(link
->name_assign_type
, NET_NAME_USER
, NET_NAME_RENAMED
))
756 log_link_debug(link
, "Policy *%s*: keeping existing userspace name",
757 name_policy_to_string(*policy
));
759 case NAMEPOLICY_DATABASE
:
760 (void) sd_device_get_property_value(device
, "ID_NET_NAME_FROM_DATABASE", &new_name
);
762 case NAMEPOLICY_ONBOARD
:
763 (void) sd_device_get_property_value(device
, "ID_NET_NAME_ONBOARD", &new_name
);
765 case NAMEPOLICY_SLOT
:
766 (void) sd_device_get_property_value(device
, "ID_NET_NAME_SLOT", &new_name
);
768 case NAMEPOLICY_PATH
:
769 (void) sd_device_get_property_value(device
, "ID_NET_NAME_PATH", &new_name
);
772 (void) sd_device_get_property_value(device
, "ID_NET_NAME_MAC", &new_name
);
775 assert_not_reached();
777 if (ifname_valid(new_name
)) {
778 log_link_debug(link
, "Policy *%s* yields \"%s\".", name_policy_to_string(*policy
), new_name
);
779 link
->new_name
= new_name
;
784 if (link
->config
->name
) {
785 log_link_debug(link
, "Policies didn't yield a name, using specified Name=%s.", link
->config
->name
);
786 link
->new_name
= link
->config
->name
;
790 log_link_debug(link
, "Policies didn't yield a name and Name= is not given, not renaming.");
792 link
->new_name
= link
->ifname
;
796 static int link_apply_alternative_names(Link
*link
, sd_netlink
**rtnl
) {
797 _cleanup_strv_free_
char **altnames
= NULL
, **current_altnames
= NULL
;
803 assert(link
->config
);
804 assert(link
->device
);
807 config
= link
->config
;
808 device
= link
->device
;
810 if (config
->alternative_names
) {
811 altnames
= strv_copy(config
->alternative_names
);
816 if (config
->alternative_names_policy
)
817 for (NamePolicy
*p
= config
->alternative_names_policy
; *p
!= _NAMEPOLICY_INVALID
; p
++) {
818 const char *n
= NULL
;
821 case NAMEPOLICY_DATABASE
:
822 (void) sd_device_get_property_value(device
, "ID_NET_NAME_FROM_DATABASE", &n
);
824 case NAMEPOLICY_ONBOARD
:
825 (void) sd_device_get_property_value(device
, "ID_NET_NAME_ONBOARD", &n
);
827 case NAMEPOLICY_SLOT
:
828 (void) sd_device_get_property_value(device
, "ID_NET_NAME_SLOT", &n
);
830 case NAMEPOLICY_PATH
:
831 (void) sd_device_get_property_value(device
, "ID_NET_NAME_PATH", &n
);
834 (void) sd_device_get_property_value(device
, "ID_NET_NAME_MAC", &n
);
837 assert_not_reached();
839 if (ifname_valid_full(n
, IFNAME_VALID_ALTERNATIVE
)) {
840 r
= strv_extend(&altnames
, n
);
846 strv_remove(altnames
, link
->ifname
);
848 r
= rtnl_get_link_alternative_names(rtnl
, link
->ifindex
, ¤t_altnames
);
850 log_link_debug_errno(link
, r
, "Failed to get alternative names, ignoring: %m");
852 STRV_FOREACH(p
, current_altnames
)
853 strv_remove(altnames
, *p
);
857 r
= rtnl_set_link_alternative_names(rtnl
, link
->ifindex
, altnames
);
859 log_link_full_errno(link
, r
== -EOPNOTSUPP
? LOG_DEBUG
: LOG_WARNING
, r
,
860 "Could not set AlternativeName= or apply AlternativeNamesPolicy=, ignoring: %m");
865 static int sr_iov_configure(Link
*link
, sd_netlink
**rtnl
, SRIOV
*sr_iov
) {
866 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
871 assert(link
->ifindex
> 0);
874 r
= sd_netlink_open(rtnl
);
879 r
= sd_rtnl_message_new_link(*rtnl
, &req
, RTM_SETLINK
, link
->ifindex
);
883 r
= sr_iov_set_netlink_message(sr_iov
, req
);
887 r
= sd_netlink_call(*rtnl
, req
, 0, NULL
);
894 static int link_apply_sr_iov_config(Link
*link
, sd_netlink
**rtnl
) {
900 assert(link
->config
);
901 assert(link
->device
);
903 r
= sr_iov_set_num_vfs(link
->device
, link
->config
->sr_iov_num_vfs
, link
->config
->sr_iov_by_section
);
905 log_link_warning_errno(link
, r
, "Failed to set the number of SR-IOV virtual functions, ignoring: %m");
907 if (ordered_hashmap_isempty(link
->config
->sr_iov_by_section
))
910 r
= sr_iov_get_num_vfs(link
->device
, &n
);
912 log_link_warning_errno(link
, r
, "Failed to get the number of SR-IOV virtual functions, ignoring [SR-IOV] sections: %m");
916 log_link_warning(link
, "No SR-IOV virtual function exists, ignoring [SR-IOV] sections: %m");
920 ORDERED_HASHMAP_FOREACH(sr_iov
, link
->config
->sr_iov_by_section
) {
921 if (sr_iov
->vf
>= n
) {
922 log_link_warning(link
, "SR-IOV virtual function %"PRIu32
" does not exist, ignoring.", sr_iov
->vf
);
926 r
= sr_iov_configure(link
, rtnl
, sr_iov
);
928 log_link_warning_errno(link
, r
,
929 "Failed to configure SR-IOV virtual function %"PRIu32
", ignoring: %m",
936 int link_apply_config(LinkConfigContext
*ctx
, sd_netlink
**rtnl
, Link
*link
) {
943 if (!IN_SET(link
->action
, SD_DEVICE_ADD
, SD_DEVICE_BIND
, SD_DEVICE_MOVE
)) {
944 log_link_debug(link
, "Skipping to apply .link settings on '%s' uevent.",
945 device_action_to_string(link
->action
));
947 link
->new_name
= link
->ifname
;
951 r
= link_apply_ethtool_settings(link
, &ctx
->ethtool_fd
);
955 r
= link_apply_rtnl_settings(link
, rtnl
);
959 r
= link_generate_new_name(link
);
963 r
= link_apply_alternative_names(link
, rtnl
);
967 r
= link_apply_sr_iov_config(link
, rtnl
);
974 int config_parse_ifalias(
976 const char *filename
,
979 unsigned section_line
,
986 char **s
= ASSERT_PTR(data
);
992 if (isempty(rvalue
)) {
997 if (!ascii_is_valid(rvalue
)) {
998 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
999 "Interface alias is not ASCII clean, ignoring assignment: %s", rvalue
);
1003 if (strlen(rvalue
) >= IFALIASZ
) {
1004 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
1005 "Interface alias is too long, ignoring assignment: %s", rvalue
);
1009 return free_and_strdup_warn(s
, rvalue
);
1012 int config_parse_rx_tx_queues(
1014 const char *filename
,
1016 const char *section
,
1017 unsigned section_line
,
1024 uint32_t k
, *v
= data
;
1027 if (isempty(rvalue
)) {
1032 r
= safe_atou32(rvalue
, &k
);
1034 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse %s=, ignoring assignment: %s.", lvalue
, rvalue
);
1037 if (k
== 0 || k
> 4096) {
1038 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0, "Invalid %s=, ignoring assignment: %s.", lvalue
, rvalue
);
1046 int config_parse_txqueuelen(
1048 const char *filename
,
1050 const char *section
,
1051 unsigned section_line
,
1058 uint32_t k
, *v
= data
;
1061 if (isempty(rvalue
)) {
1066 r
= safe_atou32(rvalue
, &k
);
1068 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse %s=, ignoring assignment: %s.", lvalue
, rvalue
);
1071 if (k
== UINT32_MAX
) {
1072 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0, "Invalid %s=, ignoring assignment: %s.", lvalue
, rvalue
);
1080 int config_parse_wol_password(
1082 const char *filename
,
1084 const char *section
,
1085 unsigned section_line
,
1092 LinkConfig
*config
= ASSERT_PTR(userdata
);
1099 if (isempty(rvalue
)) {
1100 config
->wol_password
= erase_and_free(config
->wol_password
);
1101 config
->wol_password_file
= mfree(config
->wol_password_file
);
1105 if (path_is_absolute(rvalue
) && path_is_safe(rvalue
)) {
1106 config
->wol_password
= erase_and_free(config
->wol_password
);
1107 return free_and_strdup_warn(&config
->wol_password_file
, rvalue
);
1110 warn_file_is_world_accessible(filename
, NULL
, unit
, line
);
1112 r
= link_parse_wol_password(config
, rvalue
);
1116 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1117 "Failed to parse %s=, ignoring assignment: %s.", lvalue
, rvalue
);
1121 config
->wol_password_file
= mfree(config
->wol_password_file
);
1125 static const char* const mac_address_policy_table
[_MAC_ADDRESS_POLICY_MAX
] = {
1126 [MAC_ADDRESS_POLICY_PERSISTENT
] = "persistent",
1127 [MAC_ADDRESS_POLICY_RANDOM
] = "random",
1128 [MAC_ADDRESS_POLICY_NONE
] = "none",
1131 DEFINE_STRING_TABLE_LOOKUP(mac_address_policy
, MACAddressPolicy
);
1132 DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(
1133 config_parse_mac_address_policy
,
1136 MAC_ADDRESS_POLICY_NONE
,
1137 "Failed to parse MAC address policy");
1139 DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy
, name_policy
, NamePolicy
,
1140 _NAMEPOLICY_INVALID
,
1141 "Failed to parse interface name policy");
1143 DEFINE_CONFIG_PARSE_ENUMV(config_parse_alternative_names_policy
, alternative_names_policy
, NamePolicy
,
1144 _NAMEPOLICY_INVALID
,
1145 "Failed to parse alternative names policy");