diff options
-rw-r--r-- | sys/net/if.c | 15 | ||||
-rw-r--r-- | sys/net/if.h | 3 | ||||
-rw-r--r-- | sys/netinet6/in6.h | 6 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.c | 69 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.h | 3 | ||||
-rw-r--r-- | sys/netinet6/ip6_input.c | 37 | ||||
-rw-r--r-- | sys/netinet6/ip6_var.h | 5 |
7 files changed, 129 insertions, 9 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index e450decf5ed..94df391bd8a 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.542 2018/02/10 05:32:21 claudio Exp $ */ +/* $OpenBSD: if.c,v 1.543 2018/02/10 05:52:08 florian Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -1922,6 +1922,19 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p) break; } } + + if (ISSET(ifr->ifr_flags, IFXF_INET6_NOSOII) && + !ISSET(ifp->if_xflags, IFXF_INET6_NOSOII)) { + ifp->if_xflags |= IFXF_INET6_NOSOII; + in6_soiiupdate(ifp); + } + + if (!ISSET(ifr->ifr_flags, IFXF_INET6_NOSOII) && + ISSET(ifp->if_xflags, IFXF_INET6_NOSOII)) { + ifp->if_xflags &= ~IFXF_INET6_NOSOII; + in6_soiiupdate(ifp); + } + #endif /* INET6 */ #ifdef MPLS diff --git a/sys/net/if.h b/sys/net/if.h index fbee692ba32..39ccfa3c18a 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if.h,v 1.190 2018/01/16 10:33:55 mpi Exp $ */ +/* $OpenBSD: if.h,v 1.191 2018/02/10 05:52:08 florian Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -221,6 +221,7 @@ struct if_status_description { #define IFXF_MPLS 0x8 /* [N] supports MPLS */ #define IFXF_WOL 0x10 /* [N] wake on lan enabled */ #define IFXF_AUTOCONF6 0x20 /* [N] v6 autoconf enabled */ +#define IFXF_INET6_NOSOII 0x40 /* [N] don't do RFC 7217 */ #define IFXF_CANTCHANGE \ (IFXF_MPSAFE|IFXF_CLONED) diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h index 6ea62f9fbd2..337f48738cf 100644 --- a/sys/netinet6/in6.h +++ b/sys/netinet6/in6.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in6.h,v 1.100 2017/11/20 10:35:24 mpi Exp $ */ +/* $OpenBSD: in6.h,v 1.101 2018/02/10 05:52:08 florian Exp $ */ /* $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $ */ /* @@ -590,7 +590,8 @@ ifatoia6(struct ifaddr *ifa) #define IPV6CTL_IFQUEUE 51 #define IPV6CTL_MRTMIF 52 #define IPV6CTL_MRTMFC 53 -#define IPV6CTL_MAXID 54 +#define IPV6CTL_SOIIKEY 54 +#define IPV6CTL_MAXID 55 /* New entries should be added here from current IPV6CTL_MAXID value. */ /* to define items, should talk with KAME guys first, for *BSD compatibility */ @@ -650,6 +651,7 @@ ifatoia6(struct ifaddr *ifa) { "ifq", CTLTYPE_NODE }, \ { "mrtmif", CTLTYPE_STRUCT }, \ { "mrtmfc", CTLTYPE_STRUCT }, \ + { "soiikey", CTLTYPE_STRING }, /* binary string */ \ } #define IPV6CTL_VARS { \ 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)); diff --git a/sys/netinet6/in6_ifattach.h b/sys/netinet6/in6_ifattach.h index 6160fb984a6..0f54b457de9 100644 --- a/sys/netinet6/in6_ifattach.h +++ b/sys/netinet6/in6_ifattach.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in6_ifattach.h,v 1.7 2015/01/27 10:31:19 mpi Exp $ */ +/* $OpenBSD: in6_ifattach.h,v 1.8 2018/02/10 05:52:08 florian Exp $ */ /* $KAME: in6_ifattach.h,v 1.9 2000/04/12 05:35:48 itojun Exp $ */ /* @@ -38,6 +38,7 @@ int in6_ifattach(struct ifnet *); void in6_ifdetach(struct ifnet *); int in6_nigroup(struct ifnet *, const char *, int, struct sockaddr_in6 *); int in6_ifattach_linklocal(struct ifnet *, struct in6_addr *); +void in6_soiiupdate(struct ifnet *); #endif /* _KERNEL */ #endif /* _NETINET6_IN6_IFATTACH_H_ */ diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index b7dc6287e5a..60006380e9f 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_input.c,v 1.211 2018/02/01 21:11:33 bluhm Exp $ */ +/* $OpenBSD: ip6_input.c,v 1.212 2018/02/10 05:52:08 florian Exp $ */ /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */ /* @@ -92,6 +92,7 @@ #include <netinet/in_pcb.h> #include <netinet/ip_var.h> #include <netinet6/in6_var.h> +#include <netinet6/in6_ifattach.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet/icmp6.h> @@ -118,12 +119,15 @@ struct niqueue ip6intrq = NIQUEUE_INITIALIZER(IPQ_MAXLEN, NETISR_IPV6); struct cpumem *ip6counters; +uint8_t ip6_soiikey[IP6_SOIIKEY_LEN]; + int ip6_ours(struct mbuf **, int *, int, int); int ip6_local(struct mbuf **, int *, int, int); int ip6_check_rh0hdr(struct mbuf *, int *); int ip6_hbhchcheck(struct mbuf *, int *, int *, int *); int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *); struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); +int ip6_sysctl_soiikey(void *, size_t *, void *, size_t); static struct mbuf_queue ip6send_mq; @@ -1367,6 +1371,35 @@ ip6_sysctl_ip6stat(void *oldp, size_t *oldlenp, void *newp) } int +ip6_sysctl_soiikey(void *oldp, size_t *oldlenp, void *newp, size_t newlen) +{ + struct ifnet *ifp; + uint8_t oldkey[16]; + int error; + + error = suser(curproc, 0); + if (error != 0) + return (error); + + memcpy(oldkey, ip6_soiikey, sizeof(oldkey)); + + error = sysctl_struct(oldp, oldlenp, newp, newlen, ip6_soiikey, + sizeof(ip6_soiikey)); + + if (!error && memcmp(ip6_soiikey, oldkey, sizeof(oldkey)) != 0) { + TAILQ_FOREACH(ifp, &ifnet, if_list) { + if (ifp->if_flags & IFF_LOOPBACK) + continue; + NET_LOCK(); + in6_soiiupdate(ifp); + NET_UNLOCK(); + } + } + + return (error); +} + +int ip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { @@ -1429,6 +1462,8 @@ ip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, case IPV6CTL_IFQUEUE: return (sysctl_niq(name + 1, namelen - 1, oldp, oldlenp, newp, newlen, &ip6intrq)); + case IPV6CTL_SOIIKEY: + return (ip6_sysctl_soiikey(oldp, oldlenp, newp, newlen)); default: if (name[0] < IPV6CTL_MAXID) { NET_LOCK(); diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h index 2e62ac01540..c6fcbef957a 100644 --- a/sys/netinet6/ip6_var.h +++ b/sys/netinet6/ip6_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_var.h,v 1.82 2018/02/01 21:11:33 bluhm Exp $ */ +/* $OpenBSD: ip6_var.h,v 1.83 2018/02/10 05:52:08 florian Exp $ */ /* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */ /* @@ -292,6 +292,9 @@ extern int ip6_dad_pending; /* number of currently running DADs */ extern int ip6_auto_flowlabel; extern int ip6_auto_linklocal; +#define IP6_SOIIKEY_LEN 16 +extern uint8_t ip6_soiikey[IP6_SOIIKEY_LEN]; + struct in6pcb; struct inpcb; |