Merge pull request #9406 from yuwata/rfe-9228
Trivial conflict solved in merge and include net/if_arp.h added.
This commit is contained in:
commit
c07fe6d0df
|
@ -67,7 +67,7 @@
|
|||
<para>The following values are understood:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>vendor</option> </term>
|
||||
<term><option>vendor</option></term>
|
||||
<listitem><para>If <literal>DUIDType=vendor</literal>, then the DUID value will be generated using
|
||||
<literal>43793</literal> as the vendor identifier (systemd) and hashed contents of
|
||||
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
|
@ -76,11 +76,23 @@
|
|||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>link-layer-time</option> </term>
|
||||
<term><option>link-layer</option> </term>
|
||||
<term><option>uuid</option> </term>
|
||||
<listitem><para>Those values are parsed and can be used to set the DUID type
|
||||
field, but DUID contents must be provided using <varname>DUIDRawData=</varname>.
|
||||
<term><option>uuid</option></term>
|
||||
<listitem><para>If <literal>DUIDType=uuid</literal>, and <varname>DUIDRawData=</varname> is not set,
|
||||
then the product UUID is used as a DUID value. If a system does not have valid product UUID, then
|
||||
an application-specific
|
||||
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
is used as a DUID value. About the application-specific machine ID, see
|
||||
<citerefentry><refentrytitle>sd_id128_get_machine_app_specific</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>link-layer-time[:<replaceable>TIME</replaceable>]</option></term>
|
||||
<term><option>link-layer</option></term>
|
||||
<listitem><para>If <literal>link-layer-time</literal> or <literal>link-layer</literal> is specified,
|
||||
then the MAC address of the interface is used as a DUID value. The value <literal>link-layer-time</literal>
|
||||
can take additional time value after a colon, e.g. <literal>link-layer-time:2018-01-23 12:34:56 UTC</literal>.
|
||||
The default time value is <literal>2000-01-01 00:00:00 UTC</literal>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
@ -96,8 +108,9 @@
|
|||
byte separated by <literal>:</literal>. The DUID that is sent is composed of the DUID type specified by
|
||||
<varname>DUIDType=</varname> and the value configured here.</para>
|
||||
|
||||
<para>The DUID value specified here overrides the DUID that systemd-networkd generates using the machine-id
|
||||
from the <filename>/etc/machine-id</filename> file. To configure DUID per-network, see
|
||||
<para>The DUID value specified here overrides the DUID that
|
||||
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
generates from the machine ID. To configure DUID per-network, see
|
||||
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
The configured DHCP DUID should conform to the specification in
|
||||
<ulink url="http://tools.ietf.org/html/rfc3315#section-9">RFC 3315</ulink>,
|
||||
|
@ -125,7 +138,9 @@ DUIDRawData=00:00:ab:11:f9:2a:c2:77:29:f9:5c:00</programlisting>
|
|||
<para>
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_id128_get_machine_app_specific</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bus-common-errors.h"
|
||||
#include "bus-util.h"
|
||||
#include "def.h"
|
||||
#include "env-util.h"
|
||||
#include "fileio-label.h"
|
||||
#include "hostname-util.h"
|
||||
#include "id128-util.h"
|
||||
#include "os-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
|
@ -43,6 +45,8 @@ enum {
|
|||
typedef struct Context {
|
||||
char *data[_PROP_MAX];
|
||||
Hashmap *polkit_registry;
|
||||
sd_id128_t uuid;
|
||||
bool has_uuid;
|
||||
} Context;
|
||||
|
||||
static void context_reset(Context *c) {
|
||||
|
@ -103,6 +107,11 @@ static int context_read_data(Context *c) {
|
|||
if (r < 0 && r != -ENOENT)
|
||||
return r;
|
||||
|
||||
r = id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, &c->uuid);
|
||||
if (r < 0)
|
||||
log_info_errno(r, "Failed to read product UUID, ignoring: %m");
|
||||
c->has_uuid = (r >= 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -598,6 +607,46 @@ static int method_set_location(sd_bus_message *m, void *userdata, sd_bus_error *
|
|||
return set_machine_info(userdata, m, PROP_LOCATION, method_set_location, error);
|
||||
}
|
||||
|
||||
static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
Context *c = userdata;
|
||||
int interactive, r;
|
||||
|
||||
assert(m);
|
||||
assert(c);
|
||||
|
||||
if (!c->has_uuid)
|
||||
return sd_bus_error_set(error, BUS_ERROR_NO_PRODUCT_UUID, "Failed to read product UUID from /sys/class/dmi/id/product_uuid");
|
||||
|
||||
r = sd_bus_message_read(m, "b", &interactive);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
m,
|
||||
CAP_SYS_ADMIN,
|
||||
"org.freedesktop.hostname1.get-product-uuid",
|
||||
NULL,
|
||||
interactive,
|
||||
UID_INVALID,
|
||||
&c->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = sd_bus_message_new_method_return(m, &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append_array(reply, 'y', &c->uuid, sizeof(c->uuid));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_send(NULL, reply, NULL);
|
||||
}
|
||||
|
||||
static const sd_bus_vtable hostname_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Hostname", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
|
@ -620,6 +669,7 @@ static const sd_bus_vtable hostname_vtable[] = {
|
|||
SD_BUS_METHOD("SetChassis", "sb", NULL, method_set_chassis, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("SetDeployment", "sb", NULL, method_set_deployment, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("SetLocation", "sb", NULL, method_set_location, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("GetProductUUID", "b", "ay", method_get_product_uuid, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_VTABLE_END,
|
||||
};
|
||||
|
||||
|
|
|
@ -47,4 +47,14 @@
|
|||
</defaults>
|
||||
</action>
|
||||
|
||||
<action id="org.freedesktop.hostname1.get-product-uuid">
|
||||
<description gettext-domain="systemd">Get product UUID</description>
|
||||
<message gettext-domain="systemd">Authentication is required to get product UUID.</message>
|
||||
<defaults>
|
||||
<allow_any>auth_admin_keep</allow_any>
|
||||
<allow_inactive>auth_admin_keep</allow_inactive>
|
||||
<allow_active>auth_admin_keep</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
</policyconfig>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include <linux/if_infiniband.h>
|
||||
#include <net/if_arp.h>
|
||||
|
||||
#include "sd-device.h"
|
||||
#include "sd-id128.h"
|
||||
|
||||
|
@ -10,8 +13,10 @@
|
|||
#include "sparse-endian.h"
|
||||
#include "virt.h"
|
||||
|
||||
#define SYSTEMD_PEN 43793
|
||||
#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
|
||||
#define SYSTEMD_PEN 43793
|
||||
#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
|
||||
#define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03)
|
||||
#define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */
|
||||
|
||||
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
|
||||
struct duid d;
|
||||
|
@ -44,6 +49,56 @@ int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) {
|
||||
uint16_t time_from_2000y;
|
||||
|
||||
assert(duid);
|
||||
assert(len);
|
||||
assert(addr);
|
||||
|
||||
if (arp_type == ARPHRD_ETHER)
|
||||
assert_return(addr_len == ETH_ALEN, -EINVAL);
|
||||
else if (arp_type == ARPHRD_INFINIBAND)
|
||||
assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (t < USEC_2000)
|
||||
time_from_2000y = 0;
|
||||
else
|
||||
time_from_2000y = (uint16_t) (((t - USEC_2000) / USEC_PER_SEC) & 0xffffffff);
|
||||
|
||||
unaligned_write_be16(&duid->type, DUID_TYPE_LLT);
|
||||
unaligned_write_be16(&duid->llt.htype, arp_type);
|
||||
unaligned_write_be32(&duid->llt.time, time_from_2000y);
|
||||
memcpy(duid->llt.haddr, addr, addr_len);
|
||||
|
||||
*len = sizeof(duid->type) + sizeof(duid->llt.htype) + sizeof(duid->llt.time) + addr_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) {
|
||||
assert(duid);
|
||||
assert(len);
|
||||
assert(addr);
|
||||
|
||||
if (arp_type == ARPHRD_ETHER)
|
||||
assert_return(addr_len == ETH_ALEN, -EINVAL);
|
||||
else if (arp_type == ARPHRD_INFINIBAND)
|
||||
assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
unaligned_write_be16(&duid->type, DUID_TYPE_LL);
|
||||
unaligned_write_be16(&duid->ll.htype, arp_type);
|
||||
memcpy(duid->ll.haddr, addr, addr_len);
|
||||
|
||||
*len = sizeof(duid->type) + sizeof(duid->ll.htype) + addr_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
|
||||
sd_id128_t machine_id;
|
||||
uint64_t hash;
|
||||
|
@ -62,13 +117,32 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
|
|||
*len = sizeof(duid->type) + sizeof(duid->en);
|
||||
|
||||
/* a bit of snake-oil perhaps, but no need to expose the machine-id
|
||||
directly; duid->en.id might not be aligned, so we need to copy */
|
||||
* directly; duid->en.id might not be aligned, so we need to copy */
|
||||
hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes));
|
||||
memcpy(duid->en.id, &hash, sizeof(duid->en.id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len) {
|
||||
sd_id128_t machine_id;
|
||||
int r;
|
||||
|
||||
assert(duid);
|
||||
assert(len);
|
||||
|
||||
r = sd_id128_get_machine_app_specific(APPLICATION_ID, &machine_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
unaligned_write_be16(&duid->type, DUID_TYPE_UUID);
|
||||
memcpy(&duid->raw.data, &machine_id, sizeof(machine_id));
|
||||
|
||||
*len = sizeof(duid->type) + sizeof(machine_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) {
|
||||
/* name is a pointer to memory in the sd_device struct, so must
|
||||
* have the same scope */
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "macro.h"
|
||||
#include "sparse-endian.h"
|
||||
#include "time-util.h"
|
||||
#include "unaligned.h"
|
||||
|
||||
typedef enum DUIDType {
|
||||
|
@ -27,18 +28,18 @@ struct duid {
|
|||
union {
|
||||
struct {
|
||||
/* DUID_TYPE_LLT */
|
||||
uint16_t htype;
|
||||
uint32_t time;
|
||||
be16_t htype;
|
||||
be32_t time;
|
||||
uint8_t haddr[0];
|
||||
} _packed_ llt;
|
||||
struct {
|
||||
/* DUID_TYPE_EN */
|
||||
uint32_t pen;
|
||||
be32_t pen;
|
||||
uint8_t id[8];
|
||||
} _packed_ en;
|
||||
struct {
|
||||
/* DUID_TYPE_LL */
|
||||
int16_t htype;
|
||||
be16_t htype;
|
||||
uint8_t haddr[0];
|
||||
} _packed_ ll;
|
||||
struct {
|
||||
|
@ -52,5 +53,8 @@ struct duid {
|
|||
} _packed_;
|
||||
|
||||
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len);
|
||||
int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
|
||||
int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
|
||||
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
|
||||
int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len);
|
||||
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);
|
||||
|
|
|
@ -341,13 +341,14 @@ int sd_dhcp_client_set_client_id(
|
|||
* without further modification. Otherwise, if duid_type is supported, DUID
|
||||
* is set based on that type. Otherwise, an error is returned.
|
||||
*/
|
||||
static int dhcp_client_set_iaid_duid(
|
||||
static int dhcp_client_set_iaid_duid_internal(
|
||||
sd_dhcp_client *client,
|
||||
uint32_t iaid,
|
||||
bool append_iaid,
|
||||
uint16_t duid_type,
|
||||
const void *duid,
|
||||
size_t duid_len) {
|
||||
size_t duid_len,
|
||||
usec_t llt_time) {
|
||||
|
||||
DHCP_CLIENT_DONT_DESTROY(client);
|
||||
int r;
|
||||
|
@ -381,18 +382,43 @@ static int dhcp_client_set_iaid_duid(
|
|||
client->client_id.ns.duid.type = htobe16(duid_type);
|
||||
memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len);
|
||||
len = sizeof(client->client_id.ns.duid.type) + duid_len;
|
||||
} else if (duid_type == DUID_TYPE_EN) {
|
||||
r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else
|
||||
return -EOPNOTSUPP;
|
||||
switch (duid_type) {
|
||||
case DUID_TYPE_LLT:
|
||||
if (!client->mac_addr || client->mac_addr_len == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = dhcp_identifier_set_duid_llt(&client->client_id.ns.duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case DUID_TYPE_EN:
|
||||
r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case DUID_TYPE_LL:
|
||||
if (!client->mac_addr || client->mac_addr_len == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = dhcp_identifier_set_duid_ll(&client->client_id.ns.duid, client->mac_addr, client->mac_addr_len, client->arp_type, &len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case DUID_TYPE_UUID:
|
||||
r = dhcp_identifier_set_duid_uuid(&client->client_id.ns.duid, &len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
client->client_id_len = sizeof(client->client_id.type) + len +
|
||||
(append_iaid ? sizeof(client->client_id.ns.iaid) : 0);
|
||||
|
||||
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
|
||||
log_dhcp_client(client, "Configured IAID+DUID, restarting.");
|
||||
log_dhcp_client(client, "Configured %sDUID, restarting.", append_iaid ? "IAID+" : "");
|
||||
client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
|
||||
sd_dhcp_client_start(client);
|
||||
}
|
||||
|
@ -406,7 +432,14 @@ int sd_dhcp_client_set_iaid_duid(
|
|||
uint16_t duid_type,
|
||||
const void *duid,
|
||||
size_t duid_len) {
|
||||
return dhcp_client_set_iaid_duid(client, iaid, true, duid_type, duid, duid_len);
|
||||
return dhcp_client_set_iaid_duid_internal(client, iaid, true, duid_type, duid, duid_len, 0);
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_iaid_duid_llt(
|
||||
sd_dhcp_client *client,
|
||||
uint32_t iaid,
|
||||
usec_t llt_time) {
|
||||
return dhcp_client_set_iaid_duid_internal(client, iaid, true, DUID_TYPE_LLT, NULL, 0, llt_time);
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_duid(
|
||||
|
@ -414,7 +447,13 @@ int sd_dhcp_client_set_duid(
|
|||
uint16_t duid_type,
|
||||
const void *duid,
|
||||
size_t duid_len) {
|
||||
return dhcp_client_set_iaid_duid(client, 0, false, duid_type, duid, duid_len);
|
||||
return dhcp_client_set_iaid_duid_internal(client, 0, false, duid_type, duid, duid_len, 0);
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_duid_llt(
|
||||
sd_dhcp_client *client,
|
||||
usec_t llt_time) {
|
||||
return dhcp_client_set_iaid_duid_internal(client, 0, false, DUID_TYPE_LLT, NULL, 0, llt_time);
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_hostname(
|
||||
|
|
|
@ -182,13 +182,14 @@ static int client_ensure_duid(sd_dhcp6_client *client) {
|
|||
* without further modification. Otherwise, if duid_type is supported, DUID
|
||||
* is set based on that type. Otherwise, an error is returned.
|
||||
*/
|
||||
int sd_dhcp6_client_set_duid(
|
||||
static int dhcp6_client_set_duid_internal(
|
||||
sd_dhcp6_client *client,
|
||||
uint16_t duid_type,
|
||||
const void *duid,
|
||||
size_t duid_len) {
|
||||
|
||||
size_t duid_len,
|
||||
usec_t llt_time) {
|
||||
int r;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(duid_len == 0 || duid != NULL, -EINVAL);
|
||||
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
|
||||
|
@ -197,22 +198,59 @@ int sd_dhcp6_client_set_duid(
|
|||
r = dhcp_validate_duid_len(duid_type, duid_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (duid != NULL) {
|
||||
client->duid.type = htobe16(duid_type);
|
||||
memcpy(&client->duid.raw.data, duid, duid_len);
|
||||
client->duid_len = sizeof(client->duid.type) + duid_len;
|
||||
} else if (duid_type == DUID_TYPE_EN) {
|
||||
r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else
|
||||
return -EOPNOTSUPP;
|
||||
switch (duid_type) {
|
||||
case DUID_TYPE_LLT:
|
||||
if (!client->mac_addr || client->mac_addr_len == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = dhcp_identifier_set_duid_llt(&client->duid, 0, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case DUID_TYPE_EN:
|
||||
r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case DUID_TYPE_LL:
|
||||
if (!client->mac_addr || client->mac_addr_len == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = dhcp_identifier_set_duid_ll(&client->duid, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case DUID_TYPE_UUID:
|
||||
r = dhcp_identifier_set_duid_uuid(&client->duid, &client->duid_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_duid(
|
||||
sd_dhcp6_client *client,
|
||||
uint16_t duid_type,
|
||||
const void *duid,
|
||||
size_t duid_len) {
|
||||
return dhcp6_client_set_duid_internal(client, duid_type, duid, duid_len, 0);
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_duid_llt(
|
||||
sd_dhcp6_client *client,
|
||||
usec_t llt_time) {
|
||||
return dhcp6_client_set_duid_internal(client, DUID_TYPE_LLT, NULL, 0, llt_time);
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) {
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
|
||||
|
|
|
@ -94,5 +94,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
|
|||
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER, ENXIO),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS, EBUSY),
|
||||
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRODUCT_UUID, EOPNOTSUPP),
|
||||
|
||||
SD_BUS_ERROR_MAP_END
|
||||
};
|
||||
|
|
|
@ -75,4 +75,6 @@
|
|||
#define BUS_ERROR_NO_SUCH_TRANSFER "org.freedesktop.import1.NoSuchTransfer"
|
||||
#define BUS_ERROR_TRANSFER_IN_PROGRESS "org.freedesktop.import1.TransferInProgress"
|
||||
|
||||
#define BUS_ERROR_NO_PRODUCT_UUID "org.freedesktop.hostname1.NoProductUUID"
|
||||
|
||||
BUS_ERROR_MAP_ELF_USE(bus_common_errors);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -131,11 +131,18 @@ int sd_dhcp_client_set_iaid_duid(
|
|||
uint16_t duid_type,
|
||||
const void *duid,
|
||||
size_t duid_len);
|
||||
int sd_dhcp_client_set_iaid_duid_llt(
|
||||
sd_dhcp_client *client,
|
||||
uint32_t iaid,
|
||||
uint64_t llt_time);
|
||||
int sd_dhcp_client_set_duid(
|
||||
sd_dhcp_client *client,
|
||||
uint16_t duid_type,
|
||||
const void *duid,
|
||||
size_t duid_len);
|
||||
int sd_dhcp_client_set_duid_llt(
|
||||
sd_dhcp_client *client,
|
||||
uint64_t llt_time);
|
||||
int sd_dhcp_client_get_client_id(
|
||||
sd_dhcp_client *client,
|
||||
uint8_t *type,
|
||||
|
|
|
@ -102,6 +102,9 @@ int sd_dhcp6_client_set_duid(
|
|||
uint16_t duid_type,
|
||||
const void *duid,
|
||||
size_t duid_len);
|
||||
int sd_dhcp6_client_set_duid_llt(
|
||||
sd_dhcp6_client *client,
|
||||
uint64_t llt_time);
|
||||
int sd_dhcp6_client_set_iaid(
|
||||
sd_dhcp6_client *client,
|
||||
uint32_t iaid);
|
||||
|
|
Loading…
Reference in New Issue