Diff below reduces the scope of the NET_LOCK(), this time in sysctl
path.  It is interesting for multiple reasons:

- It reduces the contention on the NET_LOCK(), which should improve
  the overall latency on the system when counters are frequently
  queried.  Accesses to read-only operations and per-CPU counters
  are no longer protected by the NET_LOCK().

- It allows per-CPU counters to be accessed in parallel.  counters_read(9)
  is now executed without holding the NET_LOCK().

- sysctl_mq() is now MP-safe, by serializing access using the mq's
  mutex.  However a dance is required to not hold a mutex around
  copyin(9)/copyout(9).

- The NET_LOCK() is now taken around all sysctl_int(), sysctl_struct()
  and sysctl_int_arr().  This is not nice but it will allow people to
  fix parts of the sysctl path independently.

Note that all data structure currently protected in these sysctl paths
do not necessarily need the NET_LOCK().  Take CARP's carp_opts[] for
example.  Does it need the NET_LOCK()?  Is it at all the right primitive?
Well interested readers can answer with diffs and explanations to these
questions :)

Comments, oks?

Index: kern/uipc_domain.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_domain.c,v
retrieving revision 1.52
diff -u -p -r1.52 uipc_domain.c
--- kern/uipc_domain.c  11 Aug 2017 21:24:19 -0000      1.52
+++ kern/uipc_domain.c  12 Sep 2017 13:20:42 -0000
@@ -207,10 +207,8 @@ net_sysctl(int *name, u_int namelen, voi
        protocol = name[1];
        for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
                if (pr->pr_protocol == protocol && pr->pr_sysctl) {
-                       NET_LOCK();
                        error = (*pr->pr_sysctl)(name + 2, namelen - 2,
                            oldp, oldlenp, newp, newlen);
-                       NET_UNLOCK();
                        return (error);
                }
        return (ENOPROTOOPT);
Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.512
diff -u -p -r1.512 if.c
--- net/if.c    22 Aug 2017 15:02:34 -0000      1.512
+++ net/if.c    12 Sep 2017 13:44:41 -0000
@@ -2666,10 +2666,14 @@ ifpromisc(struct ifnet *ifp, int pswitch
        return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
 }
 
+/* XXX move to kern/uipc_mbuf.c */
 int
 sysctl_mq(int *name, u_int namelen, void *oldp, size_t *oldlenp,
     void *newp, size_t newlen, struct mbuf_queue *mq)
 {
+       unsigned int maxlen;
+       int error;
+
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
@@ -2678,8 +2682,14 @@ sysctl_mq(int *name, u_int namelen, void
        case IFQCTL_LEN:
                return (sysctl_rdint(oldp, oldlenp, newp, mq_len(mq)));
        case IFQCTL_MAXLEN:
-               return (sysctl_int(oldp, oldlenp, newp, newlen,
-                   &mq->mq_maxlen)); /* XXX directly accessing maxlen */
+               maxlen = mq->mq_maxlen;
+               error = sysctl_int(oldp, oldlenp, newp, newlen, &maxlen);
+               if (!error && maxlen != mq->mq_maxlen) {
+                       mtx_enter(&mq->mq_mtx);
+                       mq->mq_maxlen = maxlen;
+                       mtx_leave(&mq->mq_mtx);
+               }
+               return (error);
        case IFQCTL_DROPS:
                return (sysctl_rdint(oldp, oldlenp, newp, mq_drops(mq)));
        default:
Index: net/if_etherip.c
===================================================================
RCS file: /cvs/src/sys/net/if_etherip.c,v
retrieving revision 1.19
diff -u -p -r1.19 if_etherip.c
--- net/if_etherip.c    6 Jun 2017 11:51:13 -0000       1.19
+++ net/if_etherip.c    12 Sep 2017 12:38:46 -0000
@@ -662,18 +662,26 @@ int
 ip_etherip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
     void *newp, size_t newlen)
 {
+       int error;
+
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return ENOTDIR;
 
        switch (name[0]) {
        case ETHERIPCTL_ALLOW:
-               return sysctl_int(oldp, oldlenp, newp, newlen, &etherip_allow);
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen, &etherip_allow);
+               NET_UNLOCK();
+               return (error);
        case ETHERIPCTL_STATS:
                if (newp != NULL)
                        return EPERM;
-               return sysctl_struct(oldp, oldlenp, newp, newlen,
+               NET_LOCK();
+               error = sysctl_struct(oldp, oldlenp, newp, newlen,
                    &etheripstat, sizeof(etheripstat));
+               NET_UNLOCK();
+               return (error);
        default:
                break;
        }
Index: net/pfkeyv2.c
===================================================================
RCS file: /cvs/src/sys/net/pfkeyv2.c,v
retrieving revision 1.166
diff -u -p -r1.166 pfkeyv2.c
--- net/pfkeyv2.c       8 Sep 2017 05:36:53 -0000       1.166
+++ net/pfkeyv2.c       12 Sep 2017 12:43:06 -0000
@@ -2386,8 +2386,6 @@ pfkeyv2_sysctl(int *name, u_int namelen,
        int error = EINVAL;
        u_int rdomain;
 
-       NET_ASSERT_LOCKED();
-
        if (new)
                return (EPERM);
        if (namelen < 1)
@@ -2403,7 +2401,9 @@ pfkeyv2_sysctl(int *name, u_int namelen,
        case NET_KEY_SADB_DUMP:
                if ((error = suser(curproc, 0)) != 0)
                        return (error);
+               NET_LOCK();
                error = tdb_walk(rdomain, pfkeyv2_sysctl_walker, &w);
+               NET_UNLOCK();
                if (oldp)
                        *oldlenp = w.w_where - oldp;
                else
@@ -2411,8 +2411,10 @@ pfkeyv2_sysctl(int *name, u_int namelen,
                break;
 
        case NET_KEY_SPD_DUMP:
+               NET_LOCK();
                error = pfkeyv2_ipo_walk(rdomain,
                    pfkeyv2_sysctl_policydumper, &w);
+               NET_UNLOCK();
                if (oldp)
                        *oldlenp = w.w_where - oldp;
                else
Index: net/rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.250
diff -u -p -r1.250 rtsock.c
--- net/rtsock.c        5 Sep 2017 07:59:11 -0000       1.250
+++ net/rtsock.c        12 Sep 2017 13:15:47 -0000
@@ -1733,8 +1733,6 @@ sysctl_rtable(int *name, u_int namelen, 
        struct rt_tableinfo      tableinfo;
        u_int                    tableid = 0;
 
-       NET_ASSERT_LOCKED();
-
        if (new)
                return (EPERM);
        if (namelen < 3 || namelen > 4)
@@ -1757,6 +1755,7 @@ sysctl_rtable(int *name, u_int namelen, 
        switch (w.w_op) {
        case NET_RT_DUMP:
        case NET_RT_FLAGS:
+               NET_LOCK();
                for (i = 1; i <= AF_MAX; i++) {
                        if (af != 0 && af != i)
                                continue;
@@ -1767,10 +1766,13 @@ sysctl_rtable(int *name, u_int namelen, 
                        if (error)
                                break;
                }
+               NET_UNLOCK();
                break;
 
        case NET_RT_IFLIST:
+               NET_LOCK();
                error = sysctl_iflist(af, &w);
+               NET_UNLOCK();
                break;
 
        case NET_RT_STATS:
@@ -1786,7 +1788,9 @@ sysctl_rtable(int *name, u_int namelen, 
                    &tableinfo, sizeof(tableinfo));
                return (error);
        case NET_RT_IFNAMES:
+               NET_LOCK();
                error = sysctl_ifnames(&w);
+               NET_UNLOCK();
                break;
        }
        free(w.w_tmem, M_RTABLE, 0);
Index: netinet/igmp.c
===================================================================
RCS file: /cvs/src/sys/netinet/igmp.c,v
retrieving revision 1.69
diff -u -p -r1.69 igmp.c
--- netinet/igmp.c      19 Jun 2017 17:58:49 -0000      1.69
+++ netinet/igmp.c      12 Sep 2017 12:50:23 -0000
@@ -680,6 +680,8 @@ int
 igmp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
     void *newp, size_t newlen)
 {
+       int error;
+
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
@@ -690,9 +692,13 @@ igmp_sysctl(int *name, u_int namelen, vo
                        return (EPERM);
                return (igmp_sysctl_igmpstat(oldp, oldlenp, newp));
        default:
-               if (name[0] < IGMPCTL_MAXID)
-                       return (sysctl_int_arr(igmpctl_vars, name, namelen,
-                           oldp, oldlenp, newp, newlen));
+               if (name[0] < IGMPCTL_MAXID) {
+                       NET_LOCK();
+                       error = sysctl_int_arr(igmpctl_vars, name, namelen,
+                           oldp, oldlenp, newp, newlen);
+                       NET_UNLOCK();
+                       return (error);
+               }
                return (ENOPROTOOPT);
        }
        /* NOTREACHED */
Index: netinet/ip_carp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.315
diff -u -p -r1.315 ip_carp.c
--- netinet/ip_carp.c   11 Aug 2017 21:24:19 -0000      1.315
+++ netinet/ip_carp.c   12 Sep 2017 12:30:54 -0000
@@ -739,6 +739,8 @@ int
 carp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
     size_t newlen)
 {
+       int error;
+
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
@@ -749,8 +751,11 @@ carp_sysctl(int *name, u_int namelen, vo
        default:
                if (name[0] <= 0 || name[0] >= CARPCTL_MAXID)
                        return (ENOPROTOOPT);
-               return sysctl_int(oldp, oldlenp, newp, newlen,
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen,
                    &carp_opts[name[0]]);
+               NET_UNLOCK();
+               return (error);
        }
 }
 
Index: netinet/ip_divert.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_divert.c,v
retrieving revision 1.52
diff -u -p -r1.52 ip_divert.c
--- netinet/ip_divert.c 6 Sep 2017 11:43:04 -0000       1.52
+++ netinet/ip_divert.c 12 Sep 2017 12:34:40 -0000
@@ -367,23 +367,35 @@ int
 divert_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void 
*newp,
     size_t newlen)
 {
+       int error;
+
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
 
        switch (name[0]) {
        case DIVERTCTL_SENDSPACE:
-               return (sysctl_int(oldp, oldlenp, newp, newlen,
-                   &divert_sendspace));
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen,
+                   &divert_sendspace);
+               NET_UNLOCK();
+               return (error);
        case DIVERTCTL_RECVSPACE:
-               return (sysctl_int(oldp, oldlenp, newp, newlen,
-                   &divert_recvspace));
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen,
+                   &divert_recvspace);
+               NET_UNLOCK();
+               return (error);
        case DIVERTCTL_STATS:
                return (divert_sysctl_divstat(oldp, oldlenp, newp));
        default:
-               if (name[0] < DIVERTCTL_MAXID)
-                       return sysctl_int_arr(divertctl_vars, name, namelen,
+               if (name[0] < DIVERTCTL_MAXID) {
+                       NET_LOCK();
+                       error = sysctl_int_arr(divertctl_vars, name, namelen,
                            oldp, oldlenp, newp, newlen);
+                       NET_UNLOCK();
+                       return (error);
+               }
 
                return (ENOPROTOOPT);
        }
Index: netinet/ip_gre.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_gre.c,v
retrieving revision 1.66
diff -u -p -r1.66 ip_gre.c
--- netinet/ip_gre.c    15 Aug 2017 17:47:15 -0000      1.66
+++ netinet/ip_gre.c    12 Sep 2017 13:19:01 -0000
@@ -373,15 +373,23 @@ int
 gre_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
     size_t newlen)
 {
+       int error;
+
         /* All sysctl names at this level are terminal. */
         if (namelen != 1)
                 return (ENOTDIR);
 
         switch (name[0]) {
         case GRECTL_ALLOW:
-                return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_allow));
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen, &gre_allow);
+               NET_UNLOCK();
+               return (error);
         case GRECTL_WCCP:
-                return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_wccp));
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen, &gre_wccp);
+               NET_UNLOCK();
+               return (error);
         default:
                 return (ENOPROTOOPT);
         }
@@ -392,14 +400,19 @@ int
 ipmobile_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
     void *newp, size_t newlen)
 {
+       int error;
+
         /* All sysctl names at this level are terminal. */
         if (namelen != 1)
                 return (ENOTDIR);
 
         switch (name[0]) {
         case MOBILEIPCTL_ALLOW:
-                return (sysctl_int(oldp, oldlenp, newp, newlen,
-                                  &ip_mobile_allow));
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen,
+                   &ip_mobile_allow);
+               NET_UNLOCK();
+               return (error);
         default:
                 return (ENOPROTOOPT);
         }
