summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2018-08-23 11:11:13 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2018-08-23 11:11:13 +0200
commitc07fe6d0df3e433b579c9cb8b8ea9cfb2fb62173 (patch)
tree4759c1c46cc17eb8b175224ad967ad83cc50b06b /src/network
parent708c425d0aeda659d430f437163587babb96b1bb (diff)
parent8fa266c2a4effa93c253e5dc499edabd52e8b4bb (diff)
downloadsystemd-c07fe6d0df3e433b579c9cb8b8ea9cfb2fb62173.tar.gz
Merge pull request #9406 from yuwata/rfe-9228
Trivial conflict solved in merge and include net/if_arp.h added.
Diffstat (limited to 'src/network')
-rw-r--r--src/network/networkd-conf.c69
-rw-r--r--src/network/networkd-dhcp4.c97
-rw-r--r--src/network/networkd-dhcp6.c13
-rw-r--r--src/network/networkd-gperf.gperf2
-rw-r--r--src/network/networkd-link.c186
-rw-r--r--src/network/networkd-link.h5
-rw-r--r--src/network/networkd-manager.c59
-rw-r--r--src/network/networkd-manager.h14
-rw-r--r--src/network/networkd-network-gperf.gperf2
-rw-r--r--src/network/networkd-network.c3
-rw-r--r--src/network/networkd-network.h1
-rw-r--r--src/network/systemd-networkd.pkla2
-rw-r--r--src/network/systemd-networkd.rules4
-rw-r--r--src/network/test-networkd-conf.c27
14 files changed, 381 insertions, 103 deletions
diff --git a/src/network/networkd-conf.c b/src/network/networkd-conf.c
index 05bbc0b3e9..334ffc3c57 100644
--- a/src/network/networkd-conf.c
+++ b/src/network/networkd-conf.c
@@ -31,7 +31,74 @@ static const char* const duid_type_table[_DUID_TYPE_MAX] = {
[DUID_TYPE_UUID] = "uuid",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(duid_type, DUIDType);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_duid_type, duid_type, DUIDType, "Failed to parse DUID type");
+
+int config_parse_duid_type(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_free_ char *type_string = NULL;
+ const char *p = rvalue;
+ DUID *duid = data;
+ DUIDType type;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(duid);
+
+ r = extract_first_word(&p, &type_string, ":", 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to extract DUID type from '%s', ignoring.", rvalue);
+ return 0;
+ }
+
+ type = duid_type_from_string(type_string);
+ if (type < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to parse DUID type '%s', ignoring.", type_string);
+ return 0;
+ }
+
+ if (!isempty(p)) {
+ usec_t u;
+
+ if (type != DUID_TYPE_LLT) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ r = parse_timestamp(p, &u);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse timestamp, ignoring: %s", p);
+ return 0;
+ }
+
+ duid->llt_time = u;
+ }
+
+ duid->type = type;
+
+ return 0;
+}
int config_parse_duid_rawdata(
const char *unit,
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 7798844e03..18867d9401 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -660,6 +660,63 @@ int dhcp4_set_promote_secondaries(Link *link) {
return 0;
}
+int dhcp4_set_client_identifier(Link *link) {
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(link->dhcp_client);
+
+ switch (link->network->dhcp_client_identifier) {
+ case DHCP_CLIENT_ID_DUID: {
+ /* If configured, apply user specified DUID and IAID */
+ const DUID *duid = link_get_duid(link);
+
+ if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
+ r = sd_dhcp_client_set_iaid_duid_llt(link->dhcp_client,
+ link->network->iaid,
+ duid->llt_time);
+ else
+ r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
+ link->network->iaid,
+ duid->type,
+ duid->raw_data_len > 0 ? duid->raw_data : NULL,
+ duid->raw_data_len);
+ if (r < 0)
+ return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set IAID+DUID: %m");
+ break;
+ }
+ case DHCP_CLIENT_ID_DUID_ONLY: {
+ /* If configured, apply user specified DUID */
+ const DUID *duid = link_get_duid(link);
+
+ if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
+ r = sd_dhcp_client_set_duid_llt(link->dhcp_client,
+ duid->llt_time);
+ else
+ r = sd_dhcp_client_set_duid(link->dhcp_client,
+ duid->type,
+ duid->raw_data_len > 0 ? duid->raw_data : NULL,
+ duid->raw_data_len);
+ if (r < 0)
+ return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set DUID: %m");
+ break;
+ }
+ case DHCP_CLIENT_ID_MAC:
+ r = sd_dhcp_client_set_client_id(link->dhcp_client,
+ ARPHRD_ETHER,
+ (const uint8_t *) &link->mac,
+ sizeof(link->mac));
+ if (r < 0)
+ return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set client ID: %m");
+ break;
+ default:
+ assert_not_reached("Unknown client identifier type.");
+ }
+
+ return 0;
+}
+
int dhcp4_configure(Link *link) {
int r;
@@ -763,43 +820,5 @@ int dhcp4_configure(Link *link) {
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set listen port: %m");
}
- switch (link->network->dhcp_client_identifier) {
- case DHCP_CLIENT_ID_DUID: {
- /* If configured, apply user specified DUID and/or IAID */
- const DUID *duid = link_duid(link);
-
- r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
- link->network->iaid,
- duid->type,
- duid->raw_data_len > 0 ? duid->raw_data : NULL,
- duid->raw_data_len);
- if (r < 0)
- return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set DUID: %m");
- break;
- }
- case DHCP_CLIENT_ID_DUID_ONLY: {
- /* If configured, apply user specified DUID */
- const DUID *duid = link_duid(link);
-
- r = sd_dhcp_client_set_duid(link->dhcp_client,
- duid->type,
- duid->raw_data_len > 0 ? duid->raw_data : NULL,
- duid->raw_data_len);
- if (r < 0)
- return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set DUID: %m");
- break;
- }
- case DHCP_CLIENT_ID_MAC:
- r = sd_dhcp_client_set_client_id(link->dhcp_client,
- ARPHRD_ETHER,
- (const uint8_t *) &link->mac,
- sizeof(link->mac));
- if (r < 0)
- return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set client ID: %m");
- break;
- default:
- assert_not_reached("Unknown client identifier type.");
- }
-
- return 0;
+ return dhcp4_set_client_identifier(link);
}
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index 0ec4deb716..fa6e18cd2c 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -494,11 +494,14 @@ int dhcp6_configure(Link *link) {
if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set IAID: %m");
- duid = link_duid(link);
- r = sd_dhcp6_client_set_duid(client,
- duid->type,
- duid->raw_data_len > 0 ? duid->raw_data : NULL,
- duid->raw_data_len);
+ duid = link_get_duid(link);
+ if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
+ r = sd_dhcp6_client_set_duid_llt(client, duid->llt_time);
+ else
+ r = sd_dhcp6_client_set_duid(client,
+ duid->type,
+ duid->raw_data_len > 0 ? duid->raw_data : NULL,
+ duid->raw_data_len);
if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set DUID: %m");
diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf
index 54161446bb..cc88fc0add 100644
--- a/src/network/networkd-gperf.gperf
+++ b/src/network/networkd-gperf.gperf
@@ -18,5 +18,5 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
-DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Manager, duid.type)
+DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Manager, duid)
DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, duid)
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 96e1119567..ab8126781d 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -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"
@@ -27,6 +28,13 @@
#include "util.h"
#include "virt.h"
+DUID* link_get_duid(Link *link) {
+ if (link->network->duid.type != _DUID_TYPE_INVALID)
+ return &link->network->duid;
+ else
+ return &link->manager->duid;
+}
+
static bool link_dhcp6_enabled(Link *link) {
assert(link);
@@ -539,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);
@@ -2884,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;
@@ -2939,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;
@@ -3433,45 +3577,13 @@ int link_update(Link *link, sd_netlink_message *m) {
if (r < 0)
return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
- switch (link->network->dhcp_client_identifier) {
- case DHCP_CLIENT_ID_DUID: {
- const DUID *duid = link_duid(link);
-
- r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
- link->network->iaid,
- duid->type,
- duid->raw_data_len > 0 ? duid->raw_data : NULL,
- duid->raw_data_len);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not update DUID/IAID in DHCP client: %m");
- break;
- }
- case DHCP_CLIENT_ID_DUID_ONLY: {
- const DUID *duid = link_duid(link);
-
- r = sd_dhcp_client_set_duid(link->dhcp_client,
- duid->type,
- duid->raw_data_len > 0 ? duid->raw_data : NULL,
- duid->raw_data_len);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not update DUID in DHCP client: %m");
- break;
- }
- case DHCP_CLIENT_ID_MAC:
- r = sd_dhcp_client_set_client_id(link->dhcp_client,
- ARPHRD_ETHER,
- (const uint8_t *)&link->mac,
- sizeof(link->mac));
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not update MAC client id in DHCP client: %m");
- break;
- default:
- assert_not_reached("Unknown client identifier type.");
- }
+ r = dhcp4_set_client_identifier(link);
+ if (r < 0)
+ return r;
}
if (link->dhcp6_client) {
- const DUID* duid = link_duid(link);
+ const DUID* duid = link_get_duid(link);
r = sd_dhcp6_client_set_mac(link->dhcp6_client,
(const uint8_t *) &link->mac,
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index b6f8ce1385..912952e651 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -44,6 +44,7 @@ typedef enum LinkOperationalState {
typedef struct Manager Manager;
typedef struct Network Network;
typedef struct Address Address;
+typedef struct DUID DUID;
typedef struct Link {
Manager *manager;
@@ -124,6 +125,9 @@ typedef struct Link {
Hashmap *bound_to_links;
} 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);
int link_get(Manager *m, int ifindex, Link **ret);
@@ -157,6 +161,7 @@ int link_set_mtu(Link *link, uint32_t mtu);
int ipv4ll_configure(Link *link);
int dhcp4_configure(Link *link);
+int dhcp4_set_client_identifier(Link *link);
int dhcp4_set_promote_secondaries(Link *link);
int dhcp6_configure(Link *link);
int dhcp6_request_address(Link *link, int ir);
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 7462a62215..27a4f6db61 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -113,6 +113,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;
}
@@ -1457,6 +1459,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)))
@@ -1828,3 +1833,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;
+}
diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h
index edaafb6a06..fbfcdad304 100644
--- a/src/network/networkd-manager.h
+++ b/src/network/networkd-manager.h
@@ -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 "libudev.h"
@@ -47,6 +48,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;
@@ -55,13 +61,6 @@ struct Manager {
Set *rules_saved;
};
-static inline const DUID* link_duid(const Link *link) {
- if (link->network->duid.type != _DUID_TYPE_INVALID)
- return &link->network->duid;
- else
- return &link->manager->duid;
-}
-
extern const sd_bus_vtable manager_vtable[];
int manager_new(Manager **ret);
@@ -91,6 +90,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);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 6ad5257f79..357231152e 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -130,7 +130,7 @@ DHCP.RequestBroadcast, config_parse_bool,
DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
DHCP.UserClass, config_parse_dhcp_user_class, 0, offsetof(Network, dhcp_user_class)
-DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid.type)
+DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid)
DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
DHCP.RouteTable, config_parse_dhcp_route_table, 0, 0
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 10c5cb4163..c7d162de67 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -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);
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index efb9efc560..6bfd8d5dd5 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -70,6 +70,7 @@ typedef struct DUID {
uint8_t raw_data_len;
uint8_t raw_data[MAX_DUID_LEN];
+ usec_t llt_time;
} DUID;
typedef enum RADVPrefixDelegation {
diff --git a/src/network/systemd-networkd.pkla b/src/network/systemd-networkd.pkla
index fb257d933b..4d1bb4585e 100644
--- a/src/network/systemd-networkd.pkla
+++ b/src/network/systemd-networkd.pkla
@@ -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
diff --git a/src/network/systemd-networkd.rules b/src/network/systemd-networkd.rules
index 2e4bc42bfb..b9077c1ea2 100644
--- a/src/network/systemd-networkd.rules
+++ b/src/network/systemd-networkd.rules
@@ -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;
diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c
index fc1646f4bf..d05680d7e1 100644
--- a/src/network/test-networkd-conf.c
+++ b/src/network/test-networkd-conf.c
@@ -11,23 +11,30 @@
#include "networkd-conf.h"
#include "networkd-network.h"
-static void test_config_parse_duid_type_one(const char *rvalue, int ret, DUIDType expected) {
- DUIDType actual = 0;
+static void test_config_parse_duid_type_one(const char *rvalue, int ret, DUIDType expected, usec_t expected_time) {
+ DUID actual = {};
int r;
r = config_parse_duid_type("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &actual, NULL);
- log_info_errno(r, "\"%s\" → %d (%m)", rvalue, actual);
+ log_info_errno(r, "\"%s\" → %d (%m)", rvalue, actual.type);
assert_se(r == ret);
- assert_se(expected == actual);
+ assert_se(expected == actual.type);
+ if (expected == DUID_TYPE_LLT)
+ assert_se(expected_time == actual.llt_time);
}
static void test_config_parse_duid_type(void) {
- test_config_parse_duid_type_one("", 0, 0);
- test_config_parse_duid_type_one("link-layer-time", 0, DUID_TYPE_LLT);
- test_config_parse_duid_type_one("vendor", 0, DUID_TYPE_EN);
- test_config_parse_duid_type_one("link-layer", 0, DUID_TYPE_LL);
- test_config_parse_duid_type_one("uuid", 0, DUID_TYPE_UUID);
- test_config_parse_duid_type_one("foo", 0, 0);
+ test_config_parse_duid_type_one("", 0, 0, 0);
+ test_config_parse_duid_type_one("link-layer-time", 0, DUID_TYPE_LLT, 0);
+ test_config_parse_duid_type_one("link-layer-time:2000-01-01 00:00:00 UTC", 0, DUID_TYPE_LLT, (usec_t) 946684800000000);
+ test_config_parse_duid_type_one("vendor", 0, DUID_TYPE_EN, 0);
+ test_config_parse_duid_type_one("vendor:2000-01-01 00:00:00 UTC", 0, 0, 0);
+ test_config_parse_duid_type_one("link-layer", 0, DUID_TYPE_LL, 0);
+ test_config_parse_duid_type_one("link-layer:2000-01-01 00:00:00 UTC", 0, 0, 0);
+ test_config_parse_duid_type_one("uuid", 0, DUID_TYPE_UUID, 0);
+ test_config_parse_duid_type_one("uuid:2000-01-01 00:00:00 UTC", 0, 0, 0);
+ test_config_parse_duid_type_one("foo", 0, 0, 0);
+ test_config_parse_duid_type_one("foo:2000-01-01 00:00:00 UTC", 0, 0, 0);
}
static void test_config_parse_duid_rawdata_one(const char *rvalue, int ret, const DUID* expected) {