]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
inet6: Support Tokenised IPv6 Identifiers
authorRoy Marples <roy@marples.name>
Tue, 30 Aug 2022 09:48:11 +0000 (10:48 +0100)
committerRoy Marples <roy@marples.name>
Tue, 30 Aug 2022 09:48:11 +0000 (10:48 +0100)
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.

src/dhcpcd.conf.5.in
src/if-options.c
src/if-options.h
src/ipv6.c

index f00df3e1999329193e4a019f38bd4b3f9462d6a9..742f39f2b06f7f4cb1acb77fd061af63afee6dd4 100644 (file)
@@ -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
index 46ea7ea0199d8b27826e2d7de2efa6d27fc38cd6..fe490fbb765b2d27710bb3c171104ba349dd7fca 100644 (file)
@@ -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;
index f80119d6c15fa1c4cf695dee1d1ea380689a5da9..4b252826fccc929d99073fa9134adea49bffe0f3 100644 (file)
@@ -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;
index 04bf7746e080727dd20cb38e54624e1d17513eeb..d8e00de3be56d728452631344141b3c34d2300d9 100644 (file)
@@ -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)
 {