Index: netinet/ip_icmp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.171
diff -u -p -r1.171 ip_icmp.c
--- netinet/ip_icmp.c   10 Aug 2017 02:26:26 -0000      1.171
+++ netinet/ip_icmp.c   12 Sep 2017 12:51:36 -0000
@@ -881,8 +881,6 @@ icmp_sysctl(int *name, u_int namelen, vo
 {
        int error;
 
-       NET_ASSERT_LOCKED();
-
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
@@ -890,6 +888,7 @@ icmp_sysctl(int *name, u_int namelen, vo
        switch (name[0]) {
        case ICMPCTL_REDIRTIMEOUT:
 
+               NET_LOCK();
                error = sysctl_int(oldp, oldlenp, newp, newlen,
                    &icmp_redirtimeout);
                if (icmp_redirect_timeout_q != NULL) {
@@ -903,6 +902,7 @@ icmp_sysctl(int *name, u_int namelen, vo
                        icmp_redirect_timeout_q =
                            rt_timer_queue_create(icmp_redirtimeout);
                }
+               NET_UNLOCK();
                break;
 
        case ICMPCTL_STATS:
@@ -911,8 +911,10 @@ icmp_sysctl(int *name, u_int namelen, vo
 
        default:
                if (name[0] < ICMPCTL_MAXID) {
+                       NET_LOCK();
                        error = sysctl_int_arr(icmpctl_vars, name, namelen,
                            oldp, oldlenp, newp, newlen);
+                       NET_UNLOCK();
                        break;
                }
                error = ENOPROTOOPT;
Index: netinet/ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.322
diff -u -p -r1.322 ip_input.c
--- netinet/ip_input.c  7 Sep 2017 10:54:49 -0000       1.322
+++ netinet/ip_input.c  12 Sep 2017 13:11:51 -0000
@@ -1617,26 +1617,24 @@ ip_sysctl(int *name, u_int namelen, void
        extern struct mrtstat mrtstat;
 #endif
 
-       NET_ASSERT_LOCKED();
-
        /* Almost all sysctl names at this level are terminal. */
        if (namelen != 1 && name[0] != IPCTL_IFQUEUE)
                return (ENOTDIR);
 
        switch (name[0]) {
-#ifdef notyet
-       case IPCTL_DEFMTU:
-               return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));
-#endif
        case IPCTL_SOURCEROUTE:
                /*
                 * Don't allow this to change in a secure environment.
                 */
                if (newp && securelevel > 0)
                        return (EPERM);
-               return (sysctl_int(oldp, oldlenp, newp, newlen,
-                   &ip_dosourceroute));
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen,
+                   &ip_dosourceroute);
+               NET_UNLOCK();
+               return (error);
        case IPCTL_MTUDISC:
+               NET_LOCK();
                error = sysctl_int(oldp, oldlenp, newp, newlen,
                    &ip_mtudisc);
                if (ip_mtudisc != 0 && ip_mtudisc_timeout_q == NULL) {
@@ -1646,25 +1644,37 @@ ip_sysctl(int *name, u_int namelen, void
                        rt_timer_queue_destroy(ip_mtudisc_timeout_q);
                        ip_mtudisc_timeout_q = NULL;
                }
+               NET_UNLOCK();
                return error;
        case IPCTL_MTUDISCTIMEOUT:
+               NET_LOCK();
                error = sysctl_int(oldp, oldlenp, newp, newlen,
                   &ip_mtudisc_timeout);
                if (ip_mtudisc_timeout_q != NULL)
                        rt_timer_queue_change(ip_mtudisc_timeout_q,
                                              ip_mtudisc_timeout);
+               NET_UNLOCK();
                return (error);
        case IPCTL_IPSEC_ENC_ALGORITHM:
-               return (sysctl_tstring(oldp, oldlenp, newp, newlen,
-                                      ipsec_def_enc, sizeof(ipsec_def_enc)));
+               NET_LOCK();
+               error = sysctl_tstring(oldp, oldlenp, newp, newlen,
+                                      ipsec_def_enc, sizeof(ipsec_def_enc));
+               NET_UNLOCK();
+               return (error);
        case IPCTL_IPSEC_AUTH_ALGORITHM:
-               return (sysctl_tstring(oldp, oldlenp, newp, newlen,
+               NET_LOCK();
+               error = sysctl_tstring(oldp, oldlenp, newp, newlen,
                                       ipsec_def_auth,
-                                      sizeof(ipsec_def_auth)));
+                                      sizeof(ipsec_def_auth));
+               NET_UNLOCK();
+               return (error);
        case IPCTL_IPSEC_IPCOMP_ALGORITHM:
-               return (sysctl_tstring(oldp, oldlenp, newp, newlen,
+               NET_LOCK();
+               error = sysctl_tstring(oldp, oldlenp, newp, newlen,
                                       ipsec_def_comp,
-                                      sizeof(ipsec_def_comp)));
+                                      sizeof(ipsec_def_comp));
+               NET_UNLOCK();
+               return (error);
        case IPCTL_IFQUEUE:
                return (sysctl_niq(name + 1, namelen - 1,
                    oldp, oldlenp, newp, newlen, &ipintrq));
@@ -1679,11 +1689,17 @@ ip_sysctl(int *name, u_int namelen, void
        case IPCTL_MRTMFC:
                if (newp)
                        return (EPERM);
-               return mrt_sysctl_mfc(oldp, oldlenp);
+               NET_LOCK();
+               error = mrt_sysctl_mfc(oldp, oldlenp);
+               NET_UNLOCK();
+               return (error);
        case IPCTL_MRTVIF:
                if (newp)
                        return (EPERM);
-               return mrt_sysctl_vif(oldp, oldlenp);
+               NET_LOCK();
+               error = mrt_sysctl_vif(oldp, oldlenp);
+               NET_UNLOCK();
+               return (error);
 #else
        case IPCTL_MRTPROTO:
        case IPCTL_MRTSTATS:
@@ -1692,9 +1708,13 @@ ip_sysctl(int *name, u_int namelen, void
                return (EOPNOTSUPP);
 #endif
        default:
-               if (name[0] < IPCTL_MAXID)
-                       return (sysctl_int_arr(ipctl_vars, name, namelen,
-                           oldp, oldlenp, newp, newlen));
+               if (name[0] < IPCTL_MAXID) {
+                       NET_LOCK();
+                       error = sysctl_int_arr(ipctl_vars, name, namelen,
+                           oldp, oldlenp, newp, newlen);
+                       NET_UNLOCK();
+                       return (error);
+               }
                return (EOPNOTSUPP);
        }
        /* NOTREACHED */
Index: netinet/ip_ipip.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ipip.c,v
retrieving revision 1.86
diff -u -p -r1.86 ip_ipip.c
--- netinet/ip_ipip.c   5 Jul 2017 11:34:10 -0000       1.86
+++ netinet/ip_ipip.c   12 Sep 2017 12:49:38 -0000
@@ -592,13 +592,18 @@ int
 ipip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
     size_t newlen)
 {
+       int error;
+
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
 
        switch (name[0]) {
        case IPIPCTL_ALLOW:
-               return (sysctl_int(oldp, oldlenp, newp, newlen, &ipip_allow));
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen, &ipip_allow);
+               NET_UNLOCK();
+               return (error);
        case IPIPCTL_STATS:
                return (ipip_sysctl_ipipstat(oldp, oldlenp, newp));
        default:
Index: netinet/ipsec_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ipsec_input.c,v
retrieving revision 1.156
diff -u -p -r1.156 ipsec_input.c
--- netinet/ipsec_input.c       5 Jul 2017 11:34:10 -0000       1.156
+++ netinet/ipsec_input.c       12 Sep 2017 12:37:20 -0000
@@ -615,6 +615,8 @@ int
 esp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
     size_t newlen)
 {
+       int error;
+
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
@@ -623,12 +625,19 @@ esp_sysctl(int *name, u_int namelen, voi
        case ESPCTL_STATS:
                if (newp != NULL)
                        return (EPERM);
-               return (sysctl_struct(oldp, oldlenp, newp, newlen,
-                   &espstat, sizeof(espstat)));
+               NET_LOCK();
+               error = sysctl_struct(oldp, oldlenp, newp, newlen,
+                   &espstat, sizeof(espstat));
+               NET_UNLOCK();
+               return (error);
        default:
-               if (name[0] < ESPCTL_MAXID)
-                       return (sysctl_int_arr(espctl_vars, name, namelen,
-                           oldp, oldlenp, newp, newlen));
+               if (name[0] < ESPCTL_MAXID) {
+                       NET_LOCK();
+                       error = sysctl_int_arr(espctl_vars, name, namelen,
+                           oldp, oldlenp, newp, newlen);
+                       NET_UNLOCK();
+                       return (error);
+               }
                return (ENOPROTOOPT);
        }
 }
@@ -637,6 +646,8 @@ int
 ah_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
     size_t newlen)
 {
+       int error;
+
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
@@ -645,12 +656,19 @@ ah_sysctl(int *name, u_int namelen, void
        case AHCTL_STATS:
                if (newp != NULL)
                        return (EPERM);
-               return (sysctl_struct(oldp, oldlenp, newp, newlen,
-                   &ahstat, sizeof(ahstat)));
+               NET_LOCK();
+               error = sysctl_struct(oldp, oldlenp, newp, newlen,
+                   &ahstat, sizeof(ahstat));
+               NET_UNLOCK();
+               return (error);
        default:
-               if (name[0] < AHCTL_MAXID)
-                       return (sysctl_int_arr(ahctl_vars, name, namelen,
-                           oldp, oldlenp, newp, newlen));
+               if (name[0] < AHCTL_MAXID) {
+                       NET_LOCK();
+                       error = sysctl_int_arr(ahctl_vars, name, namelen,
+                           oldp, oldlenp, newp, newlen);
+                       NET_UNLOCK();
+                       return (error);
+               }
                return (ENOPROTOOPT);
        }
 }
@@ -659,6 +677,8 @@ int
 ipcomp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void 
*newp,
     size_t newlen)
 {
+       int error;
+
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
@@ -667,12 +687,19 @@ ipcomp_sysctl(int *name, u_int namelen, 
        case IPCOMPCTL_STATS:
                if (newp != NULL)
                        return (EPERM);
-               return (sysctl_struct(oldp, oldlenp, newp, newlen,
-                   &ipcompstat, sizeof(ipcompstat)));
+               NET_LOCK();
+               error = sysctl_struct(oldp, oldlenp, newp, newlen,
+                   &ipcompstat, sizeof(ipcompstat));
+               NET_UNLOCK();
+               return (error);
        default:
-               if (name[0] < IPCOMPCTL_MAXID)
-                       return (sysctl_int_arr(ipcompctl_vars, name, namelen,
-                           oldp, oldlenp, newp, newlen));
+               if (name[0] < IPCOMPCTL_MAXID) {
+                       NET_LOCK();
+                       error = sysctl_int_arr(ipcompctl_vars, name, namelen,
+                           oldp, oldlenp, newp, newlen);
+                       NET_UNLOCK();
+                       return (error);
+               }
                return (ENOPROTOOPT);
        }
 }
Index: netinet/tcp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.155
diff -u -p -r1.155 tcp_usrreq.c
--- netinet/tcp_usrreq.c        5 Sep 2017 07:59:11 -0000       1.155
+++ netinet/tcp_usrreq.c        12 Sep 2017 13:01:27 -0000
@@ -955,8 +955,6 @@ tcp_sysctl(int *name, u_int namelen, voi
 {
        int error, nval;
 
-       NET_ASSERT_LOCKED();
-
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
@@ -964,73 +962,91 @@ tcp_sysctl(int *name, u_int namelen, voi
        switch (name[0]) {
 #ifdef TCP_SACK
        case TCPCTL_SACK:
-               return (sysctl_int(oldp, oldlenp, newp, newlen,
-                   &tcp_do_sack));
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen,
+                   &tcp_do_sack);
+               NET_UNLOCK();
+               return (error);
 #endif
        case TCPCTL_SLOWHZ:
                return (sysctl_rdint(oldp, oldlenp, newp, PR_SLOWHZ));
 
        case TCPCTL_BADDYNAMIC:
-               return (sysctl_struct(oldp, oldlenp, newp, newlen,
-                   baddynamicports.tcp, sizeof(baddynamicports.tcp)));
+               NET_LOCK();
+               error = sysctl_struct(oldp, oldlenp, newp, newlen,
+                   baddynamicports.tcp, sizeof(baddynamicports.tcp));
+               NET_UNLOCK();
+               return (error);
 
        case TCPCTL_ROOTONLY:
                if (newp && securelevel > 0)
                        return (EPERM);
-               return (sysctl_struct(oldp, oldlenp, newp, newlen,
-                   rootonlyports.tcp, sizeof(rootonlyports.tcp)));
+               NET_LOCK();
+               error = sysctl_struct(oldp, oldlenp, newp, newlen,
+                   rootonlyports.tcp, sizeof(rootonlyports.tcp));
+               NET_UNLOCK();
+               return (error);
 
        case TCPCTL_IDENT:
-               return (tcp_ident(oldp, oldlenp, newp, newlen, 0));
+               NET_LOCK();
+               error = tcp_ident(oldp, oldlenp, newp, newlen, 0);
+               NET_UNLOCK();
+               return (error);
 
        case TCPCTL_DROP:
-               return (tcp_ident(oldp, oldlenp, newp, newlen, 1));
+               NET_LOCK();
+               error = tcp_ident(oldp, oldlenp, newp, newlen, 1);
+               NET_UNLOCK();
+               return (error);
 
        case TCPCTL_ALWAYS_KEEPALIVE:
-               return (sysctl_int(oldp, oldlenp, newp, newlen,
-                   &tcp_always_keepalive));
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen,
+                   &tcp_always_keepalive);
+               NET_UNLOCK();
+               return (error);
 
 #ifdef TCP_ECN
        case TCPCTL_ECN:
-               return (sysctl_int(oldp, oldlenp, newp, newlen,
-                  &tcp_do_ecn));
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen,
+                  &tcp_do_ecn);
+               NET_UNLOCK();
+               return (error);
 #endif
        case TCPCTL_REASS_LIMIT:
+               NET_LOCK();
                nval = tcp_reass_limit;
                error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
-               if (error)
-                       return (error);
-               if (nval != tcp_reass_limit) {
+               if (!error && nval != tcp_reass_limit) {
                        error = pool_sethardlimit(&tcpqe_pool, nval, NULL, 0);
-                       if (error)
-                               return (error);
-                       tcp_reass_limit = nval;
+                       if (!error)
+                               tcp_reass_limit = nval;
                }
-               return (0);
+               NET_UNLOCK();
+               return (error);
 #ifdef TCP_SACK
        case TCPCTL_SACKHOLE_LIMIT:
+               NET_LOCK();
                nval = tcp_sackhole_limit;
                error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
-               if (error)
-                       return (error);
-               if (nval != tcp_sackhole_limit) {
+               if (!error && nval != tcp_sackhole_limit) {
                        error = pool_sethardlimit(&sackhl_pool, nval, NULL, 0);
-                       if (error)
-                               return (error);
-                       tcp_sackhole_limit = nval;
+                       if (!error)
+                               tcp_sackhole_limit = nval;
                }
-               return (0);
+               NET_UNLOCK();
+               return (error);
 #endif
 
        case TCPCTL_STATS:
                return (tcp_sysctl_tcpstat(oldp, oldlenp, newp));
 
        case TCPCTL_SYN_USE_LIMIT:
+               NET_LOCK();
                error = sysctl_int(oldp, oldlenp, newp, newlen,
                    &tcp_syn_use_limit);
-               if (error)
-                       return (error);
-               if (newp != NULL) {
+               if (!error && newp != NULL) {
                        /*
                         * Global tcp_syn_use_limit is used when reseeding a
                         * new cache.  Also update the value in active cache.
@@ -1040,33 +1056,40 @@ tcp_sysctl(int *name, u_int namelen, voi
                        if (tcp_syn_cache[1].scs_use > tcp_syn_use_limit)
                                tcp_syn_cache[1].scs_use = tcp_syn_use_limit;
                }
-               return (0);
+               NET_UNLOCK();
+               return (error);
 
        case TCPCTL_SYN_HASH_SIZE:
+               NET_LOCK();
                nval = tcp_syn_hash_size;
                error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
-               if (error)
-                       return (error);
-               if (nval != tcp_syn_hash_size) {
-                       if (nval < 1 || nval > 100000)
-                               return (EINVAL);
-                       /*
-                        * If global hash size has been changed, switch sets as
-                        * soon as possible.  Then the actual hash array will
-                        * be reallocated.
-                        */
-                       if (tcp_syn_cache[0].scs_size != nval)
-                               tcp_syn_cache[0].scs_use = 0;
-                       if (tcp_syn_cache[1].scs_size != nval)
-                               tcp_syn_cache[1].scs_use = 0;
-                       tcp_syn_hash_size = nval;
+               if (!error && nval != tcp_syn_hash_size) {
+                       if (nval < 1 || nval > 100000) {
+                               error = EINVAL;
+                       } else {
+                               /*
+                                * If global hash size has been changed,
+                                * switch sets as soon as possible.  Then
+                                * the actual hash array will be reallocated.
+                                */
+                               if (tcp_syn_cache[0].scs_size != nval)
+                                       tcp_syn_cache[0].scs_use = 0;
+                               if (tcp_syn_cache[1].scs_size != nval)
+                                       tcp_syn_cache[1].scs_use = 0;
+                               tcp_syn_hash_size = nval;
+                       }
                }
+               NET_UNLOCK();
                return (0);
 
        default:
-               if (name[0] < TCPCTL_MAXID)
-                       return (sysctl_int_arr(tcpctl_vars, name, namelen,
-                           oldp, oldlenp, newp, newlen));
+               if (name[0] < TCPCTL_MAXID) {
+                       NET_LOCK();
+                       error = sysctl_int_arr(tcpctl_vars, name, namelen,
+                           oldp, oldlenp, newp, newlen);
+                       NET_UNLOCK();
+                       return (error);
+               }
                return (ENOPROTOOPT);
        }
        /* NOTREACHED */
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.240
diff -u -p -r1.240 udp_usrreq.c
--- netinet/udp_usrreq.c        5 Sep 2017 07:59:11 -0000       1.240
+++ netinet/udp_usrreq.c        12 Sep 2017 12:53:41 -0000
@@ -1277,20 +1277,28 @@ int
 udp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
     size_t newlen)
 {
+       int error;
+
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
 
        switch (name[0]) {
        case UDPCTL_BADDYNAMIC:
-               return (sysctl_struct(oldp, oldlenp, newp, newlen,
-                   baddynamicports.udp, sizeof(baddynamicports.udp)));
+               NET_LOCK();
+               error = sysctl_struct(oldp, oldlenp, newp, newlen,
+                   baddynamicports.udp, sizeof(baddynamicports.udp));
+               NET_UNLOCK();
+               return (error);
 
        case UDPCTL_ROOTONLY:
                if (newp && securelevel > 0)
                        return (EPERM);
-               return (sysctl_struct(oldp, oldlenp, newp, newlen,
-                   rootonlyports.udp, sizeof(rootonlyports.udp)));
+               NET_LOCK();
+               error = sysctl_struct(oldp, oldlenp, newp, newlen,
+                   rootonlyports.udp, sizeof(rootonlyports.udp));
+               NET_UNLOCK();
+               return (error);
 
        case UDPCTL_STATS:
                if (newp != NULL)
@@ -1299,9 +1307,13 @@ udp_sysctl(int *name, u_int namelen, voi
                return (udp_sysctl_udpstat(oldp, oldlenp, newp));
 
        default:
-               if (name[0] < UDPCTL_MAXID)
-                       return (sysctl_int_arr(udpctl_vars, name, namelen,
-                           oldp, oldlenp, newp, newlen));
+               if (name[0] < UDPCTL_MAXID) {
+                       NET_LOCK();
+                       error = sysctl_int_arr(udpctl_vars, name, namelen,
+                           oldp, oldlenp, newp, newlen);
+                       NET_UNLOCK();
+                       return (error);
+               }
                return (ENOPROTOOPT);
        }
        /* NOTREACHED */
Index: netinet6/icmp6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/icmp6.c,v
retrieving revision 1.216
diff -u -p -r1.216 icmp6.c
--- netinet6/icmp6.c    1 Sep 2017 15:05:31 -0000       1.216
+++ netinet6/icmp6.c    12 Sep 2017 12:52:09 -0000
@@ -1887,6 +1887,8 @@ int
 icmp6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
     void *newp, size_t newlen)
 {
+       int error;
+
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return ENOTDIR;
@@ -1896,9 +1898,13 @@ icmp6_sysctl(int *name, u_int namelen, v
        case ICMPV6CTL_STATS:
                return icmp6_sysctl_icmp6stat(oldp, oldlenp, newp);
        default:
-               if (name[0] < ICMPV6CTL_MAXID)
-                       return (sysctl_int_arr(icmpv6ctl_vars, name, namelen,
-                           oldp, oldlenp, newp, newlen));
+               if (name[0] < ICMPV6CTL_MAXID) {
+                       NET_LOCK();
+                       error = sysctl_int_arr(icmpv6ctl_vars, name, namelen,
+                           oldp, oldlenp, newp, newlen);
+                       NET_UNLOCK();
+                       return (error);
+               }
                return ENOPROTOOPT;
        }
        /* NOTREACHED */
Index: netinet6/ip6_divert.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_divert.c,v
retrieving revision 1.51
diff -u -p -r1.51 ip6_divert.c
--- netinet6/ip6_divert.c       6 Sep 2017 11:43:04 -0000       1.51
+++ netinet6/ip6_divert.c       12 Sep 2017 12:35:00 -0000
@@ -370,23 +370,35 @@ int
 divert6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
     void *newp, size_t newlen)
 {
+       int error;
+
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
 
        switch (name[0]) {
        case DIVERT6CTL_SENDSPACE:
-               return (sysctl_int(oldp, oldlenp, newp, newlen,
-                   &divert6_sendspace));
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen,
+                   &divert6_sendspace);
+               NET_UNLOCK();
+               return (error);
        case DIVERT6CTL_RECVSPACE:
-               return (sysctl_int(oldp, oldlenp, newp, newlen,
-                   &divert6_recvspace));
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen,
+                   &divert6_recvspace);
+               NET_UNLOCK();
+               return (error);
        case DIVERT6CTL_STATS:
                return (divert6_sysctl_div6stat(oldp, oldlenp, newp));
        default:
-               if (name[0] < DIVERT6CTL_MAXID)
-                       return sysctl_int_arr(divert6ctl_vars, name, namelen,
+               if (name[0] < DIVERT6CTL_MAXID) {
+                       NET_LOCK();
+                       error = sysctl_int_arr(divert6ctl_vars, name, namelen,
                            oldp, oldlenp, newp, newlen);
+                       NET_UNLOCK();
+                       return (error);
+               }
 
                return (ENOPROTOOPT);
        }
Index: netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.202
diff -u -p -r1.202 ip6_input.c
--- netinet6/ip6_input.c        22 Aug 2017 15:02:34 -0000      1.202
+++ netinet6/ip6_input.c        12 Sep 2017 13:13:51 -0000
@@ -1383,8 +1383,6 @@ ip6_sysctl(int *name, u_int namelen, voi
 #endif
        int error;
 
-       NET_ASSERT_LOCKED();
-
        /* Almost all sysctl names at this level are terminal. */
        if (namelen != 1 && name[0] != IPV6CTL_IFQUEUE)
                return (ENOTDIR);
@@ -1398,18 +1396,27 @@ ip6_sysctl(int *name, u_int namelen, voi
        case IPV6CTL_MRTSTATS:
                if (newp != NULL)
                        return (EPERM);
-               return (sysctl_struct(oldp, oldlenp, newp, newlen,
-                   &mrt6stat, sizeof(mrt6stat)));
+               NET_LOCK();
+               error = sysctl_struct(oldp, oldlenp, newp, newlen,
+                   &mrt6stat, sizeof(mrt6stat));
+               NET_UNLOCK();
+               return (error);
        case IPV6CTL_MRTPROTO:
                return sysctl_rdint(oldp, oldlenp, newp, ip6_mrtproto);
        case IPV6CTL_MRTMIF:
                if (newp)
                        return (EPERM);
-               return mrt6_sysctl_mif(oldp, oldlenp);
+               NET_LOCK();
+               error = mrt6_sysctl_mif(oldp, oldlenp);
+               NET_UNLOCK();
+               return (error);
        case IPV6CTL_MRTMFC:
                if (newp)
                        return (EPERM);
-               return mrt6_sysctl_mfc(oldp, oldlenp);
+               NET_LOCK();
+               error = mrt6_sysctl_mfc(oldp, oldlenp);
+               NET_UNLOCK();
+               return (error);
 #else
        case IPV6CTL_MRTSTATS:
        case IPV6CTL_MRTPROTO:
@@ -1418,19 +1425,25 @@ ip6_sysctl(int *name, u_int namelen, voi
                return (EOPNOTSUPP);
 #endif
        case IPV6CTL_MTUDISCTIMEOUT:
+               NET_LOCK();
                error = sysctl_int(oldp, oldlenp, newp, newlen,
                    &ip6_mtudisc_timeout);
                if (icmp6_mtudisc_timeout_q != NULL)
                        rt_timer_queue_change(icmp6_mtudisc_timeout_q,
                            ip6_mtudisc_timeout);
+               NET_UNLOCK();
                return (error);
        case IPV6CTL_IFQUEUE:
                return (sysctl_niq(name + 1, namelen - 1,
                    oldp, oldlenp, newp, newlen, &ip6intrq));
        default:
-               if (name[0] < IPV6CTL_MAXID)
-                       return (sysctl_int_arr(ipv6ctl_vars, name, namelen,
-                           oldp, oldlenp, newp, newlen));
+               if (name[0] < IPV6CTL_MAXID) {
+                       NET_LOCK();
+                       error = sysctl_int_arr(ipv6ctl_vars, name, namelen,
+                           oldp, oldlenp, newp, newlen);
+                       NET_UNLOCK();
+                       return (error);
+               }
                return (EOPNOTSUPP);
        }
        /* NOTREACHED */

Reply via email to