summaryrefslogtreecommitdiff
path: root/src/libsystemd-network/sd-dhcp6-client.c
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2014-09-26 15:12:36 -0500
committerTom Gundersen <teg@jklm.no>2014-10-02 19:07:30 +0200
commit66eac1201a9c1596f5901f8dbbf24bda7e350878 (patch)
tree62a2fc6ff936a1fdfaa284f37cd1b9fab28e53fd /src/libsystemd-network/sd-dhcp6-client.c
parent995a1063dbdc94e2c0846216363636e8ebbc60f9 (diff)
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]
Diffstat (limited to 'src/libsystemd-network/sd-dhcp6-client.c')
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index c190b560e..130fe43cf 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);