Ensure that link-local addresses are correctly configured on loopback
authormpi <mpi@openbsd.org>
Tue, 27 Jan 2015 10:31:19 +0000 (10:31 +0000)
committermpi <mpi@openbsd.org>
Tue, 27 Jan 2015 10:31:19 +0000 (10:31 +0000)
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@

sys/net/if.c
sys/netinet6/in6.c
sys/netinet6/in6_ifattach.c
sys/netinet6/in6_ifattach.h

index 4b70862..a4dc97f 100644 (file)
@@ -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
index 21553e6..39fe98d 100644 (file)
@@ -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)
index 75ddd13..a936352 100644 (file)
@@ -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);
 }
 
 /*
index 6f574d6..6160fb9 100644 (file)
@@ -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 *);