looks reasonable to me. OK On Tue, May 01, 2018 at 07:08:59PM +0200, Theo Buehler wrote: > On Mon, Apr 30, 2018 at 02:55:21PM +0200, Martin Pieuchot wrote: > > On 30/04/18(Mon) 12:00, Theo Buehler wrote: > > > With mpi's encouragement and guidance, here's a diff that reduces the > > > scope of the NET_LOCK() a bit. > > > > > > in_control() is the only caller of mrt_ioctl() and the latter is a > > > simple function only requiring a read lock. > > > > > > There are only a handful callers of in_ioctl(). The two switches create > > > relatively tangled codepaths, so this will need some refactoring before > > > we can push the lock further down and split the read and write cases. > > > For now, establish a single exit point, grab the netlock at the > > > beginning and release it at the end. > > > > That makes sense, the same could be done for in6_ioctl(). > > Here's the corresponding diff for in6_control(). > > Push the diff down into mrt6_ioctl() and in6_ioctl(). Much like the IPv4 > version, mrt6_ioctl() only needs a read lock. > > in6_ioctl() is a bit messier. It starts off with a call to nd6_ioctl(), > which only needs a read lock. In the diff, I pushed the NET_RLOCK() down > into nd6_ioctl(), but perhaps it would be better to keep the locking > inside in6_ioctl(), like this: > > switch (cmd) { > case SIOCGIFINFO_IN6: > case SIOCGNBRINFO_IN6: > NET_RLOCK(); > error = nd6_ioctl(cmd, data, ifp); > NET_RUNLOCK(); > return error; > } > > I tested this as well as I could, but I don't usually use IPv6, so I > dabbled a bit with it on my home network and I tried to use the netinet6 > regress tests, only with moderate success. > > A test from people who actually use IPv6 would be welcome. > > Index: sys/netinet6/in6.c > =================================================================== > RCS file: /var/cvs/src/sys/netinet6/in6.c,v > retrieving revision 1.222 > diff -u -p -r1.222 in6.c > --- sys/netinet6/in6.c 24 Apr 2018 19:53:38 -0000 1.222 > +++ sys/netinet6/in6.c 1 May 2018 09:14:07 -0000 > @@ -183,7 +183,6 @@ in6_control(struct socket *so, u_long cm > int privileged; > int error; > > - NET_LOCK(); > privileged = 0; > if ((so->so_state & SS_PRIV) != 0) > privileged++; > @@ -200,7 +199,6 @@ in6_control(struct socket *so, u_long cm > break; > } > > - NET_UNLOCK(); > return error; > } > > @@ -211,12 +209,11 @@ in6_ioctl(u_long cmd, caddr_t data, stru > struct in6_ifaddr *ia6 = NULL; > struct in6_aliasreq *ifra = (struct in6_aliasreq *)data; > struct sockaddr_in6 *sa6; > + int error = 0; > > if (ifp == NULL) > return (ENXIO); > > - NET_ASSERT_LOCKED(); > - > switch (cmd) { > case SIOCGIFINFO_IN6: > case SIOCGNBRINFO_IN6: > @@ -252,13 +249,16 @@ in6_ioctl(u_long cmd, caddr_t data, stru > case SIOCSIFNETMASK: > /* > * Do not pass those ioctl to driver handler since they are not > - * properly setup. Instead just error out. > + * properly set up. Instead just error out. > */ > return (EINVAL); > default: > sa6 = NULL; > break; > } > + > + NET_LOCK(); > + > if (sa6 && sa6->sin6_family == AF_INET6) { > if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) { > if (sa6->sin6_addr.s6_addr16[1] == 0) { > @@ -267,12 +267,15 @@ in6_ioctl(u_long cmd, caddr_t data, stru > htons(ifp->if_index); > } else if (sa6->sin6_addr.s6_addr16[1] != > htons(ifp->if_index)) { > - return (EINVAL); /* link ID contradicts > */ > + error = EINVAL; /* link ID contradicts */ > + goto err; > } > if (sa6->sin6_scope_id) { > if (sa6->sin6_scope_id != > - (u_int32_t)ifp->if_index) > - return (EINVAL); > + (u_int32_t)ifp->if_index) { > + error = EINVAL; > + goto err; > + } > sa6->sin6_scope_id = 0; /* XXX: good way? */ > } > } > @@ -289,8 +292,10 @@ in6_ioctl(u_long cmd, caddr_t data, stru > * interface address from the day one, we consider "remove the > * first one" semantics to be not preferable. > */ > - if (ia6 == NULL) > - return (EADDRNOTAVAIL); > + if (ia6 == NULL) { > + error = EADDRNOTAVAIL; > + goto err; > + } > /* FALLTHROUGH */ > case SIOCAIFADDR_IN6: > /* > @@ -298,11 +303,14 @@ in6_ioctl(u_long cmd, caddr_t data, stru > * the corresponding operation. > */ > if (ifra->ifra_addr.sin6_family != AF_INET6 || > - ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6)) > - return (EAFNOSUPPORT); > - if (!privileged) > - return (EPERM); > - > + ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6)) { > + error = EAFNOSUPPORT; > + goto err; > + } > + if (!privileged) { > + error = EPERM; > + goto err; > + } > break; > > case SIOCGIFAFLAG_IN6: > @@ -310,15 +318,19 @@ in6_ioctl(u_long cmd, caddr_t data, stru > case SIOCGIFDSTADDR_IN6: > case SIOCGIFALIFETIME_IN6: > /* must think again about its semantics */ > - if (ia6 == NULL) > - return (EADDRNOTAVAIL); > + if (ia6 == NULL) { > + error = EADDRNOTAVAIL; > + goto err; > + } > break; > } > > switch (cmd) { > case SIOCGIFDSTADDR_IN6: > - if ((ifp->if_flags & IFF_POINTOPOINT) == 0) > - return (EINVAL); > + if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { > + error = EINVAL; > + break; > + } > /* > * XXX: should we check if ifa_dstaddr is NULL and return > * an error? > @@ -392,7 +404,8 @@ in6_ioctl(u_long cmd, caddr_t data, stru > if ((ifra->ifra_flags & IN6_IFF_DUPLICATED) != 0 || > (ifra->ifra_flags & IN6_IFF_DETACHED) != 0 || > (ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) { > - return (EINVAL); > + error = EINVAL; > + break; > } > > if (ia6 == NULL) > @@ -413,10 +426,10 @@ in6_ioctl(u_long cmd, caddr_t data, stru > */ > error = in6_ifattach(ifp); > if (error != 0) > - return (error); > + break; > error = in6_update_ifa(ifp, ifra, ia6); > if (error != 0) > - return (error); > + break; > > ia6 = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr); > if (ia6 == NULL) { > @@ -446,7 +459,7 @@ in6_ioctl(u_long cmd, caddr_t data, stru > ia6->ia_ifa.ifa_addr); > if (error) { > in6_purgeaddr(&ia6->ia_ifa); > - return (error); > + break; > } > dohooks(ifp->if_addrhooks, 0); > break; > @@ -458,10 +471,13 @@ in6_ioctl(u_long cmd, caddr_t data, stru > break; > > default: > - return (EOPNOTSUPP); > + error = EOPNOTSUPP; > + break; > } > > - return (0); > +err: > + NET_UNLOCK(); > + return (error); > } > > /* > Index: sys/netinet6/ip6_mroute.c > =================================================================== > RCS file: /var/cvs/src/sys/netinet6/ip6_mroute.c,v > retrieving revision 1.114 > diff -u -p -r1.114 ip6_mroute.c > --- sys/netinet6/ip6_mroute.c 26 Jun 2017 09:32:32 -0000 1.114 > +++ sys/netinet6/ip6_mroute.c 1 May 2018 08:42:18 -0000 > @@ -242,17 +242,26 @@ int > mrt6_ioctl(struct socket *so, u_long cmd, caddr_t data) > { > struct inpcb *inp = sotoinpcb(so); > + int error; > > switch (cmd) { > case SIOCGETSGCNT_IN6: > - return (get_sg6_cnt((struct sioc_sg_req6 *)data, > - inp->inp_rtableid)); > + NET_RLOCK(); > + error = get_sg6_cnt((struct sioc_sg_req6 *)data, > + inp->inp_rtableid); > + NET_RUNLOCK(); > + break; > case SIOCGETMIFCNT_IN6: > - return (get_mif6_cnt((struct sioc_mif_req6 *)data, > - inp->inp_rtableid)); > + NET_RLOCK(); > + error = get_mif6_cnt((struct sioc_mif_req6 *)data, > + inp->inp_rtableid); > + NET_RUNLOCK(); > + break; > default: > - return (ENOTTY); > + error = ENOTTY; > + break; > } > + return error; > } > > /* > Index: sys/netinet6/nd6.c > =================================================================== > RCS file: /var/cvs/src/sys/netinet6/nd6.c,v > retrieving revision 1.223 > diff -u -p -r1.223 nd6.c > --- sys/netinet6/nd6.c 15 Jan 2018 13:48:31 -0000 1.223 > +++ sys/netinet6/nd6.c 30 Apr 2018 22:42:59 -0000 > @@ -1014,20 +1014,20 @@ nd6_ioctl(u_long cmd, caddr_t data, stru > struct in6_ndireq *ndi = (struct in6_ndireq *)data; > struct in6_nbrinfo *nbi = (struct in6_nbrinfo *)data; > struct rtentry *rt; > - int error = 0; > - > - NET_ASSERT_LOCKED(); > > switch (cmd) { > case SIOCGIFINFO_IN6: > + NET_RLOCK(); > ndi->ndi = *ND_IFINFO(ifp); > - break; > + NET_RUNLOCK(); > + return (0); > case SIOCGNBRINFO_IN6: > { > struct llinfo_nd6 *ln; > struct in6_addr nb_addr = nbi->addr; /* make local for safety */ > time_t expire; > > + NET_RLOCK(); > /* > * XXX: KAME specific hack for scoped addresses > * XXXX: for other scopes than link-local? > @@ -1043,9 +1043,9 @@ nd6_ioctl(u_long cmd, caddr_t data, stru > rt = nd6_lookup(&nb_addr, 0, ifp, ifp->if_rdomain); > if (rt == NULL || > (ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) { > - error = EINVAL; > rtfree(rt); > - break; > + NET_RUNLOCK(); > + return (EINVAL); > } > expire = ln->ln_rt->rt_expire; > if (expire != 0) { > @@ -1057,12 +1057,13 @@ nd6_ioctl(u_long cmd, caddr_t data, stru > nbi->asked = ln->ln_asked; > nbi->isrouter = ln->ln_router; > nbi->expire = expire; > - rtfree(rt); > > - break; > + rtfree(rt); > + NET_RUNLOCK(); > + return (0); > } > } > - return (error); > + return (0); > } > > /* >
-- I'm not entirely sure you are real.