Remove the NOINET6 interface flag, a left-over from the times when IPv6
authorstsp <stsp@openbsd.org>
Tue, 6 Jan 2015 21:26:46 +0000 (21:26 +0000)
committerstsp <stsp@openbsd.org>
Tue, 6 Jan 2015 21:26:46 +0000 (21:26 +0000)
was enabled by default. Add AFATTACH/AFDETACH ioctls which enable/disable
an address family for an interface (currently used for IPv6 only).

New kernel needs new ifconfig for IPv6 configuration (address assignment
still works with old ifconfig making this easy to cross over).

Committing on behalf of henning@ who is currently lebensmittelvergiftet.
ok stsp, benno, mpi

sbin/ifconfig/ifconfig.c
sys/net/if.c
sys/net/if.h
sys/netinet6/in6.c
sys/netinet6/in6_ifattach.c
sys/sys/sockio.h

index 95819b4..cc361b9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ifconfig.c,v 1.292 2015/01/04 12:30:39 mpi Exp $      */
+/*     $OpenBSD: ifconfig.c,v 1.293 2015/01/06 21:26:46 stsp Exp $     */
 /*     $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $      */
 
 /*
@@ -148,6 +148,7 @@ void        setiflladdr(const char *, int);
 void   setifdstaddr(const char *, int);
 void   setifflags(const char *, int);
 void   setifxflags(const char *, int);
+void   addaf(const char *, int);
 void   removeaf(const char *, int);
 void   setifbroadaddr(const char *, int);
 void   setifmtu(const char *, int);
@@ -676,7 +677,7 @@ main(int argc, char *argv[])
        }
 #ifdef INET6
        if (argc != 0 && af == AF_INET6)
-               setifxflags("inet6", -IFXF_NOINET6);
+               addaf(name, AF_INET6);
 #endif
        while (argc > 0) {
                const struct cmd *p;
@@ -1252,19 +1253,26 @@ setifxflags(const char *vname, int value)
                warn("SIOCSIFXFLAGS");
 }
 
+void
+addaf(const char *vname, int value)
+{
+       struct if_afreq ifar;
+
+       strlcpy(ifar.ifar_name, name, sizeof(ifar.ifar_name));
+       ifar.ifar_af = value;
+       if (ioctl(s, SIOCIFAFATTACH, (caddr_t)&ifar) < 0)
+               warn("SIOCIFAFATTACH");
+}
+
 void
 removeaf(const char *vname, int value)
 {
-       switch (value) {
-#ifdef INET6
-       case AF_INET6:
-               setifxflags(vname, IFXF_NOINET6);
-               setifxflags(vname, -IFXF_AUTOCONF6);
-               break;
-#endif
-       default:
-               errx(1, "removeaf not implemented for this AF");
-       }
+       struct if_afreq ifar;
+
+       strlcpy(ifar.ifar_name, name, sizeof(ifar.ifar_name));
+       ifar.ifar_af = value;
+       if (ioctl(s, SIOCIFAFDETACH, (caddr_t)&ifar) < 0)
+               warn("SIOCIFAFDETACH");
 }
 
 #ifdef INET6
@@ -1326,7 +1334,9 @@ setia6eui64(const char *cmd, int val)
 
        if (afp->af_af != AF_INET6)
                errx(1, "%s not allowed for the AF", cmd);
-       setifxflags("inet6", -IFXF_NOINET6);
+#ifdef INET6
+       addaf(name, AF_INET6);
+#endif
        in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr;
        if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0)
                errx(1, "interface index is already filled");
index 55161b8..9b2f035 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if.c,v 1.309 2014/12/19 17:14:39 tedu Exp $   */
+/*     $OpenBSD: if.c,v 1.310 2015/01/06 21:26:46 stsp Exp $   */
 /*     $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $  */
 
 /*
@@ -383,10 +383,6 @@ if_attach(struct ifnet *ifp)
 #else
        TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
 #endif
-#ifdef INET6
-       ifp->if_xflags |= IFXF_NOINET6;
-#endif
-
        if_attachsetup(ifp);
 }
 
@@ -1100,10 +1096,9 @@ if_up(struct ifnet *ifp)
 #endif
        rt_ifmsg(ifp);
 #ifdef INET6
-       if (!(ifp->if_xflags & IFXF_NOINET6))
+       if (ifp == lo0ifp)      /* lo0 is special - needs ::1 */
                in6_if_up(ifp);
 #endif
