diff options
Diffstat (limited to 'src/network/networkd-link.c')
-rw-r--r-- | src/network/networkd-link.c | 748 |
1 files changed, 458 insertions, 290 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 4afcf843bd..e2851df31a 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -8,25 +8,37 @@ #include "alloc-util.h" #include "bus-util.h" +#include "dhcp-identifier.h" #include "dhcp-lease-internal.h" +#include "env-file.h" #include "fd-util.h" #include "fileio.h" +#include "missing_network.h" #include "netlink-util.h" #include "network-internal.h" #include "networkd-ipv6-proxy-ndp.h" #include "networkd-lldp-tx.h" #include "networkd-manager.h" #include "networkd-ndisc.h" +#include "networkd-neighbor.h" #include "networkd-radv.h" #include "networkd-routing-policy-rule.h" #include "set.h" #include "socket-util.h" #include "stdio-util.h" #include "string-table.h" -#include "udev-util.h" +#include "strv.h" +#include "tmpfile-util.h" #include "util.h" #include "virt.h" +DUID* link_get_duid(Link *link) { + if (link->network->duid.type != _DUID_TYPE_INVALID) + return &link->network->duid; + else + return &link->manager->duid; +} + static bool link_dhcp6_enabled(Link *link) { assert(link); @@ -262,7 +274,7 @@ static int link_enable_ipv6(Link *link) { p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/disable_ipv6"); - r = write_string_file(p, one_zero(disabled), WRITE_STRING_FILE_VERIFY_ON_FAILURE); + r = write_string_file(p, one_zero(disabled), WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) log_link_warning_errno(link, r, "Cannot %s IPv6 for interface %s: %m", enable_disable(!disabled), link->ifname); @@ -399,6 +411,8 @@ static int link_update_flags(Link *link, sd_netlink_message *m) { return 0; } +DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); + static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { _cleanup_(link_unrefp) Link *link = NULL; uint16_t type; @@ -413,7 +427,7 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { /* check for link kind */ r = sd_netlink_message_enter_container(message, IFLA_LINKINFO); if (r == 0) { - (void)sd_netlink_message_read_string(message, IFLA_INFO_KIND, &kind); + (void) sd_netlink_message_read_string(message, IFLA_INFO_KIND, &kind); r = sd_netlink_message_exit_container(message); if (r < 0) return r; @@ -439,16 +453,19 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { if (r < 0) return r; - link = new0(Link, 1); + link = new(Link, 1); if (!link) return -ENOMEM; - link->n_ref = 1; - link->manager = manager; - link->state = LINK_STATE_PENDING; - link->rtnl_extended_attrs = true; - link->ifindex = ifindex; - link->iftype = iftype; + *link = (Link) { + .n_ref = 1, + .manager = manager, + .state = LINK_STATE_PENDING, + .rtnl_extended_attrs = true, + .ifindex = ifindex, + .iftype = iftype, + }; + link->ifname = strdup(ifname); if (!link->ifname) return -ENOMEM; @@ -459,6 +476,10 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { return -ENOMEM; } + r = sd_netlink_message_read_u32(message, IFLA_MASTER, (uint32_t *)&link->master_ifindex); + if (r < 0) + log_link_debug_errno(link, r, "New device has no master, continuing without"); + r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac); if (r < 0) log_link_debug_errno(link, r, "MAC address not found for new device, continuing without"); @@ -489,22 +510,41 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { return 0; } -static void link_free(Link *link) { +static void link_detach_from_manager(Link *link) { + if (!link || !link->manager) + return; + + hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)); + set_remove(link->manager->links_requesting_uuid, link); + link_clean(link); + + link->manager = NULL; +} + +static Link *link_free(Link *link) { Address *address; Link *carrier; + Route *route; Iterator i; - if (!link) - return; + assert(link); - while (!set_isempty(link->addresses)) - address_free(set_first(link->addresses)); + while ((route = set_first(link->routes))) + route_free(route); - while (!set_isempty(link->addresses_foreign)) - address_free(set_first(link->addresses_foreign)); + while ((route = set_first(link->routes_foreign))) + route_free(route); - link->addresses = set_free(link->addresses); + link->routes = set_free(link->routes); + link->routes_foreign = set_free(link->routes_foreign); + while ((address = set_first(link->addresses))) + address_free(address); + + while ((address = set_first(link->addresses_foreign))) + address_free(address); + + link->addresses = set_free(link->addresses); link->addresses_foreign = set_free(link->addresses_foreign); while ((address = link->pool_addresses)) { @@ -530,17 +570,16 @@ static void link_free(Link *link) { sd_ndisc_unref(link->ndisc); sd_radv_unref(link->radv); - if (link->manager) - hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)); + link_detach_from_manager(link); free(link->ifname); free(link->kind); - (void)unlink(link->state_file); + (void) unlink(link->state_file); free(link->state_file); - udev_device_unref(link->udev_device); + sd_device_unref(link->sd_device); HASHMAP_FOREACH (carrier, link->bound_to_links, i) hashmap_remove(link->bound_to_links, INT_TO_PTR(carrier->ifindex)); @@ -550,35 +589,10 @@ static void link_free(Link *link) { hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex)); hashmap_free(link->bound_by_links); - free(link); + return mfree(link); } -Link *link_unref(Link *link) { - if (!link) - return NULL; - - assert(link->n_ref > 0); - - link->n_ref--; - - if (link->n_ref > 0) - return NULL; - - link_free(link); - - return NULL; -} - -Link *link_ref(Link *link) { - if (!link) - return NULL; - - assert(link->n_ref > 0); - - link->n_ref++; - - return link; -} +DEFINE_TRIVIAL_REF_UNREF_FUNC(Link, link, link_free); int link_get(Manager *m, int ifindex, Link **ret) { Link *link; @@ -706,7 +720,7 @@ static void link_enter_configured(Link *link) { assert(link); assert(link->network); - if (link->state != LINK_STATE_SETTING_ROUTES) + if (link->state != LINK_STATE_CONFIGURING) return; log_link_info(link, "Configured"); @@ -728,6 +742,12 @@ void link_check_ready(Link *link) { if (!link->network) return; + if (!link->addresses_configured) + return; + + if (!link->neighbors_configured) + return; + if (!link->static_routes_configured) return; @@ -776,13 +796,14 @@ static int link_set_routing_policy_rule(Link *link) { LIST_FOREACH(rules, rule, link->network->rules) { r = routing_policy_rule_get(link->manager, rule->family, &rule->from, rule->from_prefixlen, &rule->to, - rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif, &rrule); - if (r == 1) { + rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif, + rule->protocol, &rule->sport, &rule->dport, &rrule); + if (r == 0) { (void) routing_policy_rule_make_local(link->manager, rrule); continue; } - r = routing_policy_rule_configure(rule, link, link_routing_policy_rule_handler, false); + r = routing_policy_rule_configure(rule, link, NULL, false); if (r < 0) { log_link_warning_errno(link, r, "Could not set routing policy rules: %m"); link_enter_failed(link); @@ -802,14 +823,13 @@ static int link_set_routing_policy_rule(Link *link) { return 0; } -static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_(link_unrefp) Link *link = userdata; +static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; + assert(link); assert(link->route_messages > 0); - assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES, - LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED, - LINK_STATE_LINGER)); + assert(IN_SET(link->state, LINK_STATE_CONFIGURING, + LINK_STATE_FAILED, LINK_STATE_LINGER)); link->route_messages--; @@ -829,28 +849,41 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata return 1; } -static int link_enter_set_routes(Link *link) { +static int link_request_set_routes(Link *link) { + enum { + PHASE_NON_GATEWAY, /* First phase: Routes without a gateway */ + PHASE_GATEWAY, /* Second phase: Routes with a gateway */ + _PHASE_MAX + } phase; Route *rt; int r; assert(link); assert(link->network); - assert(link->state == LINK_STATE_SETTING_ADDRESSES); + assert(link->addresses_configured); + assert(link->address_messages == 0); + assert(link->state != _LINK_STATE_INVALID); + + link_set_state(link, LINK_STATE_CONFIGURING); (void) link_set_routing_policy_rule(link); - link_set_state(link, LINK_STATE_SETTING_ROUTES); + /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */ + for (phase = 0; phase < _PHASE_MAX; phase++) + LIST_FOREACH(routes, rt, link->network->static_routes) { - LIST_FOREACH(routes, rt, link->network->static_routes) { - r = route_configure(rt, link, route_handler); - if (r < 0) { - log_link_warning_errno(link, r, "Could not set routes: %m"); - link_enter_failed(link); - return r; - } + if (in_addr_is_null(rt->family, &rt->gw) != (phase == PHASE_NON_GATEWAY)) + continue; - link->route_messages++; - } + r = route_configure(rt, link, route_handler); + if (r < 0) { + log_link_warning_errno(link, r, "Could not set routes: %m"); + link_enter_failed(link); + return r; + } + + link->route_messages++; + } if (link->route_messages == 0) { link->static_routes_configured = true; @@ -861,26 +894,35 @@ static int link_enter_set_routes(Link *link) { return 0; } -int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_(link_unrefp) Link *link = userdata; +static int link_request_set_neighbors(Link *link) { + Neighbor *neighbor; int r; - assert(m); assert(link); - assert(link->ifname); + assert(link->network); + assert(link->state != _LINK_STATE_INVALID); - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; + link_set_state(link, LINK_STATE_CONFIGURING); - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -ESRCH) - log_link_warning_errno(link, r, "Could not drop route: %m"); + LIST_FOREACH(neighbors, neighbor, link->network->neighbors) { + r = neighbor_configure(neighbor, link, NULL); + if (r < 0) { + log_link_warning_errno(link, r, "Could not set neighbor: %m"); + link_enter_failed(link); + return r; + } + } - return 1; + if (link->neighbor_messages == 0) { + link->neighbors_configured = true; + link_check_ready(link); + } else + log_link_debug(link, "Setting neighbors"); + + return 0; } -static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_(link_unrefp) Link *link = userdata; +static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; assert(rtnl); @@ -888,7 +930,7 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda assert(link); assert(link->ifname); assert(link->address_messages > 0); - assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES, + assert(IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_FAILED, LINK_STATE_LINGER)); link->address_messages--; @@ -904,39 +946,13 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda if (link->address_messages == 0) { log_link_debug(link, "Addresses set"); - link_enter_set_routes(link); + link->addresses_configured = true; + link_request_set_routes(link); } return 1; } -static int address_label_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_(link_unrefp) Link *link = userdata; - int r; - - assert(rtnl); - assert(m); - assert(link); - assert(link->ifname); - assert(link->address_label_messages > 0); - - link->address_label_messages--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) - log_link_warning_errno(link, r, "could not set address label: %m"); - else if (r >= 0) - manager_rtnl_process_address(rtnl, m, link->manager); - - if (link->address_label_messages == 0) - log_link_debug(link, "Addresses label set"); - - return 1; -} - static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) { _cleanup_free_ struct in_addr *addresses = NULL; size_t n_addresses = 0, n_allocated = 0; @@ -1048,7 +1064,7 @@ static int link_set_bridge_fdb(Link *link) { return 0; } -static int link_enter_set_addresses(Link *link) { +static int link_request_set_addresses(Link *link) { AddressLabel *label; Address *ad; int r; @@ -1061,7 +1077,9 @@ static int link_enter_set_addresses(Link *link) { if (r < 0) return r; - link_set_state(link, LINK_STATE_SETTING_ADDRESSES); + link_set_state(link, LINK_STATE_CONFIGURING); + + link_request_set_neighbors(link); LIST_FOREACH(addresses, ad, link->network->static_addresses) { r = address_configure(ad, link, address_handler, false); @@ -1075,7 +1093,7 @@ static int link_enter_set_addresses(Link *link) { } LIST_FOREACH(labels, label, link->network->address_labels) { - r = address_label_configure(label, link, address_label_handler, false); + r = address_label_configure(label, link, NULL, false); if (r < 0) { log_link_warning_errno(link, r, "Could not set address label: %m"); link_enter_failed(link); @@ -1087,7 +1105,7 @@ static int link_enter_set_addresses(Link *link) { /* now that we can figure out a default address for the dhcp server, start it */ - if (link_dhcp4_server_enabled(link)) { + if (link_dhcp4_server_enabled(link) && (link->flags & IFF_UP)) { Address *address; Link *uplink = NULL; bool acquired_uplink = false; @@ -1166,10 +1184,8 @@ static int link_enter_set_addresses(Link *link) { } r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to set router emission for DHCP server: %m"); - return r; - } + if (r < 0) + return log_link_warning_errno(link, r, "Failed to set router emission for DHCP server: %m"); if (link->network->dhcp_server_emit_timezone) { _cleanup_free_ char *buffer = NULL; @@ -1204,32 +1220,15 @@ static int link_enter_set_addresses(Link *link) { log_link_debug(link, "Offering DHCPv4 leases"); } - if (link->address_messages == 0) - link_enter_set_routes(link); - else + if (link->address_messages == 0) { + link->addresses_configured = true; + link_request_set_routes(link); + } else log_link_debug(link, "Setting addresses"); return 0; } -int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_(link_unrefp) Link *link = userdata; - int r; - - assert(m); - assert(link); - assert(link->ifname); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EADDRNOTAVAIL) - log_link_warning_errno(link, r, "Could not drop address: %m"); - - return 1; -} - static int link_set_bridge_vlan(Link *link) { int r = 0; @@ -1249,43 +1248,53 @@ static int link_set_proxy_arp(Link *link) { p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/proxy_arp"); - r = write_string_file(p, one_zero(link->network->proxy_arp), WRITE_STRING_FILE_VERIFY_ON_FAILURE); + r = write_string_file(p, one_zero(link->network->proxy_arp), WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface: %m"); return 0; } -static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_(link_unrefp) Link *link = userdata; +static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; + assert(link); + log_link_debug(link, "Set link"); r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) { log_link_error_errno(link, r, "Could not join netdev: %m"); link_enter_failed(link); - return 1; } - return 0; + return 1; } -static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_(link_unrefp) Link *link = userdata; +static int link_configure_after_setting_mtu(Link *link); + +static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; assert(m); assert(link); assert(link->ifname); + link->setting_mtu = false; + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); - if (r < 0) + if (r < 0) { log_link_warning_errno(link, r, "Could not set MTU: %m"); + return 1; + } + + log_link_debug(link, "Setting MTU done."); + + if (link->state == LINK_STATE_PENDING) + (void) link_configure_after_setting_mtu(link); return 1; } @@ -1298,6 +1307,9 @@ int link_set_mtu(Link *link, uint32_t mtu) { assert(link->manager); assert(link->manager->rtnl); + if (link->mtu == mtu || link->setting_mtu) + return 0; + log_link_debug(link, "Setting MTU: %" PRIu32, mtu); r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); @@ -1305,40 +1317,35 @@ int link_set_mtu(Link *link, uint32_t mtu) { return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); /* If IPv6 not configured (no static IPv6 address and IPv6LL autoconfiguration is disabled) - for this interface, or if it is a bridge slave, then disable IPv6 else enable it. */ + * for this interface, or if it is a bridge slave, then disable IPv6 else enable it. */ (void) link_enable_ipv6(link); /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes - on the interface. Bump up MTU bytes to IPV6_MTU_MIN. */ - if (link_ipv6_enabled(link) && link->network->mtu < IPV6_MIN_MTU) { + * on the interface. Bump up MTU bytes to IPV6_MTU_MIN. */ + if (link_ipv6_enabled(link) && mtu < IPV6_MIN_MTU) { log_link_warning(link, "Bumping MTU to " STRINGIFY(IPV6_MIN_MTU) ", as " "IPv6 is requested and requires a minimum MTU of " STRINGIFY(IPV6_MIN_MTU) " bytes: %m"); - link->network->mtu = IPV6_MIN_MTU; + mtu = IPV6_MIN_MTU; } - r = sd_netlink_message_append_u32(req, IFLA_MTU, link->network->mtu); - if (r < 0) - return log_link_error_errno(link, r, "Could not set MTU: %m"); - r = sd_netlink_message_append_u32(req, IFLA_MTU, mtu); if (r < 0) return log_link_error_errno(link, r, "Could not append MTU: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL); + r = netlink_call_async(link->manager->rtnl, NULL, req, set_mtu_handler, + link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); - link->setting_mtu = true; - link_ref(link); + link->setting_mtu = true; return 0; } -static int set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_(link_unrefp) Link *link = userdata; +static int set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; assert(m); @@ -1397,7 +1404,8 @@ static int link_set_flags(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not set link flags: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, set_flags_handler, link, 0, NULL); + r = netlink_call_async(link->manager->rtnl, NULL, req, set_flags_handler, + link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -1454,7 +1462,12 @@ static int link_set_bridge(Link *link) { r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood); if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m"); + } + if (link->network->multicast_to_unicast >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_TO_UCAST, link->network->multicast_to_unicast); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_TO_UCAST attribute: %m"); } if (link->network->cost != 0) { @@ -1462,6 +1475,7 @@ static int link_set_bridge(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m"); } + if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) { r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority); if (r < 0) @@ -1472,7 +1486,8 @@ static int link_set_bridge(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL); + r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_handler, + link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -1524,7 +1539,8 @@ static int link_bond_set(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, set_flags_handler, link, 0, NULL); + r = netlink_call_async(link->manager->rtnl, NULL, req, set_flags_handler, + link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -1628,18 +1644,6 @@ static int link_acquire_ipv6_conf(Link *link) { assert(link); - if (link_dhcp6_enabled(link)) { - assert(link->dhcp6_client); - assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0); - - /* start DHCPv6 client in stateless mode */ - r = dhcp6_request_address(link, true); - if (r < 0 && r != -EBUSY) - return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m"); - else - log_link_debug(link, "Acquiring DHCPv6 lease"); - } - if (link_ipv6_accept_ra_enabled(link)) { assert(link->ndisc); @@ -1661,6 +1665,8 @@ static int link_acquire_ipv6_conf(Link *link) { return log_link_warning_errno(link, r, "Could not start IPv6 Router Advertisement: %m"); } + (void) dhcp6_request_prefix_delegation(link); + return 0; } @@ -1700,11 +1706,6 @@ static int link_acquire_conf(Link *link) { assert(link); - if (link->setting_mtu) { - link->setting_mtu = false; - return 0; - } - r = link_acquire_ipv4_conf(link); if (r < 0) return r; @@ -1738,8 +1739,7 @@ bool link_has_carrier(Link *link) { return false; } -static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_(link_unrefp) Link *link = userdata; +static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; assert(link); @@ -1749,8 +1749,7 @@ static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda r = sd_netlink_message_get_errno(m); if (r < 0) - /* we warn but don't fail the link, as it may be - brought up later */ + /* we warn but don't fail the link, as it may be brought up later */ log_link_warning_errno(link, r, "Could not bring up interface: %m"); return 1; @@ -1832,7 +1831,8 @@ int link_up(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL); + r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler, + link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -1857,7 +1857,8 @@ static int link_up_can(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not set link flags: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL); + r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler, + link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -1946,7 +1947,8 @@ static int link_set_can(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Failed to close netlink container: %m"); - r = sd_netlink_call_async(link->manager->rtnl, m, link_set_handler, link, 0, NULL); + r = netlink_call_async(link->manager->rtnl, NULL, m, link_set_handler, + link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -1965,8 +1967,7 @@ static int link_set_can(Link *link) { return r; } -static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_(link_unrefp) Link *link = userdata; +static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; assert(link); @@ -1978,10 +1979,8 @@ static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *user if (r < 0) log_link_warning_errno(link, r, "Could not bring down interface: %m"); - if (streq_ptr(link->kind, "can")) { - link_ref(link); + if (streq_ptr(link->kind, "can")) link_set_can(link); - } return 1; } @@ -2005,7 +2004,8 @@ int link_down(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not set link flags: %m"); - r = sd_netlink_call_async(link->manager->rtnl, req, link_down_handler, link, 0, NULL); + r = netlink_call_async(link->manager->rtnl, NULL, req, link_down_handler, + link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -2257,7 +2257,10 @@ void link_drop(Link *link) { log_link_debug(link, "Link removed"); - (void)unlink(link->state_file); + (void) unlink(link->state_file); + + link_detach_from_manager(link); + link_unref(link); return; @@ -2306,11 +2309,10 @@ static int link_joined(Link *link) { if (!link_has_carrier(link) && !link->network->configure_without_carrier) return 0; - return link_enter_set_addresses(link); + return link_request_set_addresses(link); } -static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_(link_unrefp) Link *link = userdata; +static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; assert(link); @@ -2344,7 +2346,7 @@ static int link_enter_join_netdev(Link *link) { assert(link->network); assert(link->state == LINK_STATE_PENDING); - link_set_state(link, LINK_STATE_ENSLAVING); + link_set_state(link, LINK_STATE_CONFIGURING); link_dirty(link); @@ -2355,6 +2357,10 @@ static int link_enter_join_netdev(Link *link) { return link_joined(link); if (link->network->bond) { + if (link->network->bond->state == NETDEV_STATE_READY && + link->network->bond->ifindex == link->master_ifindex) + return link_joined(link); + log_struct(LOG_DEBUG, LOG_LINK_INTERFACE(link), LOG_NETDEV_INTERFACE(link->network->bond), @@ -2452,7 +2458,7 @@ static int link_set_ipv4_forward(Link *link) { * primarily to keep IPv4 and IPv6 packet forwarding behaviour * somewhat in sync (see below). */ - r = write_string_file("/proc/sys/net/ipv4/ip_forward", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE); + r = write_string_file("/proc/sys/net/ipv4/ip_forward", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m"); @@ -2474,7 +2480,7 @@ static int link_set_ipv6_forward(Link *link) { * same behaviour there and also propagate the setting from * one to all, to keep things simple (see above). */ - r = write_string_file("/proc/sys/net/ipv6/conf/all/forwarding", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE); + r = write_string_file("/proc/sys/net/ipv6/conf/all/forwarding", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m"); @@ -2494,7 +2500,7 @@ static int link_set_ipv6_privacy_extensions(Link *link) { p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr"); xsprintf(buf, "%u", (unsigned) link->network->ipv6_privacy_extensions); - r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE); + r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m"); @@ -2518,7 +2524,7 @@ static int link_set_ipv6_accept_ra(Link *link) { p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra"); /* We handle router advertisements ourselves, tell the kernel to GTFO */ - r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE); + r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m"); @@ -2546,7 +2552,7 @@ static int link_set_ipv6_dad_transmits(Link *link) { p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/dad_transmits"); xsprintf(buf, "%i", link->network->ipv6_dad_transmits); - r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE); + r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m"); @@ -2574,7 +2580,7 @@ static int link_set_ipv6_hop_limit(Link *link) { p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/hop_limit"); xsprintf(buf, "%i", link->network->ipv6_hop_limit); - r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE); + r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m"); @@ -2600,13 +2606,45 @@ static int link_set_ipv6_mtu(Link *link) { xsprintf(buf, "%" PRIu32, link->network->ipv6_mtu); - r = write_string_file(p, buf, 0); + r = write_string_file(p, buf, WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface: %m"); return 0; } +static bool link_is_static_address_configured(Link *link, Address *address) { + Address *net_address; + + assert(link); + assert(address); + + if (!link->network) + return false; + + LIST_FOREACH(addresses, net_address, link->network->static_addresses) + if (address_equal(net_address, address)) + return true; + + return false; +} + +static bool link_is_static_route_configured(Link *link, Route *route) { + Route *net_route; + + assert(link); + assert(route); + + if (!link->network) + return false; + + LIST_FOREACH(routes, net_route, link->network->static_routes) + if (route_equal(net_route, route)) + return true; + + return false; +} + static int link_drop_foreign_config(Link *link) { Address *address; Route *route; @@ -2618,9 +2656,15 @@ static int link_drop_foreign_config(Link *link) { if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1) continue; - r = address_remove(address, link, link_address_remove_handler); - if (r < 0) - return r; + if (link_is_static_address_configured(link, address)) { + r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL); + if (r < 0) + return log_link_error_errno(link, r, "Failed to add address: %m"); + } else { + r = address_remove(address, link, NULL); + if (r < 0) + return r; + } } SET_FOREACH(route, link->routes_foreign, i) { @@ -2628,9 +2672,15 @@ static int link_drop_foreign_config(Link *link) { if (route->protocol == RTPROT_KERNEL) continue; - r = route_remove(route, link, link_route_remove_handler); - if (r < 0) - return r; + if (link_is_static_route_configured(link, route)) { + r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL); + if (r < 0) + return r; + } else { + r = route_remove(route, link, NULL); + if (r < 0) + return r; + } } return 0; @@ -2647,7 +2697,7 @@ static int link_drop_config(Link *link) { if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1) continue; - r = address_remove(address, link, link_address_remove_handler); + r = address_remove(address, link, NULL); if (r < 0) return r; @@ -2666,7 +2716,7 @@ static int link_drop_config(Link *link) { if (route->protocol == RTPROT_KERNEL) continue; - r = route_remove(route, link, link_route_remove_handler); + r = route_remove(route, link, NULL); if (r < 0) return r; } @@ -2868,6 +2918,19 @@ static int link_configure(Link *link) { return r; } + return link_configure_after_setting_mtu(link); +} + +static int link_configure_after_setting_mtu(Link *link) { + int r; + + assert(link); + assert(link->network); + assert(link->state == LINK_STATE_PENDING); + + if (link->setting_mtu) + return 0; + if (link_has_carrier(link) || link->network->configure_without_carrier) { r = link_acquire_conf(link); if (r < 0) @@ -2877,9 +2940,136 @@ static int link_configure(Link *link) { return link_enter_join_netdev(link); } -static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m, - void *userdata) { - _cleanup_(link_unrefp) Link *link = userdata; +static int duid_set_uuid(DUID *duid, sd_id128_t uuid) { + assert(duid); + + if (duid->raw_data_len > 0) + return 0; + + if (duid->type != DUID_TYPE_UUID) + return -EINVAL; + + memcpy(&duid->raw_data, &uuid, sizeof(sd_id128_t)); + duid->raw_data_len = sizeof(sd_id128_t); + + return 1; +} + +int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + Manager *manager = userdata; + const sd_bus_error *e; + const void *a; + size_t sz; + DUID *duid; + Link *link; + int r; + + assert(m); + assert(manager); + + e = sd_bus_message_get_error(m); + if (e) { + log_error_errno(sd_bus_error_get_errno(e), + "Could not get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %s", + e->message); + goto configure; + } + + r = sd_bus_message_read_array(m, 'y', &a, &sz); + if (r < 0) + goto configure; + + if (sz != sizeof(sd_id128_t)) { + log_error("Invalid product UUID. Falling back to use machine-app-specific ID as DUID-UUID."); + goto configure; + } + + memcpy(&manager->product_uuid, a, sz); + while ((duid = set_steal_first(manager->duids_requesting_uuid))) + (void) duid_set_uuid(duid, manager->product_uuid); + + manager->duids_requesting_uuid = set_free(manager->duids_requesting_uuid); + +configure: + while ((link = set_steal_first(manager->links_requesting_uuid))) { + r = link_configure(link); + if (r < 0) + log_link_error_errno(link, r, "Failed to configure link: %m"); + } + + manager->links_requesting_uuid = set_free(manager->links_requesting_uuid); + + /* To avoid calling GetProductUUID() bus method so frequently, set the flag below + * even if the method fails. */ + manager->has_product_uuid = true; + + return 1; +} + +static bool link_requires_uuid(Link *link) { + const DUID *duid; + + assert(link); + assert(link->manager); + assert(link->network); + + duid = link_get_duid(link); + if (duid->type != DUID_TYPE_UUID || duid->raw_data_len != 0) + return false; + + if (link_dhcp4_enabled(link) && IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY)) + return true; + + if (link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link)) + return true; + + return false; +} + +static int link_configure_duid(Link *link) { + Manager *m; + DUID *duid; + int r; + + assert(link); + assert(link->manager); + assert(link->network); + + m = link->manager; + duid = link_get_duid(link); + + if (!link_requires_uuid(link)) + return 1; + + if (m->has_product_uuid) { + (void) duid_set_uuid(duid, m->product_uuid); + return 1; + } + + if (!m->links_requesting_uuid) { + r = manager_request_product_uuid(m, link); + if (r < 0) { + if (r == -ENOMEM) + return r; + + log_link_warning_errno(link, r, + "Failed to get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %m"); + return 1; + } + } else { + r = set_put(m->links_requesting_uuid, link); + if (r < 0) + return log_oom(); + + r = set_put(m->duids_requesting_uuid, duid); + if (r < 0) + return log_oom(); + } + + return 0; +} + +static int link_initialized_and_synced(Link *link) { Network *network; int r; @@ -2901,7 +3091,7 @@ static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m, return r; if (!link->network) { - r = network_get(link->manager, link->udev_device, link->ifname, + r = network_get(link->manager, link->sd_device, link->ifname, &link->mac, &network); if (r == -ENOENT) { link_enter_unmanaged(link); @@ -2932,6 +3122,12 @@ static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m, if (r < 0) return r; + /* link_configure_duid() returns 0 if it requests product UUID. In that case, + * link_configure() is called later asynchronously. */ + r = link_configure_duid(link); + if (r <= 0) + return r; + r = link_configure(link); if (r < 0) return r; @@ -2939,7 +3135,12 @@ static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m, return 1; } -int link_initialized(Link *link, struct udev_device *device) { +static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + (void) link_initialized_and_synced(link); + return 1; +} + +int link_initialized(Link *link, sd_device *device) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; @@ -2951,12 +3152,12 @@ int link_initialized(Link *link, struct udev_device *device) { if (link->state != LINK_STATE_PENDING) return 0; - if (link->udev_device) + if (link->sd_device) return 0; log_link_debug(link, "udev initialized link"); - link->udev_device = udev_device_ref(device); + link->sd_device = sd_device_ref(device); /* udev has initialized the link, but we don't know if we have yet * processed the NEWLINK messages with the latest state. Do a GETLINK, @@ -2968,8 +3169,8 @@ int link_initialized(Link *link, struct udev_device *device) { if (r < 0) return r; - r = sd_netlink_call_async(link->manager->rtnl, req, - link_initialized_and_synced, link, 0, NULL); + r = netlink_call_async(link->manager->rtnl, NULL, req, link_initialized_handler, + link_netlink_destroy_callback, link); if (r < 0) return r; @@ -2991,13 +3192,12 @@ static int link_load(Link *link) { assert(link); - r = parse_env_file(NULL, link->state_file, NEWLINE, + r = parse_env_file(NULL, link->state_file, "NETWORK_FILE", &network_file, "ADDRESSES", &addresses, "ROUTES", &routes, "DHCP4_ADDRESS", &dhcp4_address, - "IPV4LL_ADDRESS", &ipv4ll_address, - NULL); + "IPV4LL_ADDRESS", &ipv4ll_address); if (r < 0 && r != -ENOENT) return log_link_error_errno(link, r, "Failed to read %s: %m", link->state_file); @@ -3169,9 +3369,9 @@ ipv4ll_address_fail: } int link_add(Manager *m, sd_netlink_message *message, Link **ret) { - Link *link; - _cleanup_(udev_device_unrefp) struct udev_device *device = NULL; + _cleanup_(sd_device_unrefp) sd_device *device = NULL; char ifindex_str[2 + DECIMAL_STR_MAX(int)]; + Link *link; int r; assert(m); @@ -3194,13 +3394,18 @@ int link_add(Manager *m, sd_netlink_message *message, Link **ret) { if (detect_container() <= 0) { /* not in a container, udev will be around */ sprintf(ifindex_str, "n%d", link->ifindex); - device = udev_device_new_from_device_id(m->udev, ifindex_str); - if (!device) { - r = log_link_warning_errno(link, errno, "Could not find udev device: %m"); + r = sd_device_new_from_device_id(&device, ifindex_str); + if (r < 0) { + log_link_warning_errno(link, r, "Could not find device: %m"); goto failed; } - if (udev_device_get_is_initialized(device) <= 0) { + r = sd_device_get_is_initialized(device); + if (r < 0) { + log_link_warning_errno(link, r, "Could not determine whether the device is initialized or not: %m"); + goto failed; + } + if (r == 0) { /* not yet ready */ log_link_debug(link, "link pending udev initialization..."); return 0; @@ -3210,10 +3415,7 @@ int link_add(Manager *m, sd_netlink_message *message, Link **ret) { if (r < 0) goto failed; } else { - /* we are calling a callback directly, so must take a ref */ - link_ref(link); - - r = link_initialized_and_synced(m->rtnl, NULL, link); + r = link_initialized_and_synced(link); if (r < 0) goto failed; } @@ -3257,7 +3459,7 @@ static int link_carrier_gained(Link *link) { return r; } - r = link_enter_set_addresses(link); + r = link_request_set_addresses(link); if (r < 0) return r; } @@ -3275,8 +3477,8 @@ static int link_carrier_lost(Link *link) { assert(link); /* Some devices reset itself while setting the MTU. This causes the DHCP client fall into a loop. - setting_mtu keep track whether the device got reset because of setting MTU and does not drop the - configuration and stop the clients as well. */ + * setting_mtu keep track whether the device got reset because of setting MTU and does not drop the + * configuration and stop the clients as well. */ if (link->setting_mtu) return 0; @@ -3339,9 +3541,8 @@ int link_update(Link *link, sd_netlink_message *m) { assert(m); if (link->state == LINK_STATE_LINGER) { - link_ref(link); log_link_info(link, "Link readded"); - link_set_state(link, LINK_STATE_ENSLAVING); + link_set_state(link, LINK_STATE_CONFIGURING); r = link_new_carrier_maps(link); if (r < 0) @@ -3377,10 +3578,8 @@ int link_update(Link *link, sd_netlink_message *m) { if (link->dhcp_client) { r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu); - if (r < 0) { - log_link_warning_errno(link, r, "Could not update MTU in DHCP client: %m"); - return r; - } + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MTU in DHCP client: %m"); } if (link->radv) { @@ -3423,45 +3622,13 @@ int link_update(Link *link, sd_netlink_message *m) { if (r < 0) return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m"); - switch (link->network->dhcp_client_identifier) { - case DHCP_CLIENT_ID_DUID: { - const DUID *duid = link_duid(link); - - r = sd_dhcp_client_set_iaid_duid(link->dhcp_client, - link->network->iaid, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update DUID/IAID in DHCP client: %m"); - break; - } - case DHCP_CLIENT_ID_DUID_ONLY: { - const DUID *duid = link_duid(link); - - r = sd_dhcp_client_set_duid(link->dhcp_client, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update DUID in DHCP client: %m"); - break; - } - case DHCP_CLIENT_ID_MAC: - r = sd_dhcp_client_set_client_id(link->dhcp_client, - ARPHRD_ETHER, - (const uint8_t *)&link->mac, - sizeof(link->mac)); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update MAC client id in DHCP client: %m"); - break; - default: - assert_not_reached("Unknown client identifier type."); - } + r = dhcp4_set_client_identifier(link); + if (r < 0) + return r; } if (link->dhcp6_client) { - const DUID* duid = link_duid(link); + const DUID* duid = link_get_duid(link); r = sd_dhcp6_client_set_mac(link->dhcp6_client, (const uint8_t *) &link->mac, @@ -3470,10 +3637,12 @@ int link_update(Link *link, sd_netlink_message *m) { if (r < 0) return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m"); - r = sd_dhcp6_client_set_iaid(link->dhcp6_client, - link->network->iaid); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m"); + if (link->network->iaid_set) { + r = sd_dhcp6_client_set_iaid(link->dhcp6_client, + link->network->iaid); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m"); + } r = sd_dhcp6_client_set_duid(link->dhcp6_client, duid->type, @@ -3760,6 +3929,8 @@ int link_save(Link *link) { resolve_support_to_string(link->network->llmnr)); fprintf(f, "MDNS=%s\n", resolve_support_to_string(link->network->mdns)); + if (link->network->dns_default_route >= 0) + fprintf(f, "DNS_DEFAULT_ROUTE=%s\n", yes_no(link->network->dns_default_route)); if (link->network->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID) fprintf(f, "DNS_OVER_TLS=%s\n", @@ -3898,15 +4069,12 @@ void link_clean(Link *link) { assert(link); assert(link->manager); - set_remove(link->manager->dirty_links, link); - link_unref(link); + link_unref(set_remove(link->manager->dirty_links, link)); } static const char* const link_state_table[_LINK_STATE_MAX] = { [LINK_STATE_PENDING] = "pending", - [LINK_STATE_ENSLAVING] = "configuring", - [LINK_STATE_SETTING_ADDRESSES] = "configuring", - [LINK_STATE_SETTING_ROUTES] = "configuring", + [LINK_STATE_CONFIGURING] = "configuring", [LINK_STATE_CONFIGURED] = "configured", [LINK_STATE_UNMANAGED] = "unmanaged", [LINK_STATE_FAILED] = "failed", |