sd-dhcp: use application specific machine ID when DUIDType=uuid but DUIDRawData= is not set

This commit is contained in:
Yu Watanabe 2018-06-25 18:23:13 +09:00
parent 21e627daa5
commit 27eba50e76
4 changed files with 53 additions and 16 deletions

View File

@ -11,8 +11,9 @@
#include "udev-util.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)
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
struct duid d;
@ -63,13 +64,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 udev_device struct, so must
have the same scope */

View File

@ -53,4 +53,5 @@ struct duid {
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_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);

View File

@ -381,12 +381,21 @@ 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_EN:
r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &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 -EOPNOTSUPP;
}
client->client_id_len = sizeof(client->client_id.type) + len +
(append_iaid ? sizeof(client->client_id.ns.iaid) : 0);

View File

@ -187,8 +187,8 @@ int sd_dhcp6_client_set_duid(
uint16_t duid_type,
const void *duid,
size_t duid_len) {
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,18 +197,25 @@ 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_EN:
r = dhcp_identifier_set_duid_en(&client->duid, &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 -EOPNOTSUPP;
}
return 0;
}