[systemd-devel] [PATCH] sd-dhcp6-client: support custom DUIDs

Tom Gundersen teg at jklm.no
Mon Aug 11 16:12:23 PDT 2014


On Wed, Aug 6, 2014 at 6:17 PM, Dan Williams <dcbw at redhat.com> wrote:
> 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.

I have no objections a priori to this patch. But what is the use case?
Is there some DUID scheme that is preferable to DUID-EN that we could
simply use unconditionally, or do you really depend on the possibility
of customizing it?

> ---
>  src/libsystemd-network/sd-dhcp6-client.c   | 52 +++++++++++++++++++-----------
>  src/libsystemd-network/test-dhcp6-client.c |  4 +--
>  src/network/networkd-link.c                |  2 +-
>  src/systemd/sd-dhcp6-client.h              |  2 +-
>  4 files changed, 38 insertions(+), 22 deletions(-)
>
> diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
> index c6c82eb..8123dc8 100644
> --- a/src/libsystemd-network/sd-dhcp6-client.c
> +++ b/src/libsystemd-network/sd-dhcp6-client.c
> @@ -35,14 +35,16 @@
>  #include "dhcp6-protocol.h"
>  #include "dhcp6-internal.h"
>  #include "dhcp6-lease-internal.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 MAX_DUID_LEN 32
> +
>  struct sd_dhcp6_client {
>          RefCount n_ref;
>
>          enum DHCP6State state;
>          sd_event *event;
>          int event_priority;
>          int index;
> @@ -57,20 +59,16 @@ struct sd_dhcp6_client {
>          sd_event_source *receive_message;
>          usec_t retransmit_time;
>          uint8_t retransmit_count;
>          sd_event_source *timeout_resend;
>          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[] = {
>          DHCP6_OPTION_DNS_SERVERS,
>          DHCP6_OPTION_DOMAIN_LIST,
>          DHCP6_OPTION_NTP_SERVER,
>  };
> @@ -300,15 +298,15 @@ static int client_send_message(sd_dhcp6_client *client) {
>          r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ORO,
>                                  client->req_opts_len * sizeof(be16_t),
>                                  client->req_opts);
>          if (r < 0)
>                  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;
>
>          r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message,
>                                            len - optlen);
>          if (r < 0)
>                  return r;
> @@ -585,15 +583,15 @@ static int client_parse_message(sd_dhcp6_client *client,
>                  case DHCP6_OPTION_CLIENTID:
>                          if (clientid) {
>                                  log_dhcp6_client(client, "%s contains multiple clientids",
>                                                   dhcp6_message_type_to_string(message->type));
>                                  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));
>
>                                  return -EINVAL;
>                          }
>                          clientid = true;
> @@ -1059,47 +1057,65 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
>
>                  return NULL;
>          }
>
>          return client;
>  }
>
> -int sd_dhcp6_client_new(sd_dhcp6_client **ret)
> +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, uint8_t *duid, size_t duid_len)
>  {
>          _cleanup_dhcp6_client_unref_ sd_dhcp6_client *client = NULL;
>          sd_id128_t machine_id;
>          int r;
>          size_t t;
>
>          assert_return(ret, -EINVAL);
> +        if (duid)
> +                assert_return(duid_len > 0 && duid_len < MAX_DUID_LEN, -EINVAL);
> +        else
> +                assert_return(duid_len == 0, -EINVAL);
>
>          client = new0(sd_dhcp6_client, 1);
>          if (!client)
>                  return -ENOMEM;
>
>          client->n_ref = REFCNT_INIT;
>
>          client->ia_na.type = DHCP6_OPTION_IA_NA;
>
>          client->index = -1;
>
>          client->fd = -1;
>
>          /* initialize DUID */
> -        client->duid.type = htobe16(DHCP6_DUID_EN);
> -        client->duid.pen = htobe32(SYSTEMD_PEN);
> +        if (duid) {
> +                memcpy(&client->duid, duid, duid_len);
> +                client->duid_len = duid_len;
> +        } else {
> +                struct duid_en *en = (struct duid_en *) &client->duid;
>
> -        r = sd_id128_get_machine(&machine_id);
> -        if (r < 0)
> -                return r;
> +                en->type = htobe16(DHCP6_DUID_EN);
> +                en->pen = htobe32(SYSTEMD_PEN);
>
> -        /* 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);
> +                r = sd_id128_get_machine(&machine_id);
> +                if (r < 0)
> +                        return r;
> +
> +                /* a bit of snake-oil perhaps, but no need to expose the
> +                   machine-id directly */
> +                siphash24(en->id, &machine_id, sizeof(machine_id),
> +                          HASH_KEY.bytes);
> +                client->duid_len = sizeof (*en);
> +        }
>
>          client->req_opts_len = ELEMENTSOF(default_req_opts);
>
>          client->req_opts = new0(be16_t, client->req_opts_len);
>          if (!client->req_opts)
>                  return -ENOMEM;
>
> diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c
> index 96c68e1..3545935 100644
> --- a/src/libsystemd-network/test-dhcp6-client.c
> +++ b/src/libsystemd-network/test-dhcp6-client.c
> @@ -52,15 +52,15 @@ static uint8_t test_duid[14] = { };
>
>  static int test_client_basic(sd_event *e) {
>          sd_dhcp6_client *client;
>
>          if (verbose)
>                  printf("* %s\n", __FUNCTION__);
>
> -        assert_se(sd_dhcp6_client_new(&client) >= 0);
> +        assert_se(sd_dhcp6_client_new(&client, NULL, 0) >= 0);
>          assert_se(client);
>
>          assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
>
>          assert_se(sd_dhcp6_client_set_index(client, 15) == 0);
>          assert_se(sd_dhcp6_client_set_index(client, -42) == -EINVAL);
>          assert_se(sd_dhcp6_client_set_index(client, -1) == 0);
> @@ -538,15 +538,15 @@ static void test_client_solicit_cb(sd_dhcp6_client *client, int event,
>  static int test_client_solicit(sd_event *e) {
>          sd_dhcp6_client *client;
>          usec_t time_now = now(clock_boottime_or_monotonic());
>
>          if (verbose)
>                  printf("* %s\n", __FUNCTION__);
>
> -        assert_se(sd_dhcp6_client_new(&client) >= 0);
> +        assert_se(sd_dhcp6_client_new(&client, NULL, 0) >= 0);
>          assert_se(client);
>
>          assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
>
>          assert_se(sd_dhcp6_client_set_index(client, test_index) == 0);
>          assert_se(sd_dhcp6_client_set_mac(client, &mac_addr) >= 0);
>
> diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
> index accb42b..eff14ca 100644
> --- a/src/network/networkd-link.c
> +++ b/src/network/networkd-link.c
> @@ -1367,15 +1367,15 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) {
>
>                  return;
>          }
>
>          if (link->dhcp6_client)
>                  return;
>
> -        r = sd_dhcp6_client_new(&link->dhcp6_client);
> +        r = sd_dhcp6_client_new(&link->dhcp6_client, NULL, 0);
>          if (r < 0)
>                  return;
>
>          r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0);
>          if (r < 0) {
>                  link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
>                  return;
> diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h
> index 93edcc4..b3ec82f 100644
> --- a/src/systemd/sd-dhcp6-client.h
> +++ b/src/systemd/sd-dhcp6-client.h
> @@ -54,10 +54,10 @@ int sd_dhcp6_client_stop(sd_dhcp6_client *client);
>  int sd_dhcp6_client_start(sd_dhcp6_client *client);
>  int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event,
>                                   int priority);
>  int sd_dhcp6_client_detach_event(sd_dhcp6_client *client);
>  sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client);
>  sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client);
>  sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client);
> -int sd_dhcp6_client_new(sd_dhcp6_client **ret);
> +int sd_dhcp6_client_new(sd_dhcp6_client **ret, uint8_t *duid, size_t duid_len);
>
>  #endif
> --
> 1.9.3
>
>
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel


More information about the systemd-devel mailing list