-
 #ifndef SMALL_KERNEL
        rt_if_track(ifp);
 #endif
@@ -1195,6 +1190,7 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
        struct ifreq *ifr;
        struct sockaddr_dl *sdl;
        struct ifgroupreq *ifgr;
+       struct if_afreq *ifar;
        char ifdescrbuf[IFDESCRSIZE];
        char ifrtlabelbuf[RTLABEL_LEN];
        int s, error = 0;
@@ -1229,6 +1225,28 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
                if ((error = suser(p, 0)) != 0)
                        return (error);
                return (if_setgroupattribs(data));
+       case SIOCIFAFATTACH:
+       case SIOCIFAFDETACH:
+               if ((error = suser(p, 0)) != 0)
+                       return (error);
+               ifar = (struct if_afreq *)data;
+               if ((ifp = ifunit(ifar->ifar_name)) == NULL)
+                       return (ENXIO);
+               switch (ifar->ifar_af) {
+#ifdef INET6
+               case AF_INET6:
+                       s = splsoftnet();
+                       if (cmd == SIOCIFAFATTACH) {
+                               if (in6ifa_ifpforlinklocal(ifp, 0) == NULL)
+                                       in6_if_up(ifp);
+                       } else
+                               in6_ifdetach(ifp);
+                       splx(s);
+                       return (0);
+#endif /* INET6 */
+               default:
+                       return (EAFNOSUPPORT);
+               }
        }
 
        ifp = ifunit(ifr->ifr_name);
@@ -1286,17 +1304,8 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
                        return (error);
 
 #ifdef INET6
