]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
duid: Implement RFC 6355
authorRoy Marples <roy@marples.name>
Tue, 5 Jun 2018 10:36:33 +0000 (11:36 +0100)
committerRoy Marples <roy@marples.name>
Tue, 5 Jun 2018 10:36:33 +0000 (11:36 +0100)
If no duid file is present and a system UUID exists, use that for
a DUID-UUID, otherwise proceed as before.

src/common.c
src/dhcpcd.8.in
src/dhcpcd.conf.5.in
src/duid.c

index 07c4340e6c9674f10b6cf7531d0e92e0260263b6..d4b606dc0d4ccf45d415bcc0dc1d2269b399792f 100644 (file)
@@ -140,10 +140,15 @@ hwaddr_aton(uint8_t *buffer, const char *addr)
        size_t len = 0;
 
        c[2] = '\0';
-       while (*p) {
+       while (*p != '\0') {
+               /* Skip separators */
                c[0] = *p++;
-               if (c[0] == '\n')
+               switch (c[0]) {
+               case '\n':      /* long duid split on lines */
+               case ':':       /* typical mac address */
+               case '-':       /* uuid */
                        continue;
+               }
                c[1] = *p++;
                /* Ensure that digits are hex */
                if (isxdigit((unsigned char)c[0]) == 0 ||
@@ -157,15 +162,6 @@ hwaddr_aton(uint8_t *buffer, const char *addr)
                        errno = EINVAL;
                        return 0;
                }
-               /* Ensure that next data is EOL or a seperator with data */
-               if (!(*p == '\0' || *p == '\n' ||
-                   (*p == ':' && *(p + 1) != '\0')))
-               {
-                       errno = EINVAL;
-                       return 0;
-               }
-               if (*p)
-                       p++;
                if (bp)
                        *bp++ = (uint8_t)strtol(c, NULL, 16);
                len++;
index 8af2ff4d831df21a924078da930809bae0ab7780..235161962f08dc0a5e8545ec5223f040ef05a3df 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd April 29, 2018
+.Dd June 5, 2018
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -253,15 +253,17 @@ Use this
 instead of the default
 .Pa @SCRIPT@ .
 .It Fl D , Fl Fl duid
-Generate an
-.Li RFC 4361
-compliant clientid.
-This requires persistent storage and not all DHCP servers work with it so it
-is not enabled by default.
-.Nm
-generates the DUID and stores it in
-.Pa @DBDIR@/duid .
-This file should not be copied to other hosts.
+Use a DHCP Unique Identifier.
+If a system UUID is available, that will be used to create a DUID-UUID,
+otheriwse if persistent storage is available then a DUID-LLT
+(link local address + time) is generated,
+otherwise DUID-LL is generated (link local address).
+This, plus the IAID will be used as the
+.Fl I, Fl Fl clientid .
+The DUID generated will be held in
+.Pa @DBDIR@/duid
+and should not be copied to other hosts.
+This file also takes precedence over the above rules.
 .It Fl d , Fl Fl debug
 Echo debug messages to the stderr and syslog.
 .It Fl E , Fl Fl lastlease
@@ -823,8 +825,8 @@ RFC\ 951, RFC\ 1534, RFC\ 2104, RFC\ 2131, RFC\ 2132, RFC\ 2563, RFC\ 2855,
 RFC\ 3004, RFC\ 3118, RFC\ 3203, RFC\ 3315, RFC\ 3361, RFC\ 3633, RFC\ 3396,
 RFC\ 3397, RFC\ 3442, RFC\ 3495, RFC\ 3925, RFC\ 3927, RFC\ 4039, RFC\ 4075,
 RFC\ 4242, RFC\ 4361, RFC\ 4390, RFC\ 4702, RFC\ 4074, RFC\ 4861, RFC\ 4833,
-RFC\ 4941, RFC\ 5227, RFC\ 5942, RFC\ 5969, RFC\ 6106, RFC\ 6334, RFC\ 6603,
-RFC\ 6704, RFC\ 7217, RFC\ 7550.
+RFC\ 4941, RFC\ 5227, RFC\ 5942, RFC\ 5969, RFC\ 6106, RFC\ 6334, RFC\ 6355,
+RFC\ 6603, RFC\ 6704, RFC\ 7217, RFC\ 7550.
 .Sh AUTHORS
 .An Roy Marples Aq Mt roy@marples.name
 .Sh BUGS
index e7f5e5e8b77d349e2e7163c1fbb372bc3c89f4c3..c3e01d6b90caa3e9175298f4fa644739f1829e35 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd May 3, 2018
+.Dd June 5, 2018
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -188,18 +188,17 @@ sends a default
 .Ar clientid
 of the hardware family and the hardware address.
 .It Ic duid
-Generate an
-.Rs
-.%T "RFC 4361"
-.Re
-compliant DHCP Unique Identifier.
-If persistent storage is available then a DUID-LLT (link local address + time)
-is generated, otherwise DUID-LL is generated (link local address).
+Use a DHCP Unique Identifier.
+If a system UUID is available, that will be used to create a DUID-UUID,
+otheriwse if persistent storage is available then a DUID-LLT
+(link local address + time) is generated,
+otherwise DUID-LL is generated (link local address).
 This, plus the IAID will be used as the
 .Ic clientid .
-The DUID-LLT generated will be held in
+The DUID generated will be held in
 .Pa @DBDIR@/duid
 and should not be copied to other hosts.
+This file also takes precedence over the above rules.
 .It Ic iaid Ar iaid
 Set the Interface Association Identifier to
 .Ar iaid .
index 3e8ed227efecd1ac83a19925d01e54fb3daf81d9..cc53f9bdc53b24cdb321aff83212d833546ac416 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2018 Roy Marples <roy@marples.name>
  * All rights reserved
 
  * Redistribution and use in source and binary forms, with or without
  * SUCH DAMAGE.
  */
 
-#define DUID_TIME_EPOCH 946684800
-#define DUID_LLT       1
-#define DUID_LL                3
+#define        UUID_LEN        36
+#define        DUID_TIME_EPOCH 946684800
+#define        DUID_LLT        1
+#define        DUID_LL         3
+#define        DUID_UUID       4
 
+#include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/types.h>
+#ifdef BSD
+#  include <sys/sysctl.h>
+#endif
 
 #include <arpa/inet.h>
 
 #include "duid.h"
 #include "logerr.h"
 
+static size_t
+duid_machineuuid(char *uuid, size_t uuid_len)
+{
+       int r;
+       size_t len = uuid_len;
+
+#if defined(HW_UUID) /* OpenBSD */
+       int mib[] = { CTL_HW, HW_UUID };
+
+       r = sysctl(mib, sizeof(mib)/sizeof(mib[0]), uuid, &len, NULL, 0);
+#elif defined(KERN_HOSTUUID) /* FreeBSD */
+       int mib[] = { CTL_KERN, KERN_HOSTUUID };
+
+       r = sysctl(mib, sizeof(mib)/sizeof(mib[0]), uuid, &len, NULL, 0);
+#elif defined(__NetBSD__)
+       r = sysctlbyname("machdep.dmi.system-uuid", uuid, &len, NULL, 0);
+#elif defined(__linux__)
+       FILE *fp;
+
+       fp = fopen("/sys/class/dmi/id/product_uuid", "r");
+       if (fp == NULL)
+               return 0;
+       if (fgets(uuid, (int)uuid_len, fp) == NULL) {
+               fclose(fp);
+               return 0;
+       }
+       len = strlen(uuid) + 1;
+       fclose(fp);
+       r = 0;
+#else
+       r = -1;
+       errno = ENOSYS;
+#endif
+
+       if (r == -1)
+               return 0;
+       return len;
+}
+
+static size_t
+duid_make_uuid(uint8_t *d)
+{
+       uint16_t type = htons(DUID_UUID);
+       char uuid[UUID_LEN + 1];
+       size_t l;
+
+       if (duid_machineuuid(uuid, sizeof(uuid)) != sizeof(uuid))
+               return 0;
+
+       /* All zeros UUID is not valid */
+       if (strcmp("00000000-0000-0000-0000-000000000000", uuid) == 0)
+               return 0;
+
+       memcpy(d, &type, sizeof(type));
+       l = sizeof(type);
+       d += sizeof(type);
+       l += hwaddr_aton(d, uuid);
+       return l;
+}
+
 static size_t
 duid_make(uint8_t *d, const struct interface *ifp, uint16_t type)
 {
@@ -115,7 +181,12 @@ duid_get(uint8_t **d, const struct interface *ifp)
        /* Regardless of what happens we will create a DUID to use. */
        *d = data;
 
-       /* No file? OK, lets make one based on our interface */
+       /* No file? OK, lets make one based the machines UUID */
+       len = duid_make_uuid(data);
+       if (len > 0)
+               return len;
+
+       /* No UUID? OK, lets make one based on our interface */
        if (ifp->family == ARPHRD_NETROM) {
                logwarnx("%s: is a NET/ROM pseudo interface", ifp->name);
                TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {