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,
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;
}
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;
}
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;
return r == true;
}
-int dhcp4_configure(Link *link) {
+static int dhcp4_configure(Link *link) {
sd_dhcp_option *send_option;
void *request_options;
int r;
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");
}
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(
#include "conf-parser.h"
typedef struct Link Link;
+typedef struct Network Network;
+typedef struct Request Request;
typedef enum DHCPClientIdentifier {
DHCP_CLIENT_ID_MAC,
} 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);
}
int dhcp6_start(Link *link) {
+ int r;
+
assert(link);
if (!link->dhcp6_client)
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;
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) {
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;
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();
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;
/* 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 {
} 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 */
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);
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) {
link_drop_from_master(link);
- link_unref(set_remove(link->manager->links_requesting_uuid, link));
-
(void) unlink(link->state_file);
link_clean(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)
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);
(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;
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);
DUID duid_product_uuid;
bool has_product_uuid;
bool product_uuid_requested;
- Set *links_requesting_uuid;
char* dynamic_hostname;
char* dynamic_timezone;
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);
#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"
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);
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);
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);
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);
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;
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,