RFC 7217 support for slaacd
authorflorian <florian@openbsd.org>
Sat, 10 Feb 2018 05:57:59 +0000 (05:57 +0000)
committerflorian <florian@openbsd.org>
Sat, 10 Feb 2018 05:57:59 +0000 (05:57 +0000)
OK naddy, sthen

sbin/slaacd/engine.c
sbin/slaacd/frontend.c
sbin/slaacd/slaacd.c
sbin/slaacd/slaacd.h

index 23ff8ec..f2424c3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: engine.c,v 1.19 2017/11/04 17:23:05 florian Exp $     */
+/*     $OpenBSD: engine.c,v 1.20 2018/02/10 05:57:59 florian Exp $     */
 
 /*
  * Copyright (c) 2017 Florian Obser <florian@openbsd.org>
@@ -64,6 +64,8 @@
 #include <netinet6/nd6.h>
 #include <netinet/icmp6.h>
 
+#include <crypto/sha2.h>
+
 #include <errno.h>
 #include <event.h>
 #include <imsg.h>
@@ -179,6 +181,7 @@ struct address_proposal {
        uint8_t                          prefix_len;
        uint32_t                         vltime;
        uint32_t                         pltime;
+       uint8_t                          soiikey[SLAACD_SOIIKEY_LEN];
 };
 
 struct dfr_proposal {
@@ -204,8 +207,10 @@ struct slaacd_iface {
        uint32_t                         if_index;
        int                              running;
        int                              autoconfprivacy;
+       int                              soii;
        struct ether_addr                hw_address;
        struct sockaddr_in6              ll_address;
+       uint8_t                          soiikey[SLAACD_SOIIKEY_LEN];
        LIST_HEAD(, radv)                radvs;
        LIST_HEAD(, address_proposal)    addr_proposals;
        LIST_HEAD(, dfr_proposal)        dfr_proposals;
@@ -618,12 +623,15 @@ engine_dispatch_main(int fd, short event, void *bula)
                                        iface->state = IF_DOWN;
                                iface->autoconfprivacy =
                                    imsg_ifinfo.autoconfprivacy;
+                               iface->soii = imsg_ifinfo.soii;
                                memcpy(&iface->hw_address,
                                    &imsg_ifinfo.hw_address,
                                    sizeof(struct ether_addr));
                                memcpy(&iface->ll_address,
                                    &imsg_ifinfo.ll_address,
                                    sizeof(struct sockaddr_in6));
+                               memcpy(iface->soiikey, imsg_ifinfo.soiikey,
+                                   sizeof(iface->soiikey));
                                LIST_INIT(&iface->radvs);
                                LIST_INSERT_HEAD(&slaacd_interfaces,
                                    iface, entries);
@@ -638,6 +646,14 @@ engine_dispatch_main(int fd, short event, void *bula)
                                            imsg_ifinfo.autoconfprivacy;
                                        need_refresh = 1;
                                }
+
+                               if (iface->soii !=
+                                   imsg_ifinfo.soii) {
+                                       iface->soii =
+                                           imsg_ifinfo.soii;
+                                       need_refresh = 1;
+                               }
+
                                if (memcmp(&iface->hw_address,
                                            &imsg_ifinfo.hw_address,
                                            sizeof(struct ether_addr)) != 0) {
@@ -646,6 +662,14 @@ engine_dispatch_main(int fd, short event, void *bula)
                                            sizeof(struct ether_addr));
                                        need_refresh = 1;
                                }
+                               if (memcmp(iface->soiikey,
+                                           imsg_ifinfo.soiikey,
+                                           sizeof(iface->soiikey)) != 0) {
+                                       memcpy(iface->soiikey,
+                                           imsg_ifinfo.soiikey,
+                                           sizeof(iface->soiikey));
+                                       need_refresh = 1;
+                               }
 
                                if (iface->state != IF_DOWN &&
                                    imsg_ifinfo.running && need_refresh)
@@ -763,6 +787,7 @@ send_interface_info(struct slaacd_iface *iface, pid_t pid)
        cei.if_index = iface->if_index;
        cei.running = iface->running;
        cei.autoconfprivacy = iface->autoconfprivacy;
+       cei.soii = iface->soii;
        memcpy(&cei.hw_address, &iface->hw_address, sizeof(struct ether_addr));
        memcpy(&cei.ll_address, &iface->ll_address,
            sizeof(struct sockaddr_in6));
@@ -1209,7 +1234,10 @@ void
 gen_addr(struct slaacd_iface *iface, struct radv_prefix *prefix, struct
     address_proposal *addr_proposal, int privacy)
 {
+       SHA2_CTX ctx;
        struct in6_addr priv_in6;
+       int dad_counter = 0; /* XXX not used */
+       u_int8_t digest[SHA512_DIGEST_LENGTH];
 
        /* from in6_ifadd() in nd6_rtr.c */
        /* XXX from in6.h, guarded by #ifdef _KERNEL   XXX nonstandard */
