diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index dd1dc78dae..3d00802b20 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -96,113 +96,64 @@ const DUID *link_get_duid(Link *link, int family) { return duid; } -static int link_configure_and_start_dhcp_delayed(Link *link) { - int r; - - assert(link); - - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) - return 0; - - if (!link->dhcp_client) { - r = dhcp4_configure(link); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to configure DHCP4 client: %m"); - } - - if (!link->dhcp6_client) { - r = dhcp6_configure(link); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to configure DHCP6 client: %m"); - } - - if (link->set_flags_messages > 0) - return 0; - - if (!link_has_carrier(link)) - return 0; - - r = dhcp4_start(link); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to start DHCPv4 client: %m"); - - r = ndisc_start(link); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m"); - - r = dhcp6_start(link); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to start DHCPv6 client: %m"); - - return 0; -} - static 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; - Link *link; int r; assert(m); assert(manager); + /* To avoid calling GetProductUUID() bus method so frequently, set the flag below + * even if the method fails. */ + manager->has_product_uuid = true; + e = sd_bus_message_get_error(m); if (e) { r = sd_bus_error_get_errno(e); log_warning_errno(r, "Could not get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %s", bus_error_message(e, r)); - goto configure; + return 0; } r = sd_bus_message_read_array(m, 'y', &a, &sz); if (r < 0) { log_warning_errno(r, "Failed to get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %m"); - goto configure; + return 0; } if (sz != sizeof(sd_id128_t)) { log_warning("Invalid product UUID. Falling back to use machine-app-specific ID as DUID-UUID."); - goto configure; + return 0; } + log_debug("Successfully obtained product UUID"); + memcpy(&manager->duid_product_uuid.raw_data, a, sz); manager->duid_product_uuid.raw_data_len = sz; -configure: - /* To avoid calling GetProductUUID() bus method so frequently, set the flag below - * even if the method fails. */ - manager->has_product_uuid = true; - - while ((link = set_steal_first(manager->links_requesting_uuid))) { - r = link_configure_and_start_dhcp_delayed(link); - if (r < 0) - link_enter_failed(link); - - link_unref(link); - } - - manager->links_requesting_uuid = set_free(manager->links_requesting_uuid); - - return 1; + return 0; } int manager_request_product_uuid(Manager *m) { + static bool bus_method_is_called = false; int r; assert(m); - if (m->product_uuid_requested) + if (bus_method_is_called) return 0; - log_debug("Requesting product UUID"); - - if (sd_bus_is_ready(m->bus) <= 0) { + if (sd_bus_is_ready(m->bus) <= 0 && !m->product_uuid_requested) { log_debug("Not connected to system bus, requesting product UUID later."); + m->product_uuid_requested = true; return 0; } + m->product_uuid_requested = false; + r = sd_bus_call_method_async( m->bus, NULL, @@ -217,7 +168,9 @@ int manager_request_product_uuid(Manager *m) { if (r < 0) return log_warning_errno(r, "Failed to get product UUID: %m"); - m->product_uuid_requested = true; + log_debug("Requesting product UUID."); + + bus_method_is_called = true; return 0; } @@ -247,12 +200,6 @@ int dhcp_configure_duid(Link *link, const DUID *duid) { return 1; } - r = set_ensure_put(&m->links_requesting_uuid, NULL, link); - if (r < 0) - return log_oom(); - if (r > 0) - link_ref(link); - return 0; } diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 135aeace7e..cc6d198851 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1395,15 +1395,6 @@ static int dhcp4_set_client_identifier(Link *link) { return 0; } -static int dhcp4_configure_duid(Link *link) { - assert(link); - - if (!IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY)) - return 1; - - return dhcp_configure_duid(link, link_get_dhcp4_duid(link)); -} - static int dhcp4_set_request_address(Link *link) { Address *a; @@ -1453,7 +1444,7 @@ static bool link_needs_dhcp_broadcast(Link *link) { return r == true; } -int dhcp4_configure(Link *link) { +static int dhcp4_configure(Link *link) { sd_dhcp_option *send_option; void *request_options; int r; @@ -1461,16 +1452,9 @@ int dhcp4_configure(Link *link) { assert(link); assert(link->network); - if (!link_dhcp4_enabled(link)) - return 0; - if (link->dhcp_client) return log_link_debug_errno(link, SYNTHETIC_ERRNO(EBUSY), "DHCP4 client is already configured."); - r = dhcp4_configure_duid(link); - if (r <= 0) - return r; - r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize); if (r < 0) return log_link_debug_errno(link, r, "DHCP4 CLIENT: Failed to allocate DHCP4 client: %m"); @@ -1642,17 +1626,83 @@ int dhcp4_update_mac(Link *link) { } int dhcp4_start(Link *link) { + int r; + assert(link); if (!link->dhcp_client) return 0; + if (!link_has_carrier(link)) + return 0; + if (sd_dhcp_client_is_running(link->dhcp_client) > 0) return 0; - log_link_debug(link, "Acquiring DHCPv4 lease"); + r = sd_dhcp_client_start(link->dhcp_client); + if (r < 0) + return r; - return sd_dhcp_client_start(link->dhcp_client); + return 1; +} + +static int dhcp4_configure_duid(Link *link) { + assert(link); + + if (!IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY)) + return 1; + + return dhcp_configure_duid(link, link_get_dhcp4_duid(link)); +} + +int request_process_dhcp4_client(Request *req) { + Link *link; + int r; + + assert(req); + assert(req->link); + assert(req->type == REQUEST_TYPE_DHCP4_CLIENT); + + link = req->link; + + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return 0; + + r = dhcp4_configure_duid(link); + if (r <= 0) + return r; + + r = dhcp4_configure(req->link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure DHCPv4 client: %m"); + + r = dhcp4_start(link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to start DHCPv4 client: %m"); + + log_link_debug(link, "DHCPv4 client is configured%s.", + r > 0 ? ", acquiring DHCPv4 lease" : ""); + + return 1; +} + +int link_request_dhcp4_client(Link *link) { + int r; + + assert(link); + + if (!link_dhcp4_enabled(link)) + return 0; + + if (link->dhcp_client) + return 0; + + r = link_queue_request(link, REQUEST_TYPE_DHCP4_CLIENT, NULL, false, NULL, NULL, NULL); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to request configuring of the DHCPv4 client: %m"); + + log_link_debug(link, "Requested configuring of the DHCPv4 client."); + return 0; } int config_parse_dhcp_max_attempts( diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h index e41e39fc6e..152c2213b4 100644 --- a/src/network/networkd-dhcp4.h +++ b/src/network/networkd-dhcp4.h @@ -4,6 +4,8 @@ #include "conf-parser.h" typedef struct Link Link; +typedef struct Network Network; +typedef struct Request Request; typedef enum DHCPClientIdentifier { DHCP_CLIENT_ID_MAC, @@ -18,11 +20,13 @@ typedef enum DHCPClientIdentifier { } DHCPClientIdentifier; void network_adjust_dhcp4(Network *network); -int dhcp4_configure(Link *link); int dhcp4_update_mac(Link *link); int dhcp4_start(Link *link); int dhcp4_lease_lost(Link *link); +int request_process_dhcp4_client(Request *req); +int link_request_dhcp4_client(Link *link); + CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_acl_ip_address); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 605ee7dd11..163af103e4 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -1393,6 +1393,8 @@ int dhcp6_request_information(Link *link, int ir) { } int dhcp6_start(Link *link) { + int r; + assert(link); if (!link->dhcp6_client) @@ -1401,6 +1403,9 @@ int dhcp6_start(Link *link) { if (!link_dhcp6_enabled(link)) return 0; + if (!link_has_carrier(link)) + return 0; + if (link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_NO) return 0; @@ -1412,9 +1417,11 @@ int dhcp6_start(Link *link) { if (sd_dhcp6_client_is_running(link->dhcp6_client) > 0) return 0; - log_link_debug(link, "Acquiring DHCPv6 lease"); + r = dhcp6_request_information(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST); + if (r < 0) + return r; - return dhcp6_request_information(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST); + return 1; } int dhcp6_request_prefix_delegation(Link *link) { @@ -1571,7 +1578,7 @@ static int dhcp6_set_identifier(Link *link, sd_dhcp6_client *client) { return 0; } -int dhcp6_configure(Link *link) { +static int dhcp6_configure(Link *link) { _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL; sd_dhcp6_option *vendor_option; sd_dhcp6_option *send_option; @@ -1581,16 +1588,9 @@ int dhcp6_configure(Link *link) { assert(link); assert(link->network); - if (!link_dhcp6_enabled(link) && !link_ipv6_accept_ra_enabled(link)) - return 0; - if (link->dhcp6_client) return log_link_debug_errno(link, SYNTHETIC_ERRNO(EBUSY), "DHCP6 client is already configured."); - r = dhcp_configure_duid(link, link_get_dhcp6_duid(link)); - if (r <= 0) - return r; - r = sd_dhcp6_client_new(&client); if (r == -ENOMEM) return log_oom_debug(); @@ -1716,6 +1716,60 @@ int dhcp6_update_mac(Link *link) { return 0; } +int request_process_dhcp6_client(Request *req) { + Link *link; + int r; + + assert(req); + assert(req->link); + assert(req->type == REQUEST_TYPE_DHCP6_CLIENT); + + link = req->link; + + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return 0; + + r = dhcp_configure_duid(link, link_get_dhcp6_duid(link)); + if (r <= 0) + return r; + + r = dhcp6_configure(link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure DHCPv6 client: %m"); + + r = ndisc_start(link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m"); + + r = dhcp6_start(link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to start DHCPv6 client: %m"); + + log_link_debug(link, "DHCPv6 client is configured%s.", + r > 0 ? ", acquiring DHCPv6 lease" : ""); + + return 1; +} + +int link_request_dhcp6_client(Link *link) { + int r; + + assert(link); + + if (!link_dhcp6_enabled(link) && !link_ipv6_accept_ra_enabled(link)) + return 0; + + if (link->dhcp6_client) + return 0; + + r = link_queue_request(link, REQUEST_TYPE_DHCP6_CLIENT, NULL, false, NULL, NULL, NULL); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to request configuring of the DHCPv6 client: %m"); + + log_link_debug(link, "Requested configuring of the DHCPv6 client."); + return 0; +} + int link_serialize_dhcp6_client(Link *link, FILE *f) { _cleanup_free_ char *duid = NULL; uint32_t iaid; diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h index 82becb0321..23612454d9 100644 --- a/src/network/networkd-dhcp6.h +++ b/src/network/networkd-dhcp6.h @@ -1,9 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once -#include "sd-dhcp6-client.h" - #include "conf-parser.h" +#include "in-addr-util.h" #include "macro.h" typedef enum DHCP6ClientStartMode { @@ -15,7 +14,7 @@ typedef enum DHCP6ClientStartMode { } DHCP6ClientStartMode; typedef struct Link Link; -typedef struct Manager Manager; +typedef struct Request Request; typedef struct DHCP6DelegatedPrefix { struct in6_addr prefix; /* Prefix assigned to the link */ @@ -29,12 +28,14 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DHCP6DelegatedPrefix*, dhcp6_pd_free); bool link_dhcp6_with_address_enabled(Link *link); bool link_dhcp6_pd_is_enabled(Link *link); int dhcp6_pd_remove(Link *link); -int dhcp6_configure(Link *link); int dhcp6_update_mac(Link *link); int dhcp6_start(Link *link); int dhcp6_request_information(Link *link, int ir); int dhcp6_request_prefix_delegation(Link *link); +int request_process_dhcp6_client(Request *req); +int link_request_dhcp6_client(Link *link); + int link_serialize_dhcp6_client(Link *link, FILE *f); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index b4d5155b4a..041a53e97b 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -650,12 +650,14 @@ static int link_acquire_dynamic_ipv4_conf(Link *link) { if (r < 0) return log_link_warning_errno(link, r, "Failed to start DHCPv4 client: %m"); - } else if (link->ipv4ll) { - log_link_debug(link, "Acquiring IPv4 link-local address"); + log_link_debug(link, "Acquiring DHCPv4 lease."); + } else if (link->ipv4ll) { r = sd_ipv4ll_start(link->ipv4ll); if (r < 0) return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m"); + + log_link_debug(link, "Acquiring IPv4 link-local address."); } if (link->dhcp_server) { @@ -975,8 +977,6 @@ static Link *link_drop(Link *link) { link_drop_from_master(link); - link_unref(set_remove(link->manager->links_requesting_uuid, link)); - (void) unlink(link->state_file); link_clean(link); @@ -1127,13 +1127,13 @@ static int link_configure(Link *link) { if (r < 0) return r; - r = dhcp4_configure(link); + r = link_request_dhcp4_client(link); if (r < 0) - return log_link_warning_errno(link, r, "Failed to configure DHCP4 client: %m"); + return r; - r = dhcp6_configure(link); + r = link_request_dhcp6_client(link); if (r < 0) - return log_link_warning_errno(link, r, "Failed to configure DHCP6 client: %m"); + return r; r = ndisc_configure(link); if (r < 0) @@ -1263,7 +1263,6 @@ static int link_reconfigure_impl(Link *link, bool force) { link_free_carrier_maps(link); link_free_engines(link); link->network = network_unref(link->network); - link_unref(set_remove(link->manager->links_requesting_uuid, link)); /* Then, apply new .network file */ link->network = network_ref(network); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 374d27bef3..c8df49a490 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -103,7 +103,7 @@ static int on_connected(sd_bus_message *message, void *userdata, sd_bus_error *r (void) manager_set_hostname(m, m->dynamic_hostname); if (m->dynamic_timezone) (void) manager_set_timezone(m, m->dynamic_timezone); - if (!set_isempty(m->links_requesting_uuid)) + if (m->product_uuid_requested) (void) manager_request_product_uuid(m); return 0; @@ -460,7 +460,6 @@ Manager* manager_free(Manager *m) { m->dhcp6_pd_prefixes = set_free_with_destructor(m->dhcp6_pd_prefixes, dhcp6_pd_free); m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref); - m->links_requesting_uuid = set_free_with_destructor(m->links_requesting_uuid, link_unref); m->links_by_name = hashmap_free(m->links_by_name); m->links_by_hw_addr = hashmap_free(m->links_by_hw_addr); m->links_by_index = hashmap_free_with_destructor(m->links_by_index, link_unref); diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 4ee48f3468..4e78904538 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -60,7 +60,6 @@ struct Manager { DUID duid_product_uuid; bool has_product_uuid; bool product_uuid_requested; - Set *links_requesting_uuid; char* dynamic_hostname; char* dynamic_timezone; diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index e5e6f5ac7f..bfdae0bc19 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -1396,6 +1396,9 @@ int ndisc_start(Link *link) { if (!link->ndisc || !link->dhcp6_client) return 0; + if (!link_has_carrier(link)) + return 0; + log_link_debug(link, "Discovering IPv6 routers"); return sd_ndisc_start(link->ndisc); diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index 27a16f2951..7f2481997d 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -5,6 +5,8 @@ #include "networkd-bridge-fdb.h" #include "networkd-bridge-mdb.h" #include "networkd-dhcp-server.h" +#include "networkd-dhcp4.h" +#include "networkd-dhcp6.h" #include "networkd-ipv6-proxy-ndp.h" #include "networkd-manager.h" #include "networkd-neighbor.h" @@ -33,6 +35,8 @@ static void request_free_object(RequestType type, void *object) { case REQUEST_TYPE_CREATE_STACKED_NETDEV: break; case REQUEST_TYPE_DHCP_SERVER: + case REQUEST_TYPE_DHCP4_CLIENT: + case REQUEST_TYPE_DHCP6_CLIENT: break; case REQUEST_TYPE_IPV6_PROXY_NDP: free(object); @@ -112,7 +116,9 @@ static void request_hash_func(const Request *req, struct siphash *state) { trivial_hash_func(req->object, state); break; case REQUEST_TYPE_DHCP_SERVER: - /* This type does not have an object. */ + case REQUEST_TYPE_DHCP4_CLIENT: + case REQUEST_TYPE_DHCP6_CLIENT: + /* These types do not have an object. */ break; case REQUEST_TYPE_IPV6_PROXY_NDP: in6_addr_hash_func(req->ipv6_proxy_ndp, state); @@ -170,6 +176,8 @@ static int request_compare_func(const struct Request *a, const struct Request *b case REQUEST_TYPE_CREATE_STACKED_NETDEV: return trivial_compare_func(a->object, b->object); case REQUEST_TYPE_DHCP_SERVER: + case REQUEST_TYPE_DHCP4_CLIENT: + case REQUEST_TYPE_DHCP6_CLIENT: return 0; case REQUEST_TYPE_IPV6_PROXY_NDP: return in6_addr_compare_func(a->ipv6_proxy_ndp, b->ipv6_proxy_ndp); @@ -218,12 +226,16 @@ int link_queue_request( assert(IN_SET(type, REQUEST_TYPE_ACTIVATE_LINK, REQUEST_TYPE_DHCP_SERVER, + REQUEST_TYPE_DHCP4_CLIENT, + REQUEST_TYPE_DHCP6_CLIENT, REQUEST_TYPE_RADV, REQUEST_TYPE_SET_LINK, REQUEST_TYPE_UP_DOWN) || object); assert(IN_SET(type, REQUEST_TYPE_DHCP_SERVER, + REQUEST_TYPE_DHCP4_CLIENT, + REQUEST_TYPE_DHCP6_CLIENT, REQUEST_TYPE_RADV) || netlink_handler); @@ -300,6 +312,12 @@ int manager_process_requests(sd_event_source *s, void *userdata) { case REQUEST_TYPE_DHCP_SERVER: r = request_process_dhcp_server(req); break; + case REQUEST_TYPE_DHCP4_CLIENT: + r = request_process_dhcp4_client(req); + break; + case REQUEST_TYPE_DHCP6_CLIENT: + r = request_process_dhcp6_client(req); + break; case REQUEST_TYPE_IPV6_PROXY_NDP: r = request_process_ipv6_proxy_ndp_address(req); break; diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index 85d2be7367..1fdd07d60a 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -28,6 +28,8 @@ typedef enum RequestType { REQUEST_TYPE_BRIDGE_MDB, REQUEST_TYPE_CREATE_STACKED_NETDEV, REQUEST_TYPE_DHCP_SERVER, + REQUEST_TYPE_DHCP4_CLIENT, + REQUEST_TYPE_DHCP6_CLIENT, REQUEST_TYPE_IPV6_PROXY_NDP, REQUEST_TYPE_NEIGHBOR, REQUEST_TYPE_NEXTHOP,