From: Roy Marples Date: Tue, 30 Aug 2022 09:48:11 +0000 (+0100) Subject: inet6: Support Tokenised IPv6 Identifiers X-Git-Tag: v10.0.0~45 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1a70f1b51c453c66993fab8172e57924059bd34b;p=thirdparty%2Fdhcpcd.git inet6: Support Tokenised IPv6 Identifiers https://datatracker.ietf.org/doc/id/draft-chown-6man-tokenised-ipv6-identifiers-02.txt Didn't quite make it to a RFC, but it's easy to implement and seems a nice to have. Fixes #101. --- diff --git a/src/dhcpcd.conf.5.in b/src/dhcpcd.conf.5.in index f00df3e1..742f39f2 100644 --- a/src/dhcpcd.conf.5.in +++ b/src/dhcpcd.conf.5.in @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 29, 2022 +.Dd August 30, 2022 .Dt DHCPCD.CONF 5 .Os .Sh NAME @@ -648,13 +648,16 @@ instead of the default .It Ic ssid Ar ssid Subsequent options are only parsed for this wireless .Ar ssid . -.It Ic slaac Ar hwaddr | Ar private Op Ar temp | Ar temporary +.It Ic slaac Ic hwaddr | Ic private | Ic token Ar token Op Ic temp | Ic temporary Selects the interface identifier used for SLAAC generated IPv6 addresses. If -.Ar private +.Ic private is used, a RFC 7217 address is generated. +If +.Ic token Ar token +is used then the token is combied with the prefix to make the final address. The -.Ar temporary +.Ic temporary directive will create a temporary address for the prefix as well. .It Ic static Ar value Configures a static diff --git a/src/if-options.c b/src/if-options.c index 46ea7ea0..fe490fbb 100644 --- a/src/if-options.c +++ b/src/if-options.c @@ -2231,6 +2231,22 @@ invalid_token: ifo->options |= DHCPCD_SLAACPRIVATE; else ifo->options &= ~DHCPCD_SLAACPRIVATE; + if (strcmp(arg, "token") == 0) { + if (np == NULL) { + logerrx("slaac token: no token specified"); + return -1; + } + arg = np; + np = strwhite(np); + if (np != NULL) { + *np++ = '\0'; + np = strskipwhite(np); + } + if (inet_pton(AF_INET6, arg, &ifo->token) != 1) { + logerrx("slaac token: invalid token"); + return -1; + } + } if (np != NULL && (strcmp(np, "temp") == 0 || strcmp(np, "temporary") == 0)) ifo->options |= DHCPCD_SLAACTEMP; diff --git a/src/if-options.h b/src/if-options.h index f80119d6..4b252826 100644 --- a/src/if-options.h +++ b/src/if-options.h @@ -266,6 +266,9 @@ struct if_options { struct if_ia *ia; size_t ia_len; +#ifdef INET6 + struct in6_addr token; +#endif struct dhcp_opt *dhcp_override; size_t dhcp_override_len; diff --git a/src/ipv6.c b/src/ipv6.c index 04bf7746..d8e00de3 100644 --- a/src/ipv6.c +++ b/src/ipv6.c @@ -359,51 +359,6 @@ again: } #endif -int -ipv6_makeaddr(struct in6_addr *addr, struct interface *ifp, - const struct in6_addr *prefix, int prefix_len, unsigned int flags) -{ - const struct ipv6_addr *ap; - int dad; - - if (prefix_len < 0 || prefix_len > 120) { - errno = EINVAL; - return -1; - } - -#ifdef IPV6_AF_TEMPORARY - if (flags & IPV6_AF_TEMPORARY) - return ipv6_maketemporaryaddress(addr, prefix, prefix_len, ifp); -#else - UNUSED(flags); -#endif - - if (ifp->options->options & DHCPCD_SLAACPRIVATE) { - dad = 0; - if (ipv6_makestableprivate(addr, - prefix, prefix_len, ifp, &dad) == -1) - return -1; - return dad; - } - - if (prefix_len > 64) { - errno = EINVAL; - return -1; - } - if ((ap = ipv6_linklocal(ifp)) == NULL) { - /* We delay a few functions until we get a local-link address - * so this should never be hit. */ - errno = ENOENT; - return -1; - } - - /* Make the address from the first local-link address */ - memcpy(addr, prefix, sizeof(*prefix)); - addr->s6_addr32[2] = ap->addr.s6_addr32[2]; - addr->s6_addr32[3] = ap->addr.s6_addr32[3]; - return 0; -} - static int ipv6_makeprefix(struct in6_addr *prefix, const struct in6_addr *addr, int len) { @@ -478,6 +433,55 @@ ipv6_prefixlen(const struct in6_addr *mask) return (uint8_t)(x * NBBY + y); } +int +ipv6_makeaddr(struct in6_addr *addr, struct interface *ifp, + const struct in6_addr *prefix, int prefix_len, unsigned int flags) +{ + const struct ipv6_addr *ap; + const struct if_options *ifo = ifp->options; + int dad; + + if (prefix_len < 0 || prefix_len > 120) { + errno = EINVAL; + return -1; + } + +#ifdef IPV6_AF_TEMPORARY + if (flags & IPV6_AF_TEMPORARY) + return ipv6_maketemporaryaddress(addr, prefix, prefix_len, ifp); +#else + UNUSED(flags); +#endif + + if (ifo->options & DHCPCD_SLAACPRIVATE) { + dad = 0; + if (ipv6_makestableprivate(addr, + prefix, prefix_len, ifp, &dad) == -1) + return -1; + return dad; + } else if (!IN6_IS_ADDR_UNSPECIFIED(&ifo->token)) { + *addr = ifo->token; + return ipv6_makeprefix(addr, prefix, prefix_len); + } + + if (prefix_len > 64) { + errno = EINVAL; + return -1; + } + if ((ap = ipv6_linklocal(ifp)) == NULL) { + /* We delay a few functions until we get a local-link address + * so this should never be hit. */ + errno = ENOENT; + return -1; + } + + /* Make the address from the first local-link address */ + memcpy(addr, prefix, sizeof(*prefix)); + addr->s6_addr32[2] = ap->addr.s6_addr32[2]; + addr->s6_addr32[3] = ap->addr.s6_addr32[3]; + return 0; +} + static void in6_to_h64(uint64_t *vhigh, uint64_t *vlow, const struct in6_addr *addr) {