diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index 3ea3a5a7ba..d3053d0354 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -9,6 +9,7 @@ #include "in-addr-util.h" #include "networkd-dhcp-common.h" #include "networkd-link.h" +#include "networkd-manager.h" #include "networkd-network.h" #include "parse-util.h" #include "socket-util.h" @@ -37,6 +38,194 @@ bool link_dhcp_enabled(Link *link, int family) { return link->network->dhcp & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6); } +DUID* link_get_duid(Link *link) { + if (link->network->duid.type != _DUID_TYPE_INVALID) + return &link->network->duid; + else + return &link->manager->duid; +} + +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; +} + +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; + 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))) { + link_unref(link); + + r = link_configure(link); + if (r < 0) + link_enter_failed(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; +} + +int manager_request_product_uuid(Manager *m, Link *link) { + int r; + + assert(m); + + if (m->has_product_uuid) + return 0; + + log_debug("Requesting product UUID"); + + if (link) { + DUID *duid; + + assert_se(duid = link_get_duid(link)); + + r = set_ensure_put(&m->links_requesting_uuid, NULL, link); + if (r < 0) + return log_oom(); + if (r > 0) + link_ref(link); + + r = set_ensure_put(&m->duids_requesting_uuid, NULL, duid); + if (r < 0) + return log_oom(); + } + + if (!m->bus || sd_bus_is_ready(m->bus) <= 0) { + log_debug("Not connected to system bus, requesting product UUID later."); + return 0; + } + + r = sd_bus_call_method_async( + m->bus, + NULL, + "org.freedesktop.hostname1", + "/org/freedesktop/hostname1", + "org.freedesktop.hostname1", + "GetProductUUID", + get_product_uuid_handler, + m, + "b", + false); + if (r < 0) + return log_warning_errno(r, "Failed to get product UUID: %m"); + + return 0; +} + +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; +} + +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(); + if (r > 0) + link_ref(link); + + r = set_put(m->duids_requesting_uuid, duid); + if (r < 0) + return log_oom(); + } + + return 0; +} + int config_parse_dhcp( const char* unit, const char *filename, diff --git a/src/network/networkd-dhcp-common.h b/src/network/networkd-dhcp-common.h index 1032ec2bda..e3982a7ef1 100644 --- a/src/network/networkd-dhcp-common.h +++ b/src/network/networkd-dhcp-common.h @@ -8,6 +8,7 @@ #define DHCP_ROUTE_METRIC 1024 typedef struct Link Link; +typedef struct Manager Manager; typedef enum DHCPUseDomains { DHCP_USE_DOMAINS_NO, @@ -45,6 +46,10 @@ static inline bool link_dhcp6_enabled(Link *link) { return link_dhcp_enabled(link, AF_INET6); } +DUID* link_get_duid(Link *link); +int link_configure_duid(Link *link); +int manager_request_product_uuid(Manager *m, Link *link); + const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_; DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 0f48402cb6..5835f76cef 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -54,13 +54,6 @@ #include "util.h" #include "vrf.h" -DUID* link_get_duid(Link *link) { - if (link->network->duid.type != _DUID_TYPE_INVALID) - return &link->network->duid; - else - return &link->manager->duid; -} - bool link_ipv4ll_enabled(Link *link, AddressFamily mask) { assert(link); assert((mask & ~(ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) == 0); @@ -2302,7 +2295,7 @@ static int link_configure_sr_iov(Link *link) { return 0; } -static int link_configure(Link *link) { +int link_configure(Link *link) { int r; assert(link); @@ -2468,139 +2461,6 @@ static int link_configure_continue(Link *link) { return link_enter_join_netdev(link); } -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))) { - link_unref(link); - - r = link_configure(link); - if (r < 0) - link_enter_failed(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; -} - -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(); - if (r > 0) - link_ref(link); - - r = set_put(m->duids_requesting_uuid, duid); - if (r < 0) - return log_oom(); - } - - return 0; -} - static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool force) { Network *network; int r; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 6a4ef4f6bf..43451ee2de 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -191,9 +191,6 @@ typedef struct Link { typedef int (*link_netlink_message_handler_t)(sd_netlink*, sd_netlink_message*, Link*); -DUID *link_get_duid(Link *link); -int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error); - void link_ntp_settings_clear(Link *link); void link_dns_settings_clear(Link *link); Link *link_unref(Link *link); @@ -244,6 +241,7 @@ int link_stop_clients(Link *link, bool may_keep_dhcp); const char* link_state_to_string(LinkState s) _const_; LinkState link_state_from_string(const char *s) _pure_; +int link_configure(Link *link); int link_reconfigure(Link *link, bool force); int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 524dbedb1e..e8d270987d 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -1244,51 +1244,3 @@ int manager_set_timezone(Manager *m, const char *tz) { return 0; } - -int manager_request_product_uuid(Manager *m, Link *link) { - int r; - - assert(m); - - if (m->has_product_uuid) - return 0; - - log_debug("Requesting product UUID"); - - if (link) { - DUID *duid; - - assert_se(duid = link_get_duid(link)); - - r = set_ensure_put(&m->links_requesting_uuid, NULL, link); - if (r < 0) - return log_oom(); - if (r > 0) - link_ref(link); - - r = set_ensure_put(&m->duids_requesting_uuid, NULL, duid); - if (r < 0) - return log_oom(); - } - - if (!m->bus || sd_bus_is_ready(m->bus) <= 0) { - log_debug("Not connected to system bus, requesting product UUID later."); - return 0; - } - - r = sd_bus_call_method_async( - m->bus, - NULL, - "org.freedesktop.hostname1", - "/org/freedesktop/hostname1", - "org.freedesktop.hostname1", - "GetProductUUID", - get_product_uuid_handler, - m, - "b", - false); - if (r < 0) - return log_warning_errno(r, "Failed to get product UUID: %m"); - - return 0; -} diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 2e250f1509..142a6eb358 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -89,6 +89,5 @@ Link* manager_find_uplink(Manager *m, Link *exclude); int manager_set_hostname(Manager *m, const char *hostname); int manager_set_timezone(Manager *m, const char *timezone); -int manager_request_product_uuid(Manager *m, Link *link); DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);