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