@@ -1256,20 +1284,33 @@ gen_addr(struct slaacd_iface *iface, struct radv_prefix *prefix, struct
                addr_proposal->addr.sin6_addr.s6_addr32[3] |=
                    (priv_in6.s6_addr32[3] & ~addr_proposal->mask.s6_addr32[3]);
        } else {
-               addr_proposal->addr.sin6_addr.s6_addr32[0] |=
-                   (iface->ll_address.sin6_addr.s6_addr32[0] &
-                   ~addr_proposal->mask.s6_addr32[0]);
-               addr_proposal->addr.sin6_addr.s6_addr32[1] |=
-                   (iface->ll_address.sin6_addr.s6_addr32[1] &
-                   ~addr_proposal->mask.s6_addr32[1]);
-               addr_proposal->addr.sin6_addr.s6_addr32[2] |=
-                   (iface->ll_address.sin6_addr.s6_addr32[2] &
-                   ~addr_proposal->mask.s6_addr32[2]);
-               addr_proposal->addr.sin6_addr.s6_addr32[3] |=
-                   (iface->ll_address.sin6_addr.s6_addr32[3] &
-                   ~addr_proposal->mask.s6_addr32[3]);
+               if (iface->soii) {
+                       SHA512Init(&ctx);
+                       SHA512Update(&ctx, &prefix->prefix,
+                           sizeof(prefix->prefix));
+                       SHA512Update(&ctx, &iface->hw_address,
+                           sizeof(iface->hw_address));
+                       SHA512Update(&ctx, &dad_counter, sizeof(dad_counter));
+                       SHA512Update(&ctx, addr_proposal->soiikey,
+                           sizeof(addr_proposal->soiikey));
+                       SHA512Final(digest, &ctx);
+                       memcpy(&addr_proposal->addr.sin6_addr.s6_addr[8],
+                           digest, 8);
+               } else {
+                       addr_proposal->addr.sin6_addr.s6_addr32[0] |=
+                           (iface->ll_address.sin6_addr.s6_addr32[0] &
+                           ~addr_proposal->mask.s6_addr32[0]);
+                       addr_proposal->addr.sin6_addr.s6_addr32[1] |=
+                           (iface->ll_address.sin6_addr.s6_addr32[1] &
+                           ~addr_proposal->mask.s6_addr32[1]);
+                       addr_proposal->addr.sin6_addr.s6_addr32[2] |=
+                           (iface->ll_address.sin6_addr.s6_addr32[2] &
+                           ~addr_proposal->mask.s6_addr32[2]);
+                       addr_proposal->addr.sin6_addr.s6_addr32[3] |=
+                           (iface->ll_address.sin6_addr.s6_addr32[3] &
+                           ~addr_proposal->mask.s6_addr32[3]);
+               }
        }
-
 #undef s6_addr32
 }
 
@@ -1650,6 +1691,11 @@ void update_iface_ra(struct slaacd_iface *iface, struct radv *ra)
                                    sizeof(addr_proposal->hw_address)) != 0)
                                        continue;
 
