diff options
author | Florian Obser <florian@cvs.openbsd.org> | 2018-02-10 05:58:00 +0000 |
---|---|---|
committer | Florian Obser <florian@cvs.openbsd.org> | 2018-02-10 05:58:00 +0000 |
commit | 040fcac5496fcb05243ae57288d3169ddfb1dbc1 (patch) | |
tree | 0cec2851feb146098fa4f08a5912fc6f0b57ab9c /sbin | |
parent | dc78b166bf4558328cfbe1dcab7c6cf45914c4c6 (diff) |
RFC 7217 support for slaacd
OK naddy, sthen
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/slaacd/engine.c | 76 | ||||
-rw-r--r-- | sbin/slaacd/frontend.c | 3 | ||||
-rw-r--r-- | sbin/slaacd/slaacd.c | 20 | ||||
-rw-r--r-- | sbin/slaacd/slaacd.h | 7 |
4 files changed, 87 insertions, 19 deletions
diff --git a/sbin/slaacd/engine.c b/sbin/slaacd/engine.c index 23ff8ec3534..f2424c392f2 100644 --- a/sbin/slaacd/engine.c +++ b/sbin/slaacd/engine.c @@ -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)); diff --git a/sbin/slaacd/frontend.c b/sbin/slaacd/frontend.c index 3a193e2a00f..171cfe251b0 100644 --- a/sbin/slaacd/frontend.c +++ b/sbin/slaacd/frontend.c @@ -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, diff --git a/sbin/slaacd/slaacd.c b/sbin/slaacd/slaacd.c index 628031f9049..fe895f906b0 100644 --- a/sbin/slaacd/slaacd.c +++ b/sbin/slaacd/slaacd.c @@ -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); +} diff --git a/sbin/slaacd/slaacd.h b/sbin/slaacd/slaacd.h index 9e2fe0fc5b8..f824411da32 100644 --- a/sbin/slaacd/slaacd.h +++ b/sbin/slaacd/slaacd.h @@ -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 { |