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 ||
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++;
.\" 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
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
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
.\" 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
.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 .
/*
* 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)
{
/* 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) {