From: Yu Watanabe Date: Fri, 5 Nov 2021 01:13:56 +0000 (+0900) Subject: udev/net: introduce "struct Link" to store link attributes X-Git-Tag: v250-rc1~124^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=613701a4e88b3fbf9d0f7901fea62ed0016d8862;p=thirdparty%2Fsystemd.git udev/net: introduce "struct Link" to store link attributes --- diff --git a/src/shared/net-condition.c b/src/shared/net-condition.c index fbd7bd0784b..006676d973e 100644 --- a/src/shared/net-condition.c +++ b/src/shared/net-condition.c @@ -134,21 +134,14 @@ int net_match_config( _cleanup_free_ char *iftype_str = NULL; const char *path = NULL; - int r; assert(match); - r = net_get_type_string(device, iftype, &iftype_str); - if (r == -ENOMEM) - return r; + if (net_get_type_string(device, iftype, &iftype_str) == -ENOMEM) + return -ENOMEM; - if (device) { + if (device) (void) sd_device_get_property_value(device, "ID_PATH", &path); - if (!driver) - (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &driver); - if (!ifname) - (void) sd_device_get_sysname(device, &ifname); - } if (match->hw_addr && (!hw_addr || !set_contains(match->hw_addr, hw_addr))) return false; diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index ab9ffdc2162..940b5cdfeac 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -18,7 +18,7 @@ #include "fd-util.h" #include "fileio.h" #include "link-config.h" -#include "log.h" +#include "log-link.h" #include "memory-util.h" #include "net-condition.h" #include "netif-naming-scheme.h" @@ -347,99 +347,146 @@ bool link_config_should_reload(LinkConfigContext *ctx) { return paths_check_timestamp(NETWORK_DIRS, &ctx->network_dirs_ts_usec, false); } -int link_config_get(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, LinkConfig **ret) { - unsigned name_assign_type = NET_NAME_UNKNOWN; - struct hw_addr_data hw_addr, permanent_hw_addr; - unsigned short iftype; - LinkConfig *config; - const char *name; - unsigned flags; - int ifindex, r; +Link *link_free(Link *link) { + if (!link) + return NULL; + + sd_device_unref(link->device); + free(link->driver); + return mfree(link); +} + +int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, Link **ret) { + _cleanup_(link_freep) Link *link = NULL; + int r; assert(ctx); assert(rtnl); assert(device); assert(ret); - r = sd_device_get_sysname(device, &name); + link = new(Link, 1); + if (!link) + return -ENOMEM; + + *link = (Link) { + .device = sd_device_ref(device), + }; + + r = sd_device_get_sysname(device, &link->ifname); if (r < 0) return r; - r = sd_device_get_ifindex(device, &ifindex); + r = sd_device_get_ifindex(device, &link->ifindex); if (r < 0) return r; - r = rtnl_get_link_info(rtnl, ifindex, &iftype, &flags, &hw_addr, &permanent_hw_addr); + r = sd_device_get_action(device, &link->action); if (r < 0) return r; - /* Do not configure loopback interfaces by .link files. */ - if (flags & IFF_LOOPBACK) - return -ENOENT; + r = device_unsigned_attribute(device, "name_assign_type", &link->name_assign_type); + if (r < 0) + log_link_debug_errno(link, r, "Failed to get \"name_assign_type\" attribute, ignoring: %m"); + + r = device_unsigned_attribute(device, "addr_assign_type", &link->addr_assign_type); + if (r < 0) + log_link_debug_errno(link, r, "Failed to get \"addr_assign_type\" attribute, ignoring: %m"); - if (hw_addr.length > 0 && permanent_hw_addr.length == 0) { - r = ethtool_get_permanent_hw_addr(&ctx->ethtool_fd, name, &permanent_hw_addr); + r = rtnl_get_link_info(rtnl, link->ifindex, &link->iftype, &link->flags, &link->hw_addr, &link->permanent_hw_addr); + if (r < 0) + return r; + + if (link->hw_addr.length > 0 && link->permanent_hw_addr.length == 0) { + r = ethtool_get_permanent_hw_addr(&ctx->ethtool_fd, link->ifname, &link->permanent_hw_addr); if (r < 0) - log_device_debug_errno(device, r, "Failed to get permanent hardware address, ignoring: %m"); + log_link_debug_errno(link, r, "Failed to get permanent hardware address, ignoring: %m"); } - (void) device_unsigned_attribute(device, "name_assign_type", &name_assign_type); + r = ethtool_get_driver(&ctx->ethtool_fd, link->ifname, &link->driver); + if (r < 0) + log_link_debug_errno(link, r, "Failed to get driver, ignoring: %m"); + + *ret = TAKE_PTR(link); + return 0; +} + +int link_get_config(LinkConfigContext *ctx, Link *link) { + LinkConfig *config; + int r; + + assert(ctx); + assert(link); + + /* Do not configure loopback interfaces by .link files. */ + if (link->flags & IFF_LOOPBACK) + return -ENOENT; LIST_FOREACH(configs, config, ctx->configs) { - r = net_match_config(&config->match, device, &hw_addr, &permanent_hw_addr, - NULL, iftype, NULL, NULL, 0, NULL, NULL); + r = net_match_config( + &config->match, + link->device, + &link->hw_addr, + &link->permanent_hw_addr, + link->driver, + link->iftype, + link->ifname, + /* alternative_names = */ NULL, + /* wlan_iftype = */ 0, + /* ssid = */ NULL, + /* bssid = */ NULL); if (r < 0) return r; if (r == 0) continue; - if (config->match.ifname && !strv_contains(config->match.ifname, "*") && name_assign_type == NET_NAME_ENUM) - log_device_warning(device, "Config file %s is applied to device based on potentially unpredictable interface name.", - config->filename); + if (config->match.ifname && !strv_contains(config->match.ifname, "*") && link->name_assign_type == NET_NAME_ENUM) + log_link_warning(link, "Config file %s is applied to device based on potentially unpredictable interface name.", + config->filename); else - log_device_debug(device, "Config file %s is applied", config->filename); + log_link_debug(link, "Config file %s is applied", config->filename); - *ret = config; + link->config = config; return 0; } return -ENOENT; } -static int link_config_apply_ethtool_settings(int *ethtool_fd, const LinkConfig *config, sd_device *device) { +static int link_apply_ethtool_settings(Link *link, int *ethtool_fd) { + LinkConfig *config; const char *name; int r; + assert(link); + assert(link->config); assert(ethtool_fd); - assert(config); - assert(device); - r = sd_device_get_sysname(device, &name); - if (r < 0) - return log_device_error_errno(device, r, "Failed to get sysname: %m"); + config = link->config; + name = link->ifname; r = ethtool_set_glinksettings(ethtool_fd, name, config->autonegotiation, config->advertise, config->speed, config->duplex, config->port); if (r < 0) { if (config->autonegotiation >= 0) - log_device_warning_errno(device, r, "Could not %s auto negotiation, ignoring: %m", - enable_disable(config->autonegotiation)); + log_link_warning_errno(link, r, "Could not %s auto negotiation, ignoring: %m", + enable_disable(config->autonegotiation)); if (!eqzero(config->advertise)) - log_device_warning_errno(device, r, "Could not set advertise mode, ignoring: %m"); + log_link_warning_errno(link, r, "Could not set advertise mode, ignoring: %m"); if (config->speed > 0) - log_device_warning_errno(device, r, "Could not set speed to %"PRIu64"Mbps, ignoring: %m", - DIV_ROUND_UP(config->speed, 1000000)); + log_link_warning_errno(link, r, "Could not set speed to %"PRIu64"Mbps, ignoring: %m", + DIV_ROUND_UP(config->speed, 1000000)); if (config->duplex >= 0) - log_device_warning_errno(device, r, "Could not set duplex to %s, ignoring: %m", - duplex_to_string(config->duplex)); + log_link_warning_errno(link, r, "Could not set duplex to %s, ignoring: %m", + duplex_to_string(config->duplex)); if (config->port >= 0) - log_device_warning_errno(device, r, "Could not set port to '%s', ignoring: %m", - port_to_string(config->port)); + log_link_warning_errno(link, r, "Could not set port to '%s', ignoring: %m", + port_to_string(config->port)); } r = ethtool_set_wol(ethtool_fd, name, config->wol, config->wol_password); @@ -447,83 +494,82 @@ static int link_config_apply_ethtool_settings(int *ethtool_fd, const LinkConfig _cleanup_free_ char *str = NULL; (void) wol_options_to_string_alloc(config->wol, &str); - log_device_warning_errno(device, r, "Could not set WakeOnLan%s%s, ignoring: %m", - isempty(str) ? "" : " to ", strempty(str)); + log_link_warning_errno(link, r, "Could not set WakeOnLan%s%s, ignoring: %m", + isempty(str) ? "" : " to ", strempty(str)); } r = ethtool_set_features(ethtool_fd, name, config->features); if (r < 0) - log_device_warning_errno(device, r, "Could not set offload features, ignoring: %m"); + log_link_warning_errno(link, r, "Could not set offload features, ignoring: %m"); r = ethtool_set_channels(ethtool_fd, name, &config->channels); if (r < 0) - log_device_warning_errno(device, r, "Could not set channels, ignoring: %m"); + log_link_warning_errno(link, r, "Could not set channels, ignoring: %m"); r = ethtool_set_nic_buffer_size(ethtool_fd, name, &config->ring); if (r < 0) - log_device_warning_errno(device, r, "Could not set ring buffer, ignoring: %m"); + log_link_warning_errno(link, r, "Could not set ring buffer, ignoring: %m"); r = ethtool_set_flow_control(ethtool_fd, name, config->rx_flow_control, config->tx_flow_control, config->autoneg_flow_control); if (r < 0) - log_device_warning_errno(device, r, "Could not set flow control, ignoring: %m"); + log_link_warning_errno(link, r, "Could not set flow control, ignoring: %m"); r = ethtool_set_nic_coalesce_settings(ethtool_fd, name, &config->coalesce); if (r < 0) - log_device_warning_errno(device, r, "Could not set coalesce settings, ignoring: %m"); + log_link_warning_errno(link, r, "Could not set coalesce settings, ignoring: %m"); return 0; } -static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr *mac) { - unsigned addr_type; - bool want_random = policy == MAC_ADDRESS_POLICY_RANDOM; +static int link_generate_new_mac(Link *link, struct ether_addr *mac) { int r; - assert(IN_SET(policy, MAC_ADDRESS_POLICY_RANDOM, MAC_ADDRESS_POLICY_PERSISTENT)); + assert(link); + assert(link->config); + assert(IN_SET(link->config->mac_address_policy, MAC_ADDRESS_POLICY_RANDOM, MAC_ADDRESS_POLICY_PERSISTENT)); + assert(link->device); + assert(mac); - r = device_unsigned_attribute(device, "addr_assign_type", &addr_type); - if (r < 0) - return r; - switch (addr_type) { + switch (link->addr_assign_type) { case NET_ADDR_SET: - log_device_debug(device, "MAC on the device already set by userspace"); + log_link_debug(link, "MAC on the device already set by userspace"); return 0; case NET_ADDR_STOLEN: - log_device_debug(device, "MAC on the device already set based on another device"); + log_link_debug(link, "MAC on the device already set based on another device"); return 0; case NET_ADDR_RANDOM: case NET_ADDR_PERM: break; default: - log_device_warning(device, "Unknown addr_assign_type %u, ignoring", addr_type); + log_link_warning(link, "Unknown addr_assign_type %u, ignoring", link->addr_assign_type); return 0; } - if (want_random == (addr_type == NET_ADDR_RANDOM)) { - log_device_debug(device, "MAC on the device already matches policy *%s*", - mac_address_policy_to_string(policy)); + if ((link->config->mac_address_policy == MAC_ADDRESS_POLICY_RANDOM) == (link->addr_assign_type == NET_ADDR_RANDOM)) { + log_link_debug(link, "MAC on the device already matches policy *%s*", + mac_address_policy_to_string(link->config->mac_address_policy)); return 0; } - if (want_random) { - log_device_debug(device, "Using random bytes to generate MAC"); + if (link->config->mac_address_policy == MAC_ADDRESS_POLICY_RANDOM) { + log_link_debug(link, "Using random bytes to generate MAC"); /* We require genuine randomness here, since we want to make sure we won't collide with other * systems booting up at the very same time. We do allow RDRAND however, since this is not * cryptographic key material. */ r = genuine_random_bytes(mac->ether_addr_octet, ETH_ALEN, RANDOM_ALLOW_RDRAND); if (r < 0) - return log_device_error_errno(device, r, "Failed to acquire random data to generate MAC: %m"); + return log_link_warning_errno(link, r, "Failed to acquire random data to generate MAC: %m"); } else { uint64_t result; - r = net_get_unique_predictable_data(device, + r = net_get_unique_predictable_data(link->device, naming_scheme_has(NAMING_STABLE_VIRTUAL_MACS), &result); if (r < 0) - return log_device_warning_errno(device, r, "Could not generate persistent MAC: %m"); + return log_link_warning_errno(link, r, "Could not generate persistent MAC: %m"); - log_device_debug(device, "Using generated persistent MAC address"); + log_link_debug(link, "Using generated persistent MAC address"); assert_cc(ETH_ALEN <= sizeof(result)); memcpy(mac->ether_addr_octet, &result, ETH_ALEN); } @@ -534,74 +580,78 @@ static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr return 1; } -static int link_config_apply_rtnl_settings(sd_netlink **rtnl, const LinkConfig *config, sd_device *device) { +static int link_apply_rtnl_settings(Link *link, sd_netlink **rtnl) { struct ether_addr generated_mac, *mac = NULL; - int ifindex, r; + LinkConfig *config; + int r; + assert(link); + assert(link->config); assert(rtnl); - assert(config); - assert(device); - r = sd_device_get_ifindex(device, &ifindex); - if (r < 0) - return log_device_error_errno(device, r, "Could not find ifindex: %m"); + config = link->config; if (IN_SET(config->mac_address_policy, MAC_ADDRESS_POLICY_PERSISTENT, MAC_ADDRESS_POLICY_RANDOM)) { - if (get_mac(device, config->mac_address_policy, &generated_mac) > 0) + if (link_generate_new_mac(link, &generated_mac) > 0) mac = &generated_mac; } else mac = config->mac; - r = rtnl_set_link_properties(rtnl, ifindex, config->alias, mac, + r = rtnl_set_link_properties(rtnl, link->ifindex, config->alias, mac, config->txqueues, config->rxqueues, config->txqueuelen, config->mtu, config->gso_max_size, config->gso_max_segments); if (r < 0) - log_device_warning_errno(device, r, - "Could not set Alias=, MACAddress=, " - "TransmitQueues=, ReceiveQueues=, TransmitQueueLength=, MTU=, " - "GenericSegmentOffloadMaxBytes= or GenericSegmentOffloadMaxSegments=, " - "ignoring: %m"); + log_link_warning_errno(link, r, + "Could not set Alias=, MACAddress=/MACAddressPolicy=, " + "TransmitQueues=, ReceiveQueues=, TransmitQueueLength=, MTUBytes=, " + "GenericSegmentOffloadMaxBytes= or GenericSegmentOffloadMaxSegments=, " + "ignoring: %m"); return 0; } -static int link_config_generate_new_name(const LinkConfigContext *ctx, const LinkConfig *config, sd_device *device, const char **ret_name) { - unsigned name_type = NET_NAME_UNKNOWN; - int r; +static int link_generate_new_name(Link *link, bool enable_name_policy) { + LinkConfig *config; + sd_device *device; - assert(ctx); - assert(config); - assert(device); - assert(ret_name); + assert(link); + assert(link->config); + assert(link->device); - (void) device_unsigned_attribute(device, "name_assign_type", &name_type); + config = link->config; + device = link->device; - if (IN_SET(name_type, NET_NAME_USER, NET_NAME_RENAMED) - && !naming_scheme_has(NAMING_ALLOW_RERENAMES)) { - log_device_debug(device, "Device already has a name given by userspace, not renaming."); + if (link->action == SD_DEVICE_MOVE) { + log_link_debug(link, "Skipping to apply Name= and NamePolicy= on '%s' uevent.", + device_action_to_string(link->action)); goto no_rename; } - if (ctx->enable_name_policy && config->name_policy) - for (NamePolicy *p = config->name_policy; *p != _NAMEPOLICY_INVALID; p++) { + if (IN_SET(link->name_assign_type, NET_NAME_USER, NET_NAME_RENAMED) && + !naming_scheme_has(NAMING_ALLOW_RERENAMES)) { + log_link_debug(link, "Device already has a name given by userspace, not renaming."); + goto no_rename; + } + + if (enable_name_policy && config->name_policy) + for (NamePolicy *policy = config->name_policy; *policy != _NAMEPOLICY_INVALID; policy++) { const char *new_name = NULL; - NamePolicy policy = *p; - switch (policy) { + switch (*policy) { case NAMEPOLICY_KERNEL: - if (name_type != NET_NAME_PREDICTABLE) + if (link->name_assign_type != NET_NAME_PREDICTABLE) continue; /* The kernel claims to have given a predictable name, keep it. */ - log_device_debug(device, "Policy *%s*: keeping predictable kernel name", - name_policy_to_string(policy)); + log_link_debug(link, "Policy *%s*: keeping predictable kernel name", + name_policy_to_string(*policy)); goto no_rename; case NAMEPOLICY_KEEP: - if (!IN_SET(name_type, NET_NAME_USER, NET_NAME_RENAMED)) + if (!IN_SET(link->name_assign_type, NET_NAME_USER, NET_NAME_RENAMED)) continue; - log_device_debug(device, "Policy *%s*: keeping existing userspace name", - name_policy_to_string(policy)); + log_link_debug(link, "Policy *%s*: keeping existing userspace name", + name_policy_to_string(*policy)); goto no_rename; case NAMEPOLICY_DATABASE: (void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &new_name); @@ -622,43 +672,37 @@ static int link_config_generate_new_name(const LinkConfigContext *ctx, const Lin assert_not_reached(); } if (ifname_valid(new_name)) { - log_device_debug(device, "Policy *%s* yields \"%s\".", name_policy_to_string(policy), new_name); - *ret_name = new_name; + log_link_debug(link, "Policy *%s* yields \"%s\".", name_policy_to_string(*policy), new_name); + link->new_name = new_name; return 0; } } - if (config->name) { - log_device_debug(device, "Policies didn't yield a name, using specified Name=%s.", config->name); - *ret_name = config->name; + if (link->config->name) { + log_link_debug(link, "Policies didn't yield a name, using specified Name=%s.", link->config->name); + link->new_name = link->config->name; return 0; } - log_device_debug(device, "Policies didn't yield a name and Name= is not given, not renaming."); + log_link_debug(link, "Policies didn't yield a name and Name= is not given, not renaming."); no_rename: - r = sd_device_get_sysname(device, ret_name); - if (r < 0) - return log_device_error_errno(device, r, "Failed to get sysname: %m"); - + link->new_name = link->ifname; return 0; } -static int link_config_apply_alternative_names(sd_netlink **rtnl, const LinkConfig *config, sd_device *device, const char *new_name) { +static int link_apply_alternative_names(Link *link, sd_netlink **rtnl) { _cleanup_strv_free_ char **altnames = NULL, **current_altnames = NULL; - const char *current_name; - int ifindex, r; + LinkConfig *config; + sd_device *device; + int r; + assert(link); + assert(link->config); + assert(link->device); assert(rtnl); - assert(config); - assert(device); - r = sd_device_get_sysname(device, ¤t_name); - if (r < 0) - return log_device_error_errno(device, r, "Failed to get sysname: %m"); - - r = sd_device_get_ifindex(device, &ifindex); - if (r < 0) - return log_device_error_errno(device, r, "Could not find ifindex: %m"); + config = link->config; + device = link->device; if (config->alternative_names) { altnames = strv_copy(config->alternative_names); @@ -696,13 +740,13 @@ static int link_config_apply_alternative_names(sd_netlink **rtnl, const LinkConf } } - if (new_name) - strv_remove(altnames, new_name); - strv_remove(altnames, current_name); + if (link->new_name) + strv_remove(altnames, link->new_name); + strv_remove(altnames, link->ifname); - r = rtnl_get_link_alternative_names(rtnl, ifindex, ¤t_altnames); + r = rtnl_get_link_alternative_names(rtnl, link->ifindex, ¤t_altnames); if (r < 0) - log_device_debug_errno(device, r, "Failed to get alternative names, ignoring: %m"); + log_link_debug_errno(link, r, "Failed to get alternative names, ignoring: %m"); char **p; STRV_FOREACH(p, current_altnames) @@ -710,81 +754,45 @@ static int link_config_apply_alternative_names(sd_netlink **rtnl, const LinkConf strv_uniq(altnames); strv_sort(altnames); - r = rtnl_set_link_alternative_names(rtnl, ifindex, altnames); + r = rtnl_set_link_alternative_names(rtnl, link->ifindex, altnames); if (r < 0) - log_device_full_errno(device, r == -EOPNOTSUPP ? LOG_DEBUG : LOG_WARNING, r, - "Could not set AlternativeName= or apply AlternativeNamesPolicy=, ignoring: %m"); + log_link_full_errno(link, r == -EOPNOTSUPP ? LOG_DEBUG : LOG_WARNING, r, + "Could not set AlternativeName= or apply AlternativeNamesPolicy=, ignoring: %m"); return 0; } -int link_config_apply(LinkConfigContext *ctx, const LinkConfig *config, sd_netlink **rtnl, sd_device *device, const char **ret_name) { - const char *new_name; - sd_device_action_t a; +int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link) { int r; assert(ctx); - assert(config); assert(rtnl); - assert(device); - assert(ret_name); + assert(link); - r = sd_device_get_action(device, &a); - if (r < 0) - return log_device_error_errno(device, r, "Failed to get ACTION= property: %m"); - - if (!IN_SET(a, SD_DEVICE_ADD, SD_DEVICE_BIND, SD_DEVICE_MOVE)) { - log_device_debug(device, "Skipping to apply .link settings on '%s' uevent.", device_action_to_string(a)); - - r = sd_device_get_sysname(device, ret_name); - if (r < 0) - return log_device_error_errno(device, r, "Failed to get sysname: %m"); + if (!IN_SET(link->action, SD_DEVICE_ADD, SD_DEVICE_BIND, SD_DEVICE_MOVE)) { + log_link_debug(link, "Skipping to apply .link settings on '%s' uevent.", + device_action_to_string(link->action)); + link->new_name = link->ifname; return 0; } - r = link_config_apply_ethtool_settings(&ctx->ethtool_fd, config, device); - if (r < 0) - return r; - - r = link_config_apply_rtnl_settings(rtnl, config, device); + r = link_apply_ethtool_settings(link, &ctx->ethtool_fd); if (r < 0) return r; - if (a == SD_DEVICE_MOVE) { - log_device_debug(device, "Skipping to apply Name= and NamePolicy= on '%s' uevent.", device_action_to_string(a)); - - r = sd_device_get_sysname(device, &new_name); - if (r < 0) - return log_device_error_errno(device, r, "Failed to get sysname: %m"); - } else { - r = link_config_generate_new_name(ctx, config, device, &new_name); - if (r < 0) - return r; - } - - r = link_config_apply_alternative_names(rtnl, config, device, new_name); + r = link_apply_rtnl_settings(link, rtnl); if (r < 0) return r; - *ret_name = new_name; - return 0; -} - -int link_get_driver(LinkConfigContext *ctx, sd_device *device, char **ret) { - const char *name; - char *driver = NULL; - int r; - - r = sd_device_get_sysname(device, &name); + r = link_generate_new_name(link, ctx->enable_name_policy); if (r < 0) return r; - r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver); + r = link_apply_alternative_names(link, rtnl); if (r < 0) return r; - *ret = driver; return 0; } diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h index 47619d923ff..ad2a32790d3 100644 --- a/src/udev/net/link-config.h +++ b/src/udev/net/link-config.h @@ -33,6 +33,24 @@ typedef enum NamePolicy { _NAMEPOLICY_INVALID = -EINVAL, } NamePolicy; +typedef struct Link { + int ifindex; + const char *ifname; + const char *new_name; + + LinkConfig *config; + sd_device *device; + sd_device_action_t action; + + char *driver; + uint16_t iftype; + uint32_t flags; + struct hw_addr_data hw_addr; + struct hw_addr_data permanent_hw_addr; + unsigned name_assign_type; + unsigned addr_assign_type; +} Link; + struct LinkConfig { char *filename; @@ -80,9 +98,12 @@ int link_load_one(LinkConfigContext *ctx, const char *filename); int link_config_load(LinkConfigContext *ctx); bool link_config_should_reload(LinkConfigContext *ctx); -int link_config_get(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, LinkConfig **ret); -int link_config_apply(LinkConfigContext *ctx, const LinkConfig *config, sd_netlink **rtnl, sd_device *device, const char **ret_name); -int link_get_driver(LinkConfigContext *ctx, sd_device *device, char **ret); +int link_new(LinkConfigContext *ctx, sd_netlink **rtnl, sd_device *device, Link **ret); +Link *link_free(Link *link); +DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free); + +int link_get_config(LinkConfigContext *ctx, Link *link); +int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link); const char *name_policy_to_string(NamePolicy p) _const_; NamePolicy name_policy_from_string(const char *p) _pure_; diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c index 4c7a5b23fdb..d4095c7684c 100644 --- a/src/udev/udev-builtin-net_setup_link.c +++ b/src/udev/udev-builtin-net_setup_link.c @@ -11,25 +11,25 @@ static LinkConfigContext *ctx = NULL; static int builtin_net_setup_link(sd_device *dev, sd_netlink **rtnl, int argc, char **argv, bool test) { - _cleanup_free_ char *driver = NULL; - const char *name = NULL; - LinkConfig *link; + _cleanup_(link_freep) Link *link = NULL; int r; if (argc > 1) return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); - r = link_get_driver(ctx, dev, &driver); + r = link_new(ctx, rtnl, dev, &link); + if (r == -ENODEV) { + log_device_debug_errno(dev, r, "Link vanished while getting information, ignoring."); + return 0; + } if (r < 0) - log_device_full_errno(dev, ERRNO_IS_NOT_SUPPORTED(r) || r == -ENODEV ? LOG_DEBUG : LOG_WARNING, - r, "Failed to query device driver: %m"); - else - udev_builtin_add_property(dev, test, "ID_NET_DRIVER", driver); + return log_device_warning_errno(dev, r, "Failed to get link information: %m"); - r = link_config_get(ctx, rtnl, dev, &link); + if (link->driver) + udev_builtin_add_property(dev, test, "ID_NET_DRIVER", link->driver); + + r = link_get_config(ctx, link); if (r < 0) { - if (r == -ENODEV) - return log_device_debug_errno(dev, r, "Link vanished while searching for configuration for it."); if (r == -ENOENT) { log_device_debug_errno(dev, r, "No matching link configuration found, ignoring device."); return 0; @@ -38,16 +38,15 @@ static int builtin_net_setup_link(sd_device *dev, sd_netlink **rtnl, int argc, c return log_device_error_errno(dev, r, "Failed to get link config: %m"); } - r = link_config_apply(ctx, link, rtnl, dev, &name); + r = link_apply_config(ctx, rtnl, link); if (r == -ENODEV) log_device_debug_errno(dev, r, "Link vanished while applying configuration, ignoring."); else if (r < 0) log_device_warning_errno(dev, r, "Could not apply link configuration, ignoring: %m"); - udev_builtin_add_property(dev, test, "ID_NET_LINK_FILE", link->filename); - - if (name) - udev_builtin_add_property(dev, test, "ID_NET_NAME", name); + udev_builtin_add_property(dev, test, "ID_NET_LINK_FILE", link->config->filename); + if (link->new_name) + udev_builtin_add_property(dev, test, "ID_NET_NAME", link->new_name); return 0; }