-               if (ifr->ifr_flags & IFXF_NOINET6 &&
-                   !(ifp->if_xflags & IFXF_NOINET6)) {
-                       s = splnet();
-                       in6_ifdetach(ifp);
-                       splx(s);
-               }
-               if (ifp->if_xflags & IFXF_NOINET6 &&
-                   !(ifr->ifr_flags & IFXF_NOINET6)) {
-                       ifp->if_xflags &= ~IFXF_NOINET6;
-                       if (ifp->if_flags & IFF_UP) {
-                               /* configure link-local address */
+               if (ISSET(ifr->ifr_flags, IFXF_AUTOCONF6)) {
+                       if (in6ifa_ifpforlinklocal(ifp, 0) == NULL) {
                                s = splnet();
                                in6_if_up(ifp);
                                splx(s);
@@ -1314,6 +1323,7 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
                        if (!timeout_pending(&nd6_rs_output_timer))
                                nd6_rs_output_set_timo(nd6_rs_output_timeout);
                }
+
                if ((ifp->if_xflags & IFXF_AUTOCONF6) &&
                    !(ifr->ifr_flags & IFXF_AUTOCONF6)) {
                        hook_disestablish(ifp->if_linkstatehooks,
@@ -1322,7 +1332,7 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
                        if (nd6_rs_timeout_count == 0)
                                timeout_del(&nd6_rs_output_timer);
                }
-#endif
+#endif /* INET6 */
 
 #ifdef MPLS
                if (ISSET(ifr->ifr_flags, IFXF_MPLS) &&
@@ -1341,7 +1351,7 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
                        ifp->if_ll_output = NULL;
                        splx(s);
                }
-#endif
+#endif /* MPLS */
 
 #ifndef SMALL_KERNEL
                if (ifp->if_capabilities & IFCAP_WOL) {
@@ -1650,17 +1660,9 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
                break;
        }
 
-       if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
+       if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0)
                microtime(&ifp->if_lastchange);
-#ifdef INET6
-               if (!(ifp->if_xflags & IFXF_NOINET6) &&
-                   (ifp->if_flags & IFF_UP) != 0) {
-                       s = splnet();
-                       in6_if_up(ifp);
-                       splx(s);
-               }
-#endif
-       }
+
        /* If we took down the IF, bring it back */
        if (up) {
                s = splnet();
@@ -2250,7 +2252,7 @@ ifnewlladdr(struct ifnet *ifp)
 #ifdef INET6
        /* Update the link-local address. Don't do it if we're
         * a router to avoid confusing hosts on the network. */
-       if (!(ifp->if_xflags & IFXF_NOINET6) && !ip6_forwarding) {
+       if (!ip6_forwarding) {
                ifa = &in6ifa_ifpforlinklocal(ifp, 0)->ia_ifa;
                if (ifa) {
                        in6_purgeaddr(ifa);
index c4a5cd3..4bf6a68 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if.h,v 1.158 2014/12/05 15:50:04 mpi Exp $    */
+/*     $OpenBSD: if.h,v 1.159 2015/01/06 21:26:46 stsp Exp $   */
 /*     $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $  */
 
 /*
@@ -206,7 +206,6 @@ struct if_status_description {
            IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI)
 
 #define IFXF_TXREADY           0x1             /* interface is ready to tx */
-#define        IFXF_NOINET6            0x2             /* don't do inet6 */
 #define        IFXF_INET6_NOPRIVACY    0x4             /* don't autoconf privacy */
 #define        IFXF_MPLS               0x8             /* supports MPLS */
 #define        IFXF_WOL                0x10            /* wake on lan enabled */
@@ -429,6 +428,12 @@ struct if_laddrreq {
        struct sockaddr_storage dstaddr; /* out */
 };
 
+/* SIOCIFAFDETACH */
+struct if_afreq {
+       char            ifar_name[IFNAMSIZ];
+       sa_family_t     ifar_af;
+};
+
 #include <net/if_arp.h>
 
 #ifdef _KERNEL
index 4da4f77..75dcb41 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in6.c,v 1.147 2014/12/08 10:38:48 mpi Exp $   */
+/*     $OpenBSD: in6.c,v 1.148 2015/01/06 21:26:46 stsp Exp $  */
 /*     $KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun Exp $   */
 
 /*
@@ -473,9 +473,12 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp)
                }
                /*
                 * first, make or update the interface address structure,
-                * and link it to the list.
+                * and link it to the list. try to enable inet6 if there
+                * is no link-local yet.
                 */
                s = splsoftnet();
+               if (in6ifa_ifpforlinklocal(ifp, 0) == NULL)
+                       in6_if_up(ifp);
                error = in6_update_ifa(ifp, ifra, ia6);
                splx(s);
                if (error != 0)
@@ -606,10 +609,6 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
            ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
                return (EAFNOSUPPORT);
 
-       /* must have link-local */
-       if (ifp->if_xflags & IFXF_NOINET6)
-               return (EAFNOSUPPORT);
-
        /*
         * validate ifra_prefixmask.  don't check sin6_family, netmask
         * does not carry fields other than sin6_len.
index 6f36b1e..2150619 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in6_ifattach.c,v 1.78 2014/12/04 00:02:15 tedu Exp $  */
+/*     $OpenBSD: in6_ifattach.c,v 1.79 2015/01/06 21:26:46 stsp Exp $  */
 /*     $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $  */
 
 /*
@@ -617,6 +617,8 @@ in6_ifdetach(struct ifnet *ifp)
        struct rtentry *rt;
        struct sockaddr_in6 sin6;
 
+       ifp->if_xflags &= ~IFXF_AUTOCONF6;
+
 #ifdef MROUTING
        /* remove ip6_mrouter stuff */
        ip6_mrouter_detach(ifp);
index 625ee67..20ef021 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sockio.h,v 1.55 2014/07/13 13:41:46 henning Exp $     */
+/*     $OpenBSD: sockio.h,v 1.56 2015/01/06 21:26:46 stsp Exp $        */
 /*     $NetBSD: sockio.h,v 1.5 1995/08/23 00:40:47 thorpej Exp $       */
 
 /*-
 #define        SIOCGETPFLOW    _IOWR('i', 254, struct ifreq)
 
 #define        SIOCGIFRXR      _IOW('i', 170, struct ifreq)
+#define        SIOCIFAFATTACH  _IOW('i', 171, struct if_afreq) /* attach given af */
+#define        SIOCIFAFDETACH  _IOW('i', 172, struct if_afreq) /* detach given af */
 
 #endif /* !_SYS_SOCKIO_H_ */