+                               if (memcmp(&addr_proposal->soiikey,
+                                   &iface->soiikey,
+                                   sizeof(addr_proposal->soiikey)) != 0)
+                                       continue;
+
                                if (addr_proposal->privacy) {
                                        /*
                                         * create new privacy address if old
@@ -1797,6 +1843,8 @@ gen_address_proposal(struct slaacd_iface *iface, struct radv *ra, struct
        addr_proposal->if_index = iface->if_index;
        memcpy(&addr_proposal->hw_address, &iface->hw_address,
            sizeof(addr_proposal->hw_address));
+       memcpy(&addr_proposal->soiikey, &iface->soiikey,
+           sizeof(addr_proposal->soiikey));
        addr_proposal->privacy = privacy;
        memcpy(&addr_proposal->prefix, &prefix->prefix,
            sizeof(addr_proposal->prefix));
index 3a193e2..171cfe2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: frontend.c,v 1.10 2017/12/10 10:07:54 florian Exp $   */
+/*     $OpenBSD: frontend.c,v 1.11 2018/02/10 05:57:59 florian Exp $   */
 
 /*
  * Copyright (c) 2017 Florian Obser <florian@openbsd.org>
@@ -490,6 +490,7 @@ update_iface(uint32_t if_index, char* if_name)
        imsg_ifinfo.running = (flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP |
            IFF_RUNNING);
        imsg_ifinfo.autoconfprivacy = !(xflags & IFXF_INET6_NOPRIVACY);
+       imsg_ifinfo.soii = !(xflags & IFXF_INET6_NOSOII);
        get_lladdr(if_name, &imsg_ifinfo.hw_address, &imsg_ifinfo.ll_address);
 
        memcpy(&nd_opt_source_link_addr, &imsg_ifinfo.hw_address,
index 628031f..fe895f9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: slaacd.c,v 1.14 2017/12/10 17:34:05 stsp Exp $        */
+/*     $OpenBSD: slaacd.c,v 1.15 2018/02/10 05:57:59 florian Exp $     */
 
 /*
  * Copyright (c) 2017 Florian Obser <florian@openbsd.org>
@@ -23,6 +23,7 @@
 #include <sys/queue.h>
 #include <sys/socket.h>
 #include <sys/syslog.h>
+#include <sys/sysctl.h>
 #include <sys/uio.h>
 #include <sys/wait.h>
 
@@ -100,6 +101,7 @@ void        configure_interface(struct imsg_configure_address *);
 void   configure_gateway(struct imsg_configure_dfr *, uint8_t);
 void   add_gateway(struct imsg_configure_dfr *);
 void   delete_gateway(struct imsg_configure_dfr *);
+int    get_soiikey(uint8_t *);
 
 static int     main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *);
 int            main_imsg_compose_frontend(int, pid_t, void *, uint16_t);
@@ -470,8 +472,11 @@ main_dispatch_frontend(int fd, short event, void *bula)
                                fatal("%s: IMSG_UPDATE_IF wrong length: %d",
                                    __func__, imsg.hdr.len);
                        memcpy(&imsg_ifinfo, imsg.data, sizeof(imsg_ifinfo));
-                       main_imsg_compose_engine(IMSG_UPDATE_IF, 0,
-                           &imsg_ifinfo, sizeof(imsg_ifinfo));
+                       if (get_soiikey(imsg_ifinfo.soiikey) == -1)
+                               log_warn("get_soiikey");
+                       else
+                               main_imsg_compose_engine(IMSG_UPDATE_IF, 0,
+                                   &imsg_ifinfo, sizeof(imsg_ifinfo));
                        break;
                default:
                        log_debug("%s: error handling imsg %d", __func__,
@@ -885,3 +890,12 @@ sin6_to_str(struct sockaddr_in6 *sin6)
        return hbuf;
 }
 #endif /* SMALL */
+
+int
+get_soiikey(uint8_t *key)
+{
+       int      mib[4] = {CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_SOIIKEY};
+       size_t   size = SLAACD_SOIIKEY_LEN;
+
+       return sysctl(mib, sizeof(mib) / sizeof(mib[0]), key, &size, NULL, 0);
+}
index 9e2fe0f..f824411 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: slaacd.h,v 1.11 2017/12/10 10:07:54 florian Exp $     */
+/*     $OpenBSD: slaacd.h,v 1.12 2018/02/10 05:57:59 florian Exp $     */
 
 /*
  * Copyright (c) 2017 Florian Obser <florian@openbsd.org>
@@ -21,6 +21,8 @@
 #define        SLAACD_SOCKET           "/dev/slaacd.sock"
 #define SLAACD_USER            "_slaacd"
 
+#define SLAACD_SOIIKEY_LEN     16
+
 /* MAXDNAME from arpa/namesr.h */
 #define SLAACD_MAX_DNSSL       1025
 
@@ -90,6 +92,7 @@ struct ctl_engine_info {
        uint32_t                if_index;
        int                     running;
        int                     autoconfprivacy;
+       int                     soii;
        struct ether_addr       hw_address;
        struct sockaddr_in6     ll_address;
 };
@@ -169,8 +172,10 @@ struct imsg_ifinfo {
        uint32_t                if_index;
        int                     running;
        int                     autoconfprivacy;
+       int                     soii;
        struct ether_addr       hw_address;
        struct sockaddr_in6     ll_address;
+       uint8_t                 soiikey[SLAACD_SOIIKEY_LEN];
 };
 
 struct imsg_del_addr {