From 3298ff1c5ccb69b6f8f9a0427eccad17ada0287e Mon Sep 17 00:00:00 2001 From: stsp Date: Tue, 6 Jan 2015 21:26:46 +0000 Subject: [PATCH] Remove the NOINET6 interface flag, a left-over from the times when IPv6 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 | 36 +++++++++++++-------- sys/net/if.c | 64 +++++++++++++++++++------------------ sys/net/if.h | 9 ++++-- sys/netinet6/in6.c | 11 +++---- sys/netinet6/in6_ifattach.c | 4 ++- sys/sys/sockio.h | 4 ++- 6 files changed, 74 insertions(+), 54 deletions(-) diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index 95819b4b293..cc361b96056 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -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"); diff --git a/sys/net/if.c b/sys/net/if.c index 55161b8cd02..9b2f03588b7 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -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); diff --git a/sys/net/if.h b/sys/net/if.h index c4a5cd30f6a..4bf6a686d3d 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -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 #ifdef _KERNEL diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 4da4f7795c0..75dcb416765 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -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. diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index 6f36b1e3418..21506198a0d 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -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); diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h index 625ee6755e0..20ef02154a2 100644 --- a/sys/sys/sockio.h +++ b/sys/sys/sockio.h @@ -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 $ */ /*- @@ -200,5 +200,7 @@ #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_ */ -- 2.20.1