summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2015-01-27 10:31:19 +0000
committermpi <mpi@openbsd.org>2015-01-27 10:31:19 +0000
commit15f0a5b39a2bb226b44457ed81a5d989cfee0393 (patch)
tree0ea823943f9339ced713c5db55a70e177409cebe
parentDo not overwrite user-specified MTU. (diff)
downloadwireguard-openbsd-15f0a5b39a2bb226b44457ed81a5d989cfee0393.tar.xz
wireguard-openbsd-15f0a5b39a2bb226b44457ed81a5d989cfee0393.zip
Ensure that link-local addresses are correctly configured on loopback
interfaces. When the kernel automagically configures IPv6 addresses on loopback interfaces, start by assigning a link-local address and then try to assign "::1". Only the first configured loopback interface per rdomain can have the "::1" address. But even if other loopback interfaces failed to get this address, because it is already taken, give them a chance to have a link-local address. While here change in6_ifattach() to return an error value and remove duplicated code. Fix a regression introduced by the NOINET6 flag removal. ok henning@, stsp@, florian@, benno@
-rw-r--r--sys/net/if.c33
-rw-r--r--sys/netinet6/in6.c5
-rw-r--r--sys/netinet6/in6_ifattach.c88
-rw-r--r--sys/netinet6/in6_ifattach.h4
4 files changed, 42 insertions, 88 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 4b70862449a..a4dc97f0139 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.314 2015/01/27 03:17:36 dlg Exp $ */
+/* $OpenBSD: if.c,v 1.315 2015/01/27 10:31:19 mpi Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -1238,10 +1238,9 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
#ifdef INET6
case AF_INET6:
s = splsoftnet();
- if (cmd == SIOCIFAFATTACH) {
- if (in6ifa_ifpforlinklocal(ifp, 0) == NULL)
- in6_ifattach(ifp);
- } else
+ if (cmd == SIOCIFAFATTACH)
+ in6_ifattach(ifp);
+ else
in6_ifdetach(ifp);
splx(s);
return (0);
@@ -1307,16 +1306,11 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
#ifdef INET6
if (ISSET(ifr->ifr_flags, IFXF_AUTOCONF6)) {
- if (in6ifa_ifpforlinklocal(ifp, 0) == NULL) {
- s = splsoftnet();
- in6_ifattach(ifp);
- splx(s);
- }
+ s = splsoftnet();
+ in6_ifattach(ifp);
+ splx(s);
}
- if (ifr->ifr_flags & IFXF_AUTOCONF6)
- nd6_rs_output_set_timo(ND6_RS_OUTPUT_QUICK_INTERVAL);
-
if ((ifr->ifr_flags & IFXF_AUTOCONF6) &&
!(ifp->if_xflags & IFXF_AUTOCONF6)) {
nd6_rs_timeout_count++;
@@ -2199,19 +2193,16 @@ ifnewlladdr(struct ifnet *ifp)
arp_ifinit((struct arpcom *)ifp, ifa);
}
#ifdef INET6
- /* Update the link-local address. Don't do it if we're
- * a router to avoid confusing hosts on the network. */
+ /*
+ * Update the link-local address. Don't do it if we're
+ * a router to avoid confusing hosts on the network.
+ */
if (!ip6_forwarding) {
ifa = &in6ifa_ifpforlinklocal(ifp, 0)->ia_ifa;
if (ifa) {
in6_purgeaddr(ifa);
dohooks(ifp->if_addrhooks, 0);
- in6_ifattach_linklocal(ifp, NULL);
- if (in6if_do_dad(ifp)) {
- ifa = &in6ifa_ifpforlinklocal(ifp, 0)->ia_ifa;
- if (ifa)
- nd6_dad_start(ifa, NULL);
- }
+ in6_ifattach(ifp);
}
}
#endif
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 21553e6a220..39fe98d6c4e 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6.c,v 1.150 2015/01/24 00:29:06 deraadt Exp $ */
+/* $OpenBSD: in6.c,v 1.151 2015/01/27 10:31:19 mpi Exp $ */
/* $KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun Exp $ */
/*
@@ -478,8 +478,7 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp)
* is no link-local yet.
*/
s = splsoftnet();
- if (in6ifa_ifpforlinklocal(ifp, 0) == NULL)
- in6_ifattach(ifp);
+ in6_ifattach(ifp);
error = in6_update_ifa(ifp, ifra, ia6);
splx(s);
if (error != 0)
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index 75ddd13d91b..a9363527df8 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_ifattach.c,v 1.82 2015/01/26 11:38:37 mpi Exp $ */
+/* $OpenBSD: in6_ifattach.c,v 1.83 2015/01/27 10:31:19 mpi Exp $ */
/* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */
/*
@@ -57,8 +57,6 @@
#include <netinet6/ip6_mroute.h>
#endif
-int ip6_auto_linklocal = 1; /* enable by default */
-
int get_last_resort_ifid(struct ifnet *, struct in6_addr *);
int get_hw_ifid(struct ifnet *, struct in6_addr *);
int get_ifid(struct ifnet *, struct in6_addr *);
@@ -431,15 +429,12 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct in6_addr *ifid)
return 0;
}
-/*
- * ifp - must be IFT_LOOP
- */
-
int
in6_ifattach_loopback(struct ifnet *ifp)
{
struct in6_aliasreq ifra;
- int error;
+
+ KASSERT(ifp->if_flags & IFF_LOOPBACK);
bzero(&ifra, sizeof(ifra));
@@ -476,14 +471,7 @@ in6_ifattach_loopback(struct ifnet *ifp)
* We are sure that this is a newly assigned address, so we can set
* NULL to the 3rd arg.
*/
- if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) {
- nd6log((LOG_ERR, "in6_ifattach_loopback: failed to configure "
- "the loopback address on %s (errno=%d)\n",
- ifp->if_xname, error));
- return (-1);
- }
-
- return 0;
+ return (in6_update_ifa(ifp, &ifra, NULL));
}
/*
@@ -542,12 +530,11 @@ in6_nigroup(struct ifnet *ifp, const char *name, int namelen,
* nodelocal address needs to be configured onto only one of them.
* XXX multiple link-local address case
*/
-void
+int
in6_ifattach(struct ifnet *ifp)
{
struct ifaddr *ifa;
- struct in6_ifaddr *ia6;
- int dad_delay; /* delay ticks before DAD output */
+ int dad_delay = 0; /* delay ticks before DAD output */
/* some of the interfaces are inherently not IPv6 capable */
switch (ifp->if_type) {
@@ -555,7 +542,7 @@ in6_ifattach(struct ifnet *ifp)
case IFT_ENC:
case IFT_PFLOG:
case IFT_PFSYNC:
- return;
+ return (0);
}
/*
@@ -563,63 +550,40 @@ in6_ifattach(struct ifnet *ifp)
* remember there could be some link-layer that has special
* fragmentation logic.
*/
- if (ifp->if_mtu < IPV6_MMTU) {
- nd6log((LOG_INFO, "in6_ifattach: "
- "%s has too small MTU, IPv6 not enabled\n",
- ifp->if_xname));
- return;
- }
+ if (ifp->if_mtu < IPV6_MMTU)
+ return (EINVAL);
- /*
- * usually, we require multicast capability to the interface
- */
- if ((ifp->if_flags & IFF_MULTICAST) == 0) {
- nd6log((LOG_INFO, "in6_ifattach: "
- "%s is not multicast capable, IPv6 not enabled\n",
- ifp->if_xname));
- return;
- }
+ if ((ifp->if_flags & IFF_MULTICAST) == 0)
+ return (EINVAL);
- /*
- * assign loopback address for loopback interface.
- * XXX multiple loopback interface case.
- */
- if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
- struct in6_addr in6 = in6addr_loopback;
- if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {
- if (in6_ifattach_loopback(ifp) != 0)
- return;
+ /* Assign a link-local address, if there's none. */
+ if (in6ifa_ifpforlinklocal(ifp, 0) == NULL) {
+ if (in6_ifattach_linklocal(ifp, NULL) != 0) {
+ /* failed to assign linklocal address. bark? */
}
}
- /*
- * assign a link-local address, if there's none.
- */
- if (ip6_auto_linklocal) {
- ia6 = in6ifa_ifpforlinklocal(ifp, 0);
- if (ia6 == NULL) {
- if (in6_ifattach_linklocal(ifp, NULL) == 0) {
- /* linklocal address assigned */
- } else {
- /* failed to assign linklocal address. bark? */
- }
- }
+ /* Assign loopback address, if there's none. */
+ if (ifp->if_flags & IFF_LOOPBACK) {
+ struct in6_addr in6 = in6addr_loopback;
+ if (in6ifa_ifpwithaddr(ifp, &in6) != NULL)
+ return (0);
+
+ return (in6_ifattach_loopback(ifp));
}
- /*
- * perform DAD.
- */
- dad_delay = 0;
+ /* Perform DAD. */
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
- ia6 = ifatoia6(ifa);
- if (ia6->ia6_flags & IN6_IFF_TENTATIVE)
+ if (ifatoia6(ifa)->ia6_flags & IN6_IFF_TENTATIVE)
nd6_dad_start(ifa, &dad_delay);
}
if (ifp->if_xflags & IFXF_AUTOCONF6)
nd6_rs_output_set_timo(ND6_RS_OUTPUT_QUICK_INTERVAL);
+
+ return (0);
}
/*
diff --git a/sys/netinet6/in6_ifattach.h b/sys/netinet6/in6_ifattach.h
index 6f574d6e1be..6160fb984a6 100644
--- a/sys/netinet6/in6_ifattach.h
+++ b/sys/netinet6/in6_ifattach.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_ifattach.h,v 1.6 2014/01/07 16:34:05 stsp Exp $ */
+/* $OpenBSD: in6_ifattach.h,v 1.7 2015/01/27 10:31:19 mpi Exp $ */
/* $KAME: in6_ifattach.h,v 1.9 2000/04/12 05:35:48 itojun Exp $ */
/*
@@ -34,7 +34,7 @@
#define _NETINET6_IN6_IFATTACH_H_
#ifdef _KERNEL
-void in6_ifattach(struct ifnet *);
+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 *);