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 "alloc-util.h"
|
||||||
#include "bus-util.h"
|
#include "bus-util.h"
|
||||||
|
#include "dhcp-identifier.h"
|
||||||
#include "dhcp-lease-internal.h"
|
#include "dhcp-lease-internal.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
|
@ -546,8 +547,10 @@ static void link_free(Link *link) {
|
||||||
sd_ndisc_unref(link->ndisc);
|
sd_ndisc_unref(link->ndisc);
|
||||||
sd_radv_unref(link->radv);
|
sd_radv_unref(link->radv);
|
||||||
|
|
||||||
if (link->manager)
|
if (link->manager) {
|
||||||
hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
|
hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
|
||||||
|
set_remove(link->manager->links_requesting_uuid, link);
|
||||||
|
}
|
||||||
|
|
||||||
free(link->ifname);
|
free(link->ifname);
|
||||||
|
|
||||||
|
@ -2891,6 +2894,134 @@ static int link_configure(Link *link) {
|
||||||
return link_enter_join_netdev(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,
|
static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
_cleanup_(link_unrefp) Link *link = 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)
|
if (r < 0)
|
||||||
return r;
|
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);
|
r = link_configure(link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -125,6 +125,7 @@ typedef struct Link {
|
||||||
} Link;
|
} Link;
|
||||||
|
|
||||||
DUID *link_get_duid(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_unref(Link *link);
|
||||||
Link *link_ref(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);
|
(void) manager_set_hostname(m, m->dynamic_hostname);
|
||||||
if (m->dynamic_timezone)
|
if (m->dynamic_timezone)
|
||||||
(void) manager_set_timezone(m, 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1459,6 +1461,9 @@ void manager_free(Manager *m) {
|
||||||
link_unref(link);
|
link_unref(link);
|
||||||
hashmap_free(m->links);
|
hashmap_free(m->links);
|
||||||
|
|
||||||
|
set_free(m->links_requesting_uuid);
|
||||||
|
set_free(m->duids_requesting_uuid);
|
||||||
|
|
||||||
hashmap_free(m->networks_by_name);
|
hashmap_free(m->networks_by_name);
|
||||||
|
|
||||||
while ((netdev = hashmap_first(m->netdevs)))
|
while ((netdev = hashmap_first(m->netdevs)))
|
||||||
|
@ -1831,3 +1836,57 @@ int manager_set_timezone(Manager *m, const char *tz) {
|
||||||
|
|
||||||
return 0;
|
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-bus.h"
|
||||||
#include "sd-event.h"
|
#include "sd-event.h"
|
||||||
|
#include "sd-id128.h"
|
||||||
#include "sd-netlink.h"
|
#include "sd-netlink.h"
|
||||||
#include "sd-resolve.h"
|
#include "sd-resolve.h"
|
||||||
#include "udev.h"
|
#include "udev.h"
|
||||||
|
@ -48,6 +49,11 @@ struct Manager {
|
||||||
usec_t network_dirs_ts_usec;
|
usec_t network_dirs_ts_usec;
|
||||||
|
|
||||||
DUID duid;
|
DUID duid;
|
||||||
|
sd_id128_t product_uuid;
|
||||||
|
bool has_product_uuid;
|
||||||
|
Set *links_requesting_uuid;
|
||||||
|
Set *duids_requesting_uuid;
|
||||||
|
|
||||||
char* dynamic_hostname;
|
char* dynamic_hostname;
|
||||||
char* dynamic_timezone;
|
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_hostname(Manager *m, const char *hostname);
|
||||||
int manager_set_timezone(Manager *m, const char *timezone);
|
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);
|
Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr);
|
||||||
int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link);
|
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)
|
if (network->manager->networks_by_name)
|
||||||
hashmap_remove(network->manager->networks_by_name, network->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);
|
free(network->name);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[Allow systemd-networkd to set timezone and transient hostname]
|
[Allow systemd-networkd to set timezone and transient hostname]
|
||||||
Identity=unix-user:systemd-network
|
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
|
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) {
|
polkit.addRule(function(action, subject) {
|
||||||
if ((action.id == "org.freedesktop.hostname1.set-hostname" ||
|
if ((action.id == "org.freedesktop.hostname1.set-hostname" ||
|
||||||
|
action.id == "org.freedesktop.hostname1.get-product-uuid" ||
|
||||||
action.id == "org.freedesktop.timedate1.set-timezone") &&
|
action.id == "org.freedesktop.timedate1.set-timezone") &&
|
||||||
subject.user == "systemd-network") {
|
subject.user == "systemd-network") {
|
||||||
return polkit.Result.YES;
|
return polkit.Result.YES;
|
||||||
|
|
Loading…
Reference in a new issue