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 "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-util.h"
26 #include "netlink-util.h"
27 #include "parse-util.h"
28 #include "path-lookup.h"
29 #include "path-util.h"
30 #include "proc-cmdline.h"
31 #include "random-util.h"
32 #include "stat-util.h"
33 #include "string-table.h"
34 #include "string-util.h"
38 struct LinkConfigContext
{
39 LIST_HEAD(LinkConfig
, configs
);
41 bool enable_name_policy
;
42 usec_t network_dirs_ts_usec
;
45 static LinkConfig
* link_config_free(LinkConfig
*config
) {
49 free(config
->filename
);
51 net_match_clear(&config
->match
);
52 condition_free_list(config
->conditions
);
54 free(config
->description
);
55 free(config
->name_policy
);
57 strv_free(config
->alternative_names
);
58 free(config
->alternative_names_policy
);
60 free(config
->wol_password_file
);
61 erase_and_free(config
->wol_password
);
66 DEFINE_TRIVIAL_CLEANUP_FUNC(LinkConfig
*, link_config_free
);
68 static void link_configs_free(LinkConfigContext
*ctx
) {
69 LinkConfig
*config
, *config_next
;
74 LIST_FOREACH_SAFE(configs
, config
, config_next
, ctx
->configs
)
75 link_config_free(config
);
78 LinkConfigContext
*link_config_ctx_free(LinkConfigContext
*ctx
) {
82 safe_close(ctx
->ethtool_fd
);
83 link_configs_free(ctx
);
87 int link_config_ctx_new(LinkConfigContext
**ret
) {
88 _cleanup_(link_config_ctx_freep
) LinkConfigContext
*ctx
= NULL
;
93 ctx
= new(LinkConfigContext
, 1);
97 *ctx
= (LinkConfigContext
) {
99 .enable_name_policy
= true,
102 *ret
= TAKE_PTR(ctx
);
107 static int link_parse_wol_password(LinkConfig
*config
, const char *str
) {
108 _cleanup_(erase_and_freep
) uint8_t *p
= NULL
;
114 assert_cc(sizeof(struct ether_addr
) == SOPASS_MAX
);
116 p
= new(uint8_t, SOPASS_MAX
);
120 /* Reuse parse_ether_addr(), as their formats are equivalent. */
121 r
= parse_ether_addr(str
, (struct ether_addr
*) p
);
125 erase_and_free(config
->wol_password
);
126 config
->wol_password
= TAKE_PTR(p
);
130 static int link_read_wol_password_from_file(LinkConfig
*config
) {
131 _cleanup_(erase_and_freep
) char *password
= NULL
;
136 if (!config
->wol_password_file
)
139 r
= read_full_file_full(
140 AT_FDCWD
, config
->wol_password_file
, UINT64_MAX
, SIZE_MAX
,
141 READ_FULL_FILE_SECURE
| READ_FULL_FILE_WARN_WORLD_READABLE
| READ_FULL_FILE_CONNECT_SOCKET
,
142 NULL
, &password
, NULL
);
146 return link_parse_wol_password(config
, password
);
149 static int link_read_wol_password_from_cred(LinkConfig
*config
) {
150 _cleanup_free_
char *base
= NULL
, *cred_name
= NULL
;
151 _cleanup_(erase_and_freep
) char *password
= NULL
;
155 assert(config
->filename
);
157 if (config
->wol
== UINT32_MAX
)
158 return 0; /* WakeOnLan= is not specified. */
159 if (!FLAGS_SET(config
->wol
, WAKE_MAGICSECURE
))
160 return 0; /* secureon is not specified in WakeOnLan=. */
161 if (config
->wol_password
)
162 return 0; /* WakeOnLanPassword= is specified. */
163 if (config
->wol_password_file
)
164 return 0; /* a file name is specified in WakeOnLanPassword=, but failed to read it. */
166 r
= path_extract_filename(config
->filename
, &base
);
170 cred_name
= strjoin(base
, ".wol.password");
174 r
= read_credential(cred_name
, (void**) &password
, NULL
);
176 r
= read_credential("wol.password", (void**) &password
, NULL
);
180 return link_parse_wol_password(config
, password
);
183 static int link_adjust_wol_options(LinkConfig
*config
) {
188 r
= link_read_wol_password_from_file(config
);
192 log_warning_errno(r
, "Failed to read WakeOnLan password from %s, ignoring: %m", config
->wol_password_file
);
194 r
= link_read_wol_password_from_cred(config
);
198 log_warning_errno(r
, "Failed to read WakeOnLan password from credential, ignoring: %m");
200 if (config
->wol
!= UINT32_MAX
&& config
->wol_password
)
201 /* Enable WAKE_MAGICSECURE flag when WakeOnLanPassword=. Note that when
202 * WakeOnLanPassword= is set without WakeOnLan=, then ethtool_set_wol() enables
203 * WAKE_MAGICSECURE flag and other flags are not changed. */
204 config
->wol
|= WAKE_MAGICSECURE
;
209 int link_load_one(LinkConfigContext
*ctx
, const char *filename
) {
210 _cleanup_(link_config_freep
) LinkConfig
*config
= NULL
;
211 _cleanup_free_
char *name
= NULL
;
212 const char *dropin_dirname
;
219 r
= null_or_empty_path(filename
);
225 log_debug("Skipping empty file: %s", filename
);
229 name
= strdup(filename
);
233 config
= new(LinkConfig
, 1);
237 *config
= (LinkConfig
) {
238 .filename
= TAKE_PTR(name
),
239 .mac_address_policy
= MAC_ADDRESS_POLICY_NONE
,
240 .wol
= UINT32_MAX
, /* UINT32_MAX means do not change WOL setting. */
241 .duplex
= _DUP_INVALID
,
242 .port
= _NET_DEV_PORT_INVALID
,
243 .autonegotiation
= -1,
244 .rx_flow_control
= -1,
245 .tx_flow_control
= -1,
246 .autoneg_flow_control
= -1,
247 .txqueuelen
= UINT32_MAX
,
248 .coalesce
.use_adaptive_rx_coalesce
= -1,
249 .coalesce
.use_adaptive_tx_coalesce
= -1,
252 for (i
= 0; i
< ELEMENTSOF(config
->features
); i
++)
253 config
->features
[i
] = -1;
255 dropin_dirname
= strjoina(basename(filename
), ".d");
256 r
= config_parse_many(
257 STRV_MAKE_CONST(filename
),
258 (const char* const*) CONF_PATHS_STRV("systemd/network"),
261 config_item_perf_lookup
, link_config_gperf_lookup
,
262 CONFIG_PARSE_WARN
, config
, NULL
);
266 if (net_match_is_empty(&config
->match
) && !config
->conditions
) {
267 log_warning("%s: No valid settings found in the [Match] section, ignoring file. "
268 "To match all interfaces, add OriginalName=* in the [Match] section.",
273 if (!condition_test_list(config
->conditions
, environ
, NULL
, NULL
, NULL
)) {
274 log_debug("%s: Conditions do not match the system environment, skipping.", filename
);
278 if (IN_SET(config
->mac_address_policy
, MAC_ADDRESS_POLICY_PERSISTENT
, MAC_ADDRESS_POLICY_RANDOM
) &&
279 config
->hw_addr
.length
> 0)
280 log_warning("%s: MACAddress= in [Link] section will be ignored when MACAddressPolicy= "
281 "is set to \"persistent\" or \"random\".",
284 r
= link_adjust_wol_options(config
);
288 log_debug("Parsed configuration file %s", filename
);
290 LIST_PREPEND(configs
, ctx
->configs
, TAKE_PTR(config
));
294 static bool enable_name_policy(void) {
297 return proc_cmdline_get_bool("net.ifnames", &b
) <= 0 || b
;
300 static int device_unsigned_attribute(sd_device
*device
, const char *attr
, unsigned *type
) {
304 r
= sd_device_get_sysattr_value(device
, attr
, &s
);
306 return log_device_debug_errno(device
, r
, "Failed to query %s: %m", attr
);
308 r
= safe_atou(s
, type
);
310 return log_device_warning_errno(device
, r
, "Failed to parse %s \"%s\": %m", attr
, s
);
312 log_device_debug(device
, "Device has %s=%u", attr
, *type
);
316 int link_config_load(LinkConfigContext
*ctx
) {
317 _cleanup_strv_free_
char **files
= NULL
;
321 link_configs_free(ctx
);
323 if (!enable_name_policy()) {
324 ctx
->enable_name_policy
= false;
325 log_info("Network interface NamePolicy= disabled on kernel command line, ignoring.");
328 /* update timestamp */
329 paths_check_timestamp(NETWORK_DIRS
, &ctx
->network_dirs_ts_usec
, true);
331 r
= conf_files_list_strv(&files
, ".link", NULL
, 0, NETWORK_DIRS
);
333 return log_error_errno(r
, "failed to enumerate link files: %m");
335 STRV_FOREACH_BACKWARDS(f
, files
) {
336 r
= link_load_one(ctx
, *f
);
338 log_error_errno(r
, "Failed to load %s, ignoring: %m", *f
);
344 bool link_config_should_reload(LinkConfigContext
*ctx
) {
345 return paths_check_timestamp(NETWORK_DIRS
, &ctx
->network_dirs_ts_usec
, false);
348 Link
*link_free(Link
*link
) {
352 sd_device_unref(link
->device
);
357 int link_new(LinkConfigContext
*ctx
, sd_netlink
**rtnl
, sd_device
*device
, Link
**ret
) {
358 _cleanup_(link_freep
) Link
*link
= NULL
;
371 .device
= sd_device_ref(device
),
374 r
= sd_device_get_sysname(device
, &link
->ifname
);
378 r
= sd_device_get_ifindex(device
, &link
->ifindex
);
382 r
= sd_device_get_action(device
, &link
->action
);
386 r
= device_unsigned_attribute(device
, "name_assign_type", &link
->name_assign_type
);
388 log_link_debug_errno(link
, r
, "Failed to get \"name_assign_type\" attribute, ignoring: %m");
390 r
= device_unsigned_attribute(device
, "addr_assign_type", &link
->addr_assign_type
);
392 log_link_debug_errno(link
, r
, "Failed to get \"addr_assign_type\" attribute, ignoring: %m");
394 r
= rtnl_get_link_info(rtnl
, link
->ifindex
, &link
->iftype
, &link
->flags
, &link
->hw_addr
, &link
->permanent_hw_addr
);
398 if (link
->hw_addr
.length
> 0 && link
->permanent_hw_addr
.length
== 0) {
399 r
= ethtool_get_permanent_hw_addr(&ctx
->ethtool_fd
, link
->ifname
, &link
->permanent_hw_addr
);
401 log_link_debug_errno(link
, r
, "Failed to get permanent hardware address, ignoring: %m");
404 r
= ethtool_get_driver(&ctx
->ethtool_fd
, link
->ifname
, &link
->driver
);
406 log_link_debug_errno(link
, r
, "Failed to get driver, ignoring: %m");
408 *ret
= TAKE_PTR(link
);
412 int link_get_config(LinkConfigContext
*ctx
, Link
*link
) {
419 /* Do not configure loopback interfaces by .link files. */
420 if (link
->flags
& IFF_LOOPBACK
)
423 LIST_FOREACH(configs
, config
, ctx
->configs
) {
424 r
= net_match_config(
428 &link
->permanent_hw_addr
,
432 /* alternative_names = */ NULL
,
433 /* wlan_iftype = */ 0,
441 if (config
->match
.ifname
&& !strv_contains(config
->match
.ifname
, "*") && link
->name_assign_type
== NET_NAME_ENUM
)
442 log_link_warning(link
, "Config file %s is applied to device based on potentially unpredictable interface name.",
445 log_link_debug(link
, "Config file %s is applied", config
->filename
);
447 link
->config
= config
;
454 static int link_apply_ethtool_settings(Link
*link
, int *ethtool_fd
) {
460 assert(link
->config
);
463 config
= link
->config
;
466 r
= ethtool_set_glinksettings(ethtool_fd
, name
,
467 config
->autonegotiation
, config
->advertise
,
468 config
->speed
, config
->duplex
, config
->port
);
470 if (config
->autonegotiation
>= 0)
471 log_link_warning_errno(link
, r
, "Could not %s auto negotiation, ignoring: %m",
472 enable_disable(config
->autonegotiation
));
474 if (!eqzero(config
->advertise
))
475 log_link_warning_errno(link
, r
, "Could not set advertise mode, ignoring: %m");
477 if (config
->speed
> 0)
478 log_link_warning_errno(link
, r
, "Could not set speed to %"PRIu64
"Mbps, ignoring: %m",
479 DIV_ROUND_UP(config
->speed
, 1000000));
481 if (config
->duplex
>= 0)
482 log_link_warning_errno(link
, r
, "Could not set duplex to %s, ignoring: %m",
483 duplex_to_string(config
->duplex
));
485 if (config
->port
>= 0)
486 log_link_warning_errno(link
, r
, "Could not set port to '%s', ignoring: %m",
487 port_to_string(config
->port
));
490 r
= ethtool_set_wol(ethtool_fd
, name
, config
->wol
, config
->wol_password
);
492 _cleanup_free_
char *str
= NULL
;
494 (void) wol_options_to_string_alloc(config
->wol
, &str
);
495 log_link_warning_errno(link
, r
, "Could not set WakeOnLan%s%s, ignoring: %m",
496 isempty(str
) ? "" : " to ", strempty(str
));
499 r
= ethtool_set_features(ethtool_fd
, name
, config
->features
);
501 log_link_warning_errno(link
, r
, "Could not set offload features, ignoring: %m");
503 r
= ethtool_set_channels(ethtool_fd
, name
, &config
->channels
);
505 log_link_warning_errno(link
, r
, "Could not set channels, ignoring: %m");
507 r
= ethtool_set_nic_buffer_size(ethtool_fd
, name
, &config
->ring
);
509 log_link_warning_errno(link
, r
, "Could not set ring buffer, ignoring: %m");
511 r
= ethtool_set_flow_control(ethtool_fd
, name
, config
->rx_flow_control
, config
->tx_flow_control
, config
->autoneg_flow_control
);
513 log_link_warning_errno(link
, r
, "Could not set flow control, ignoring: %m");
515 r
= ethtool_set_nic_coalesce_settings(ethtool_fd
, name
, &config
->coalesce
);
517 log_link_warning_errno(link
, r
, "Could not set coalesce settings, ignoring: %m");
522 static bool hw_addr_is_valid(Link
*link
, const struct hw_addr_data
*hw_addr
) {
526 switch (link
->iftype
) {
528 /* Refuse all zero and all 0xFF. */
529 assert(hw_addr
->length
== ETH_ALEN
);
530 return !ether_addr_is_null(&hw_addr
->ether
) && !ether_addr_is_broadcast(&hw_addr
->ether
);
532 case ARPHRD_INFINIBAND
:
533 /* The last 8 bytes cannot be zero*/
534 assert(hw_addr
->length
== INFINIBAND_ALEN
);
535 return !memeqzero(hw_addr
->bytes
+ INFINIBAND_ALEN
- 8, 8);
538 assert_not_reached();
542 static int link_generate_new_hw_addr(Link
*link
, struct hw_addr_data
*ret
) {
543 struct hw_addr_data hw_addr
= HW_ADDR_NULL
;
544 bool is_static
= false;
550 assert(link
->config
);
551 assert(link
->device
);
554 if (link
->hw_addr
.length
== 0)
557 if (link
->config
->mac_address_policy
== MAC_ADDRESS_POLICY_NONE
) {
558 log_link_debug(link
, "Using static MAC address.");
559 hw_addr
= link
->config
->hw_addr
;
564 if (!IN_SET(link
->iftype
, ARPHRD_ETHER
, ARPHRD_INFINIBAND
))
567 switch (link
->addr_assign_type
) {
569 log_link_debug(link
, "MAC address on the device already set by userspace.");
571 case NET_ADDR_STOLEN
:
572 log_link_debug(link
, "MAC address on the device already set based on another device.");
574 case NET_ADDR_RANDOM
:
578 log_link_warning(link
, "Unknown addr_assign_type %u, ignoring", link
->addr_assign_type
);
582 if ((link
->config
->mac_address_policy
== MAC_ADDRESS_POLICY_RANDOM
) == (link
->addr_assign_type
== NET_ADDR_RANDOM
)) {
583 log_link_debug(link
, "MAC address on the device already matches policy \"%s\".",
584 mac_address_policy_to_string(link
->config
->mac_address_policy
));
588 hw_addr
= (struct hw_addr_data
) {
589 .length
= arphrd_to_hw_addr_len(link
->iftype
),
592 switch (link
->iftype
) {
595 len
= hw_addr
.length
;
597 case ARPHRD_INFINIBAND
:
598 p
= hw_addr
.bytes
+ INFINIBAND_ALEN
- 8;
602 assert_not_reached();
605 if (link
->config
->mac_address_policy
== MAC_ADDRESS_POLICY_RANDOM
)
606 /* We require genuine randomness here, since we want to make sure we won't collide with other
607 * systems booting up at the very same time. We do allow RDRAND however, since this is not
608 * cryptographic key material. */
610 r
= genuine_random_bytes(p
, len
, RANDOM_ALLOW_RDRAND
);
612 return log_link_warning_errno(link
, r
, "Failed to acquire random data to generate MAC address: %m");
614 if (hw_addr_is_valid(link
, &hw_addr
))
621 r
= net_get_unique_predictable_data(link
->device
,
622 naming_scheme_has(NAMING_STABLE_VIRTUAL_MACS
),
625 return log_link_warning_errno(link
, r
, "Could not generate persistent MAC address: %m");
627 assert(len
<= sizeof(result
));
628 memcpy(p
, &result
, len
);
629 if (!hw_addr_is_valid(link
, &hw_addr
))
630 return log_link_warning_errno(link
, SYNTHETIC_ERRNO(EINVAL
),
631 "Could not generate valid persistent MAC address: %m");
636 r
= net_verify_hardware_address(link
->ifname
, is_static
, link
->iftype
, &link
->hw_addr
, &hw_addr
);
640 if (hw_addr_equal(&link
->hw_addr
, &hw_addr
)) {
645 if (hw_addr
.length
> 0)
646 log_link_debug(link
, "Applying %s MAC address: %s",
647 link
->config
->mac_address_policy
== MAC_ADDRESS_POLICY_NONE
? "static" :
648 mac_address_policy_to_string(link
->config
->mac_address_policy
),
649 HW_ADDR_TO_STR(&hw_addr
));
655 static int link_apply_rtnl_settings(Link
*link
, sd_netlink
**rtnl
) {
656 struct hw_addr_data hw_addr
= {};
661 assert(link
->config
);
664 config
= link
->config
;
666 (void) link_generate_new_hw_addr(link
, &hw_addr
);
668 r
= rtnl_set_link_properties(rtnl
, link
->ifindex
, config
->alias
, &hw_addr
,
669 config
->txqueues
, config
->rxqueues
, config
->txqueuelen
,
670 config
->mtu
, config
->gso_max_size
, config
->gso_max_segments
);
672 log_link_warning_errno(link
, r
,
673 "Could not set Alias=, MACAddress=/MACAddressPolicy=, "
674 "TransmitQueues=, ReceiveQueues=, TransmitQueueLength=, MTUBytes=, "
675 "GenericSegmentOffloadMaxBytes= or GenericSegmentOffloadMaxSegments=, "
681 static int link_generate_new_name(Link
*link
, bool enable_name_policy
) {
686 assert(link
->config
);
687 assert(link
->device
);
689 config
= link
->config
;
690 device
= link
->device
;
692 if (link
->action
== SD_DEVICE_MOVE
) {
693 log_link_debug(link
, "Skipping to apply Name= and NamePolicy= on '%s' uevent.",
694 device_action_to_string(link
->action
));
698 if (IN_SET(link
->name_assign_type
, NET_NAME_USER
, NET_NAME_RENAMED
) &&
699 !naming_scheme_has(NAMING_ALLOW_RERENAMES
)) {
700 log_link_debug(link
, "Device already has a name given by userspace, not renaming.");
704 if (enable_name_policy
&& config
->name_policy
)
705 for (NamePolicy
*policy
= config
->name_policy
; *policy
!= _NAMEPOLICY_INVALID
; policy
++) {
706 const char *new_name
= NULL
;
709 case NAMEPOLICY_KERNEL
:
710 if (link
->name_assign_type
!= NET_NAME_PREDICTABLE
)
713 /* The kernel claims to have given a predictable name, keep it. */
714 log_link_debug(link
, "Policy *%s*: keeping predictable kernel name",
715 name_policy_to_string(*policy
));
717 case NAMEPOLICY_KEEP
:
718 if (!IN_SET(link
->name_assign_type
, NET_NAME_USER
, NET_NAME_RENAMED
))
721 log_link_debug(link
, "Policy *%s*: keeping existing userspace name",
722 name_policy_to_string(*policy
));
724 case NAMEPOLICY_DATABASE
:
725 (void) sd_device_get_property_value(device
, "ID_NET_NAME_FROM_DATABASE", &new_name
);
727 case NAMEPOLICY_ONBOARD
:
728 (void) sd_device_get_property_value(device
, "ID_NET_NAME_ONBOARD", &new_name
);
730 case NAMEPOLICY_SLOT
:
731 (void) sd_device_get_property_value(device
, "ID_NET_NAME_SLOT", &new_name
);
733 case NAMEPOLICY_PATH
:
734 (void) sd_device_get_property_value(device
, "ID_NET_NAME_PATH", &new_name
);
737 (void) sd_device_get_property_value(device
, "ID_NET_NAME_MAC", &new_name
);
740 assert_not_reached();
742 if (ifname_valid(new_name
)) {
743 log_link_debug(link
, "Policy *%s* yields \"%s\".", name_policy_to_string(*policy
), new_name
);
744 link
->new_name
= new_name
;
749 if (link
->config
->name
) {
750 log_link_debug(link
, "Policies didn't yield a name, using specified Name=%s.", link
->config
->name
);
751 link
->new_name
= link
->config
->name
;
755 log_link_debug(link
, "Policies didn't yield a name and Name= is not given, not renaming.");
757 link
->new_name
= link
->ifname
;
761 static int link_apply_alternative_names(Link
*link
, sd_netlink
**rtnl
) {
762 _cleanup_strv_free_
char **altnames
= NULL
, **current_altnames
= NULL
;
768 assert(link
->config
);
769 assert(link
->device
);
772 config
= link
->config
;
773 device
= link
->device
;
775 if (config
->alternative_names
) {
776 altnames
= strv_copy(config
->alternative_names
);
781 if (config
->alternative_names_policy
)
782 for (NamePolicy
*p
= config
->alternative_names_policy
; *p
!= _NAMEPOLICY_INVALID
; p
++) {
783 const char *n
= NULL
;
786 case NAMEPOLICY_DATABASE
:
787 (void) sd_device_get_property_value(device
, "ID_NET_NAME_FROM_DATABASE", &n
);
789 case NAMEPOLICY_ONBOARD
:
790 (void) sd_device_get_property_value(device
, "ID_NET_NAME_ONBOARD", &n
);
792 case NAMEPOLICY_SLOT
:
793 (void) sd_device_get_property_value(device
, "ID_NET_NAME_SLOT", &n
);
795 case NAMEPOLICY_PATH
:
796 (void) sd_device_get_property_value(device
, "ID_NET_NAME_PATH", &n
);
799 (void) sd_device_get_property_value(device
, "ID_NET_NAME_MAC", &n
);
802 assert_not_reached();
805 r
= strv_extend(&altnames
, n
);
812 strv_remove(altnames
, link
->new_name
);
813 strv_remove(altnames
, link
->ifname
);
815 r
= rtnl_get_link_alternative_names(rtnl
, link
->ifindex
, ¤t_altnames
);
817 log_link_debug_errno(link
, r
, "Failed to get alternative names, ignoring: %m");
820 STRV_FOREACH(p
, current_altnames
)
821 strv_remove(altnames
, *p
);
825 r
= rtnl_set_link_alternative_names(rtnl
, link
->ifindex
, altnames
);
827 log_link_full_errno(link
, r
== -EOPNOTSUPP
? LOG_DEBUG
: LOG_WARNING
, r
,
828 "Could not set AlternativeName= or apply AlternativeNamesPolicy=, ignoring: %m");
833 int link_apply_config(LinkConfigContext
*ctx
, sd_netlink
**rtnl
, Link
*link
) {
840 if (!IN_SET(link
->action
, SD_DEVICE_ADD
, SD_DEVICE_BIND
, SD_DEVICE_MOVE
)) {
841 log_link_debug(link
, "Skipping to apply .link settings on '%s' uevent.",
842 device_action_to_string(link
->action
));
844 link
->new_name
= link
->ifname
;
848 r
= link_apply_ethtool_settings(link
, &ctx
->ethtool_fd
);
852 r
= link_apply_rtnl_settings(link
, rtnl
);
856 r
= link_generate_new_name(link
, ctx
->enable_name_policy
);
860 r
= link_apply_alternative_names(link
, rtnl
);
867 int config_parse_ifalias(
869 const char *filename
,
872 unsigned section_line
,
886 if (!isempty(rvalue
)) {
891 if (!ascii_is_valid(rvalue
)) {
892 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
893 "Interface alias is not ASCII clean, ignoring assignment: %s", rvalue
);
897 if (strlen(rvalue
) >= IFALIASZ
) {
898 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
899 "Interface alias is too long, ignoring assignment: %s", rvalue
);
903 return free_and_strdup_warn(s
, rvalue
);
906 int config_parse_rx_tx_queues(
908 const char *filename
,
911 unsigned section_line
,
918 uint32_t k
, *v
= data
;
921 if (isempty(rvalue
)) {
926 r
= safe_atou32(rvalue
, &k
);
928 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse %s=, ignoring assignment: %s.", lvalue
, rvalue
);
931 if (k
== 0 || k
> 4096) {
932 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0, "Invalid %s=, ignoring assignment: %s.", lvalue
, rvalue
);
940 int config_parse_txqueuelen(
942 const char *filename
,
945 unsigned section_line
,
952 uint32_t k
, *v
= data
;
955 if (isempty(rvalue
)) {
960 r
= safe_atou32(rvalue
, &k
);
962 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "Failed to parse %s=, ignoring assignment: %s.", lvalue
, rvalue
);
965 if (k
== UINT32_MAX
) {
966 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0, "Invalid %s=, ignoring assignment: %s.", lvalue
, rvalue
);
974 int config_parse_wol_password(
976 const char *filename
,
979 unsigned section_line
,
986 LinkConfig
*config
= userdata
;
994 if (isempty(rvalue
)) {
995 config
->wol_password
= erase_and_free(config
->wol_password
);
996 config
->wol_password_file
= mfree(config
->wol_password_file
);
1000 if (path_is_absolute(rvalue
) && path_is_safe(rvalue
)) {
1001 config
->wol_password
= erase_and_free(config
->wol_password
);
1002 return free_and_strdup_warn(&config
->wol_password_file
, rvalue
);
1005 warn_file_is_world_accessible(filename
, NULL
, unit
, line
);
1007 r
= link_parse_wol_password(config
, rvalue
);
1011 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1012 "Failed to parse %s=, ignoring assignment: %s.", lvalue
, rvalue
);
1016 config
->wol_password_file
= mfree(config
->wol_password_file
);
1020 static const char* const mac_address_policy_table
[_MAC_ADDRESS_POLICY_MAX
] = {
1021 [MAC_ADDRESS_POLICY_PERSISTENT
] = "persistent",
1022 [MAC_ADDRESS_POLICY_RANDOM
] = "random",
1023 [MAC_ADDRESS_POLICY_NONE
] = "none",
1026 DEFINE_STRING_TABLE_LOOKUP(mac_address_policy
, MACAddressPolicy
);
1027 DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(
1028 config_parse_mac_address_policy
,
1031 MAC_ADDRESS_POLICY_NONE
,
1032 "Failed to parse MAC address policy");
1034 DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy
, name_policy
, NamePolicy
,
1035 _NAMEPOLICY_INVALID
,
1036 "Failed to parse interface name policy");
1038 DEFINE_CONFIG_PARSE_ENUMV(config_parse_alternative_names_policy
, alternative_names_policy
, NamePolicy
,
1039 _NAMEPOLICY_INVALID
,
1040 "Failed to parse alternative names policy");