summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2018-06-05 11:36:33 +0100
committerRoy Marples <roy@marples.name>2018-06-05 11:36:33 +0100
commit239b962fadd5a8939963a7eb2863625f3abdc6f8 (patch)
treec8b981a6c41b0f15aa2a09cd59733cbaa7f7263d
parentd51d87c63a21441757aad1bf4639311200e86542 (diff)
downloaddhcpcd-239b962fadd5a8939963a7eb2863625f3abdc6f8.tar.xz
duid: Implement RFC 6355
If no duid file is present and a system UUID exists, use that for a DUID-UUID, otherwise proceed as before.
-rw-r--r--src/common.c18
-rw-r--r--src/dhcpcd.8.in26
-rw-r--r--src/dhcpcd.conf.5.in17
-rw-r--r--src/duid.c81
4 files changed, 105 insertions, 37 deletions
diff --git a/src/common.c b/src/common.c
index 07c4340e..d4b606dc 100644
--- a/src/common.c
+++ b/src/common.c
@@ -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++;
diff --git a/src/dhcpcd.8.in b/src/dhcpcd.8.in
index 8af2ff4d..23516196 100644
--- a/src/dhcpcd.8.in
+++ b/src/dhcpcd.8.in
@@ -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
diff --git a/src/dhcpcd.conf.5.in b/src/dhcpcd.conf.5.in
index e7f5e5e8..c3e01d6b 100644
--- a/src/dhcpcd.conf.5.in
+++ b/src/dhcpcd.conf.5.in
@@ -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 .
diff --git a/src/duid.c b/src/duid.c
index 3e8ed227..cc53f9bd 100644
--- a/src/duid.c
+++ b/src/duid.c
@@ -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
@@ -25,12 +25,18 @@
* 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>
@@ -55,6 +61,66 @@
#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)
{
uint8_t *p;
@@ -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) {