From 66eac1201a9c1596f5901f8dbbf24bda7e350878 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 26 Sep 2014 15:12:36 -0500 Subject: [PATCH] sd-dhcp6-client: support custom DUIDs The caller may have an existing DUID that it wants to use, and may want to use some other DUID generation scheme than systemd's default DUID-EN. [tomegun: whitespace - we never use tabs] --- src/libsystemd-network/sd-dhcp6-client.c | 43 +++++++++++++++++++++++--------- src/systemd/sd-dhcp6-client.h | 2 ++ 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index c190b560ea..130fe43cf2 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -39,6 +39,8 @@ #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 MAX_DUID_LEN 32 + struct sd_dhcp6_client { RefCount n_ref; @@ -62,12 +64,8 @@ struct sd_dhcp6_client { sd_event_source *timeout_resend_expire; sd_dhcp6_client_cb_t cb; void *userdata; - - struct duid_en { - uint16_t type; /* DHCP6_DUID_EN */ - uint32_t pen; - uint8_t id[8]; - } _packed_ duid; + uint8_t duid[MAX_DUID_LEN]; + size_t duid_len; }; static const uint16_t default_req_opts[] = { @@ -147,6 +145,19 @@ int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, return 0; } +int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint8_t *duid, + size_t duid_len) +{ + assert_return(client, -EINVAL); + assert_return(duid, -EINVAL); + assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL); + + memcpy(&client->duid, duid, duid_len); + client->duid_len = duid_len; + + return 0; +} + int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) { size_t t; @@ -308,7 +319,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { return r; r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_CLIENTID, - sizeof(client->duid), &client->duid); + client->duid_len, &client->duid); if (r < 0) return r; @@ -616,7 +627,7 @@ static int client_parse_message(sd_dhcp6_client *client, return -EINVAL; } - if (optlen != sizeof(client->duid) || + if (optlen != client->duid_len || memcmp(&client->duid, optval, optlen) != 0) { log_dhcp6_client(client, "%s DUID does not match", dhcp6_message_type_to_string(message->type)); @@ -1116,9 +1127,16 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) { return client; } +struct duid_en { + uint16_t type; /* DHCP6_DUID_EN */ + uint32_t pen; + uint8_t id[8]; +} _packed_; + int sd_dhcp6_client_new(sd_dhcp6_client **ret) { _cleanup_dhcp6_client_unref_ sd_dhcp6_client *client = NULL; + struct duid_en *duid; sd_id128_t machine_id; int r; size_t t; @@ -1138,8 +1156,9 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) client->fd = -1; /* initialize DUID */ - client->duid.type = htobe16(DHCP6_DUID_EN); - client->duid.pen = htobe32(SYSTEMD_PEN); + duid = (struct duid_en *) &client->duid; + duid->type = htobe16(DHCP6_DUID_EN); + duid->pen = htobe32(SYSTEMD_PEN); r = sd_id128_get_machine(&machine_id); if (r < 0) @@ -1147,8 +1166,8 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) /* a bit of snake-oil perhaps, but no need to expose the machine-id directly */ - siphash24(client->duid.id, &machine_id, sizeof(machine_id), - HASH_KEY.bytes); + siphash24(duid->id, &machine_id, sizeof(machine_id), HASH_KEY.bytes); + client->duid_len = sizeof (struct duid_en); client->req_opts_len = ELEMENTSOF(default_req_opts); diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h index 93edcc41fc..7b7f098b0c 100644 --- a/src/systemd/sd-dhcp6-client.h +++ b/src/systemd/sd-dhcp6-client.h @@ -45,6 +45,8 @@ int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index); int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const struct ether_addr *mac_addr); +int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint8_t *duid, + size_t duid_len); int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option);