From: Roy Marples Date: Tue, 5 Jun 2018 10:36:33 +0000 (+0100) Subject: duid: Implement RFC 6355 X-Git-Tag: v7.0.6~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=239b962fadd5a8939963a7eb2863625f3abdc6f8;p=thirdparty%2Fdhcpcd.git 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. --- 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 + * Copyright (c) 2006-2018 Roy Marples * 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 #include #include +#ifdef BSD +# include +#endif #include @@ -54,6 +60,66 @@ #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) {