changeset 4288:0bd4f5b53051 draft

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.
author Roy Marples <roy@marples.name>
date Tue, 05 Jun 2018 11:36:33 +0100
parents 2b519911f230
children 2d4ea1b35d15
files src/common.c src/dhcpcd.8.in src/dhcpcd.conf.5.in src/duid.c
diffstat 4 files changed, 105 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/src/common.c	Mon Jun 04 17:30:16 2018 +0100
+++ b/src/common.c	Tue Jun 05 11:36:33 2018 +0100
@@ -140,10 +140,15 @@
 	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 @@
 			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++;
--- a/src/dhcpcd.8.in	Mon Jun 04 17:30:16 2018 +0100
+++ b/src/dhcpcd.8.in	Tue Jun 05 11:36:33 2018 +0100
@@ -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 @@
 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\ 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
--- a/src/dhcpcd.conf.5.in	Mon Jun 04 17:30:16 2018 +0100
+++ b/src/dhcpcd.conf.5.in	Tue Jun 05 11:36:33 2018 +0100
@@ -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 @@
 .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 .
--- a/src/duid.c	Mon Jun 04 17:30:16 2018 +0100
+++ b/src/duid.c	Tue Jun 05 11:36:33 2018 +0100
@@ -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 @@
 	/* 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) {