diff options
author | Florian Obser <florian@cvs.openbsd.org> | 2018-02-10 05:52:09 +0000 |
---|---|---|
committer | Florian Obser <florian@cvs.openbsd.org> | 2018-02-10 05:52:09 +0000 |
commit | e5ab4005935ce5c8fe35b8486f9547bd9a811db0 (patch) | |
tree | d04eeda59a2567e8e28c47fef25ed14d2528d5ab /sys/netinet6/in6_ifattach.c | |
parent | 248494399c176361309dd6387ca61e2d5b0c1307 (diff) |
Implement RFC 7217: "A Method for Generating Semantically Opaque
Interface Identifiers with IPv6 Stateless Address Autoconfiguration."
"An IPv6 address configured using this method is stable within each
subnet, but the corresponding Interface Identifier changes when the
host moves from one network to another. This method is meant to be an
alternative to generating Interface Identifiers based on hardware
addresses."
OK naddy, sthen
Diffstat (limited to 'sys/netinet6/in6_ifattach.c')
-rw-r--r-- | sys/netinet6/in6_ifattach.c | 69 |
1 files changed, 67 insertions, 2 deletions
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index 87614373686..0aa10fad94b 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6_ifattach.c,v 1.104 2017/09/01 16:48:27 florian Exp $ */ +/* $OpenBSD: in6_ifattach.c,v 1.105 2018/02/10 05:52:08 florian Exp $ */ /* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */ /* @@ -58,6 +58,7 @@ void in6_get_rand_ifid(struct ifnet *, struct in6_addr *); int in6_get_hw_ifid(struct ifnet *, struct in6_addr *); +int in6_get_soii_ifid(struct ifnet *, struct in6_addr *); void in6_get_ifid(struct ifnet *, struct in6_addr *); int in6_ifattach_loopback(struct ifnet *); @@ -72,6 +73,24 @@ int in6_ifattach_loopback(struct ifnet *); #define IFID_LOCAL(in6) (!EUI64_LOCAL(in6)) #define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6)) +void +in6_soiiupdate(struct ifnet *ifp) +{ + struct ifaddr *ifa; + + NET_ASSERT_LOCKED(); + + /* + * Update the link-local address. + */ + ifa = &in6ifa_ifpforlinklocal(ifp, 0)->ia_ifa; + if (ifa) { + in6_purgeaddr(ifa); + dohooks(ifp->if_addrhooks, 0); + in6_ifattach(ifp); + } +} + /* * Generate a random interface identifier. * @@ -192,6 +211,45 @@ in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6) } /* + * Generate a Semantically Opaque Interface Identifier according to RFC 7217 + * + * in6 - upper 64bits are preserved + */ +int +in6_get_soii_ifid(struct ifnet *ifp, struct in6_addr *in6) +{ + SHA2_CTX ctx; + u_int8_t digest[SHA512_DIGEST_LENGTH]; + struct in6_addr prefix; + struct sockaddr_dl *sdl; + int dad_counter = 0; /* XXX not used */ + char *addr; + + if (ifp->if_xflags & IFXF_INET6_NOSOII) + return -1; + + sdl = ifp->if_sadl; + if (sdl == NULL || sdl->sdl_alen == 0) + return -1; + + memset(&prefix, 0, sizeof(prefix)); + prefix.s6_addr16[0] = htons(0xfe80); + addr = LLADDR(sdl); + + SHA512Init(&ctx); + + SHA512Update(&ctx, &prefix, sizeof(prefix)); + SHA512Update(&ctx, addr, sdl->sdl_alen); + SHA512Update(&ctx, &dad_counter, sizeof(dad_counter)); + SHA512Update(&ctx, ip6_soiikey, sizeof(ip6_soiikey)); + SHA512Final(digest, &ctx); + + bcopy(digest, &in6->s6_addr[8], 8); + + return 0; +} + +/* * Get interface identifier for the specified interface. If it is not * available on ifp0, borrow interface identifier from other information * sources. @@ -201,7 +259,14 @@ in6_get_ifid(struct ifnet *ifp0, struct in6_addr *in6) { struct ifnet *ifp; - /* first, try to get it from the interface itself */ + /* first, try to generate a Semantically Opaque Interface Identifier */ + if (in6_get_soii_ifid(ifp0, in6) == 0) { + nd6log((LOG_DEBUG, "%s: got Semantically Opaque Interface " + "Identifier\n", ifp0->if_xname)); + goto success; + } + + /* next, try to get it from the interface itself */ if (in6_get_hw_ifid(ifp0, in6) == 0) { nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n", ifp0->if_xname)); |