network: request product UUID when DUIDType=uuid but DUIDRawData= is not set
Closes #9228.
This commit is contained in:
parent
fff1f40c9b
commit
27dfc98275
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "alloc-util.h"
|
||||
#include "bus-util.h"
|
||||
#include "dhcp-identifier.h"
|
||||
#include "dhcp-lease-internal.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
|
@ -546,8 +547,10 @@ static void link_free(Link *link) {
|
|||
sd_ndisc_unref(link->ndisc);
|
||||
sd_radv_unref(link->radv);
|
||||
|
||||
if (link->manager)
|
||||
if (link->manager) {
|
||||
hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
|
||||
set_remove(link->manager->links_requesting_uuid, link);
|
||||
}
|
||||
|
||||
free(link->ifname);
|
||||
|
||||
|
@ -2891,6 +2894,134 @@ static int link_configure(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. Fallback to use application specific machine 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. Fallback to use application specific machine 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. Fallback to use application specific machine 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(sd_netlink *rtnl, sd_netlink_message *m,
|
||||
void *userdata) {
|
||||
_cleanup_(link_unrefp) Link *link = userdata;
|
||||
|
@ -2946,6 +3077,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;
|
||||
|
|
|
@ -125,6 +125,7 @@ typedef struct Link {
|
|||
} Link;
|
||||
|
||||
DUID *link_get_duid(Link *link);
|
||||
int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error);
|
||||
|
||||
Link *link_unref(Link *link);
|
||||
Link *link_ref(Link *link);
|
||||
|
|
|
@ -114,6 +114,8 @@ 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 (m->links_requesting_uuid)
|
||||
(void) manager_request_product_uuid(m, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1459,6 +1461,9 @@ void manager_free(Manager *m) {
|
|||
link_unref(link);
|
||||
hashmap_free(m->links);
|
||||
|
||||
set_free(m->links_requesting_uuid);
|
||||
set_free(m->duids_requesting_uuid);
|
||||
|
||||
hashmap_free(m->networks_by_name);
|
||||
|
||||
while ((netdev = hashmap_first(m->netdevs)))
|
||||
|
@ -1831,3 +1836,57 @@ 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_allocated(&m->links_requesting_uuid, NULL);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = set_ensure_allocated(&m->duids_requesting_uuid, NULL);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "sd-bus.h"
|
||||
#include "sd-event.h"
|
||||
#include "sd-id128.h"
|
||||
#include "sd-netlink.h"
|
||||
#include "sd-resolve.h"
|
||||
#include "udev.h"
|
||||
|
@ -48,6 +49,11 @@ struct Manager {
|
|||
usec_t network_dirs_ts_usec;
|
||||
|
||||
DUID duid;
|
||||
sd_id128_t product_uuid;
|
||||
bool has_product_uuid;
|
||||
Set *links_requesting_uuid;
|
||||
Set *duids_requesting_uuid;
|
||||
|
||||
char* dynamic_hostname;
|
||||
char* dynamic_timezone;
|
||||
|
||||
|
@ -85,6 +91,7 @@ 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);
|
||||
|
||||
Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr);
|
||||
int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link);
|
||||
|
|
|
@ -415,6 +415,9 @@ void network_free(Network *network) {
|
|||
|
||||
if (network->manager->networks_by_name)
|
||||
hashmap_remove(network->manager->networks_by_name, network->name);
|
||||
|
||||
if (network->manager->duids_requesting_uuid)
|
||||
set_remove(network->manager->duids_requesting_uuid, &network->duid);
|
||||
}
|
||||
|
||||
free(network->name);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[Allow systemd-networkd to set timezone and transient hostname]
|
||||
Identity=unix-user:systemd-network
|
||||
Action=org.freedesktop.hostname1.set-hostname;org.freedesktop.timedate1.set-timezone;
|
||||
Action=org.freedesktop.hostname1.set-hostname;org.freedesktop.hostname1.get-product-uuid;org.freedesktop.timedate1.set-timezone;
|
||||
ResultAny=yes
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// Allow systemd-networkd to set timezone and transient hostname
|
||||
// Allow systemd-networkd to set timezone, get product UUID,
|
||||
// and transient hostname
|
||||
polkit.addRule(function(action, subject) {
|
||||
if ((action.id == "org.freedesktop.hostname1.set-hostname" ||
|
||||
action.id == "org.freedesktop.hostname1.get-product-uuid" ||
|
||||
action.id == "org.freedesktop.timedate1.set-timezone") &&
|
||||
subject.user == "systemd-network") {
|
||||
return polkit.Result.YES;
|
||||
|
|
Loading…
Reference in New Issue