-/* $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 $ */
/*
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
-/* $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 $ */
/*
#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)
-/* $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 $ */
/*
#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 */
{ "ifq", CTLTYPE_NODE }, \
{ "mrtmif", CTLTYPE_STRUCT }, \
{ "mrtmfc", CTLTYPE_STRUCT }, \
+ { "soiikey", CTLTYPE_STRING }, /* binary string */ \
}
#define IPV6CTL_VARS { \
-/* $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 $ */
/*
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 *);
#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.
*
return 0;
}
+/*
+ * 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
{
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));
-/* $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 $ */
/*
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_ */
-/* $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 $ */
/*
#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>
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;
return (ret);
}
+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)
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();
-/* $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 $ */
/*
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;