return duid;
}
-static int duid_set_uuid(DUID *duid, sd_id128_t uuid) {
- assert(duid);
+static int link_configure_and_start_dhcp_delayed(Link *link) {
+ int r;
- if (duid->raw_data_len > 0)
+ assert(link);
+
+ if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return 0;
- if (duid->type != DUID_TYPE_UUID)
- return -EINVAL;
+ if (!link->dhcp_client) {
+ r = dhcp4_configure(link);
+ if (r < 0)
+ return r;
+ }
+
+ if (!link->dhcp6_client) {
+ r = dhcp6_configure(link);
+ if (r < 0)
+ return r;
+ }
- memcpy(&duid->raw_data, &uuid, sizeof(sd_id128_t));
- duid->raw_data_len = sizeof(sd_id128_t);
+ if (!link_has_carrier(link))
+ return 0;
- return 1;
+ 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) {
const sd_bus_error *e;
const void *a;
size_t sz;
- DUID *duid;
Link *link;
int r;
}
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))) {
- link_unref(link);
+ /* To avoid calling GetProductUUID() bus method so frequently, set the flag below
+ * even if the method fails. */
+ manager->has_product_uuid = true;
- r = link_configure(link);
+ 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);
- /* To avoid calling GetProductUUID() bus method so frequently, set the flag below
- * even if the method fails. */
- manager->has_product_uuid = true;
-
return 1;
}
return 0;
}
-static bool dhcp4_requires_uuid(Link *link) {
- const DUID *duid;
-
- assert(link);
-
- if (!link_dhcp4_enabled(link))
- return false;
-
- if (!IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY))
- return false;
-
- duid = link_get_dhcp4_duid(link);
- if (duid->type != DUID_TYPE_UUID || duid->raw_data_len != 0)
- return false;
-
- return true;
-}
-
-static bool dhcp6_requires_uuid(Link *link) {
- const DUID *duid;
-
- assert(link);
-
- if (!link_dhcp6_enabled(link) && !link_ipv6_accept_ra_enabled(link))
- return false;
-
- duid = link_get_dhcp6_duid(link);
- if (duid->type != DUID_TYPE_UUID || duid->raw_data_len != 0)
- return false;
-
- return true;
-}
-
-static bool link_requires_uuid(Link *link) {
- return dhcp4_requires_uuid(link) || dhcp6_requires_uuid(link);
-}
-
-int link_configure_duid(Link *link) {
+int dhcp_configure_duid(Link *link, DUID *duid) {
Manager *m;
- DUID *duid;
int r;
assert(link);
assert(link->manager);
- assert(link->network);
+ assert(duid);
m = link->manager;
- if (!link_requires_uuid(link))
+ if (duid->type != DUID_TYPE_UUID || duid->raw_data_len != 0)
return 1;
if (m->has_product_uuid) {
- if (dhcp4_requires_uuid(link)) {
- duid = link_get_dhcp4_duid(link);
- (void) duid_set_uuid(duid, m->product_uuid);
- }
- if (dhcp6_requires_uuid(link)) {
- duid = link_get_dhcp6_duid(link);
- (void) duid_set_uuid(duid, m->product_uuid);
- }
+ memcpy(&duid->raw_data, &m->product_uuid, sizeof(sd_id128_t));
+ duid->raw_data_len = sizeof(sd_id128_t);
return 1;
}
if (r > 0)
link_ref(link);
- if (dhcp4_requires_uuid(link)) {
- duid = link_get_dhcp4_duid(link);
- r = set_ensure_put(&m->duids_requesting_uuid, NULL, duid);
- if (r < 0)
- return log_oom();
- }
-
- if (dhcp6_requires_uuid(link)) {
- duid = link_get_dhcp6_duid(link);
- r = set_ensure_put(&m->duids_requesting_uuid, NULL, duid);
- if (r < 0)
- return log_oom();
- }
-
return 0;
}
return link_get_duid(link, AF_INET6);
}
-int link_configure_duid(Link *link);
+int dhcp_configure_duid(Link *link, DUID *duid);
int manager_request_product_uuid(Manager *m);
const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
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;
if (link->dhcp_client)
return -EBUSY; /* 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_warning_errno(link, r, "DHCP4 CLIENT: Failed to allocate DHCP4 client: %m");
return 0;
}
+int dhcp4_start(Link *link) {
+ assert(link);
+
+ if (!link->dhcp_client)
+ return 0;
+
+ if (sd_dhcp_client_is_running(link->dhcp_client) > 0)
+ return 0;
+
+ log_link_debug(link, "Acquiring DHCPv4 lease");
+
+ return sd_dhcp_client_start(link->dhcp_client);
+}
+
int config_parse_dhcp_max_attempts(
const char *unit,
const char *filename,
void network_adjust_dhcp4(Network *network);
int dhcp4_configure(Link *link);
int dhcp4_update_mac(Link *link);
+int dhcp4_start(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_acl_ip_address);
return 0;
}
+int dhcp6_start(Link *link) {
+ assert(link);
+
+ if (!link->dhcp6_client)
+ return 0;
+
+ if (!link_dhcp6_enabled(link))
+ return 0;
+
+ if (link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_NO)
+ return 0;
+
+ if (!in6_addr_is_link_local(&link->ipv6ll_address)) {
+ log_link_debug(link, "IPv6 link-local address is not set, delaying to start DHCPv6 client.");
+ return 0;
+ }
+
+ if (sd_dhcp6_client_is_running(link->dhcp6_client) > 0)
+ return 0;
+
+ log_link_debug(link, "Acquiring DHCPv6 lease");
+
+ return dhcp6_request_address(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST);
+}
+
int dhcp6_request_prefix_delegation(Link *link) {
Link *l;
if (link->dhcp6_client)
return -EBUSY;
+ 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();
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_address(Link *link, int ir);
int dhcp6_request_prefix_delegation(Link *link);
assert(link);
- if (link->ndisc) {
- log_link_debug(link, "Discovering IPv6 routers");
-
- r = sd_ndisc_start(link->ndisc);
- if (r < 0 && r != -EBUSY)
- return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
- }
-
if (link->radv) {
assert(link->radv);
assert(in6_addr_is_link_local(&link->ipv6ll_address));
return log_link_warning_errno(link, r, "Could not start IPv6 Router Advertisement: %m");
}
- if (link_dhcp6_enabled(link) && IN_SET(link->network->dhcp6_without_ra,
- DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST,
- DHCP6_CLIENT_START_MODE_SOLICIT)) {
- assert(link->dhcp6_client);
- assert(in6_addr_is_link_local(&link->ipv6ll_address));
+ r = ndisc_start(link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m");
- r = dhcp6_request_address(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST);
- 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");
- }
+ r = dhcp6_start(link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to start DHCPv6 client: %m");
r = dhcp6_request_prefix_delegation(link);
if (r < 0)
assert(link->manager->event);
if (link->dhcp_client) {
- log_link_debug(link, "Acquiring DHCPv4 lease");
-
- r = sd_dhcp_client_start(link->dhcp_client);
+ r = dhcp4_start(link);
if (r < 0)
- return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m");
+ 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");
link_set_state(link, LINK_STATE_INITIALIZED);
link->activated = false;
- /* 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;
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;
m->links_requesting_uuid = set_free_with_destructor(m->links_requesting_uuid, link_unref);
m->links = hashmap_free_with_destructor(m->links, link_unref);
- m->duids_requesting_uuid = set_free(m->duids_requesting_uuid);
m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref);
m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
bool has_product_uuid;
bool product_uuid_requested;
Set *links_requesting_uuid;
- Set *duids_requesting_uuid;
char* dynamic_hostname;
char* dynamic_timezone;
return 0;
}
+int ndisc_start(Link *link) {
+ assert(link);
+
+ if (!link->ndisc || !link->dhcp6_client)
+ return 0;
+
+ log_link_debug(link, "Discovering IPv6 routers");
+
+ return sd_ndisc_start(link->ndisc);
+}
+
void ndisc_vacuum(Link *link) {
NDiscRDNSS *r;
NDiscDNSSL *d;
void network_adjust_ipv6_accept_ra(Network *network);
int ndisc_configure(Link *link);
+int ndisc_start(Link *link);
void ndisc_vacuum(Link *link);
void ndisc_flush(Link *link);
ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free);
- if (network->manager) {
- set_remove(network->manager->duids_requesting_uuid, &network->dhcp_duid);
- set_remove(network->manager->duids_requesting_uuid, &network->dhcp6_duid);
- }
-
free(network->name);
free(network->dhcp_server_timezone);