The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_sysctl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 1982, 1986, 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * Mike Karels at Berkeley Software Design, Inc.
    9  *
   10  * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
   11  * project, to make these variables more userfriendly.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. Neither the name of the University nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  *      @(#)kern_sysctl.c       8.4 (Berkeley) 4/14/94
   38  */
   39 
   40 #include <sys/cdefs.h>
   41 __FBSDID("$FreeBSD$");
   42 
   43 #include "opt_capsicum.h"
   44 #include "opt_ddb.h"
   45 #include "opt_ktrace.h"
   46 #include "opt_sysctl.h"
   47 
   48 #include <sys/param.h>
   49 #include <sys/fail.h>
   50 #include <sys/systm.h>
   51 #include <sys/capsicum.h>
   52 #include <sys/kernel.h>
   53 #include <sys/limits.h>
   54 #include <sys/sysctl.h>
   55 #include <sys/malloc.h>
   56 #include <sys/priv.h>
   57 #include <sys/proc.h>
   58 #include <sys/jail.h>
   59 #include <sys/kdb.h>
   60 #include <sys/lock.h>
   61 #include <sys/mutex.h>
   62 #include <sys/rmlock.h>
   63 #include <sys/sbuf.h>
   64 #include <sys/sx.h>
   65 #include <sys/sysproto.h>
   66 #include <sys/uio.h>
   67 #ifdef KTRACE
   68 #include <sys/ktrace.h>
   69 #endif
   70 
   71 #ifdef DDB
   72 #include <ddb/ddb.h>
   73 #include <ddb/db_lex.h>
   74 #endif
   75 
   76 #include <net/vnet.h>
   77 
   78 #include <security/mac/mac_framework.h>
   79 
   80 #include <vm/vm.h>
   81 #include <vm/vm_extern.h>
   82 
   83 static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic");
   84 static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids");
   85 static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer");
   86 
   87 /*
   88  * The sysctllock protects the MIB tree.  It also protects sysctl
   89  * contexts used with dynamic sysctls.  The sysctl_register_oid() and
   90  * sysctl_unregister_oid() routines require the sysctllock to already
   91  * be held, so the sysctl_wlock() and sysctl_wunlock() routines are
   92  * provided for the few places in the kernel which need to use that
   93  * API rather than using the dynamic API.  Use of the dynamic API is
   94  * strongly encouraged for most code.
   95  *
   96  * The sysctlmemlock is used to limit the amount of user memory wired for
   97  * sysctl requests.  This is implemented by serializing any userland
   98  * sysctl requests larger than a single page via an exclusive lock.
   99  *
  100  * The sysctlstringlock is used to protect concurrent access to writable
  101  * string nodes in sysctl_handle_string().
  102  */
  103 static struct rmlock sysctllock;
  104 static struct sx __exclusive_cache_line sysctlmemlock;
  105 static struct sx sysctlstringlock;
  106 
  107 #define SYSCTL_WLOCK()          rm_wlock(&sysctllock)
  108 #define SYSCTL_WUNLOCK()        rm_wunlock(&sysctllock)
  109 #define SYSCTL_RLOCK(tracker)   rm_rlock(&sysctllock, (tracker))
  110 #define SYSCTL_RUNLOCK(tracker) rm_runlock(&sysctllock, (tracker))
  111 #define SYSCTL_WLOCKED()        rm_wowned(&sysctllock)
  112 #define SYSCTL_ASSERT_LOCKED()  rm_assert(&sysctllock, RA_LOCKED)
  113 #define SYSCTL_ASSERT_WLOCKED() rm_assert(&sysctllock, RA_WLOCKED)
  114 #define SYSCTL_ASSERT_RLOCKED() rm_assert(&sysctllock, RA_RLOCKED)
  115 #define SYSCTL_INIT()           rm_init_flags(&sysctllock, "sysctl lock", \
  116                                     RM_SLEEPABLE)
  117 #define SYSCTL_SLEEP(ch, wmesg, timo)                                   \
  118                                 rm_sleep(ch, &sysctllock, 0, wmesg, timo)
  119 
  120 static int sysctl_root(SYSCTL_HANDLER_ARGS);
  121 
  122 /* Root list */
  123 struct sysctl_oid_list sysctl__children = SLIST_HEAD_INITIALIZER(&sysctl__children);
  124 
  125 static char*    sysctl_escape_name(const char*);
  126 static int      sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del,
  127                     int recurse);
  128 static int      sysctl_old_kernel(struct sysctl_req *, const void *, size_t);
  129 static int      sysctl_new_kernel(struct sysctl_req *, void *, size_t);
  130 
  131 static struct sysctl_oid *
  132 sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)
  133 {
  134         struct sysctl_oid *oidp;
  135 
  136         SYSCTL_ASSERT_LOCKED();
  137         SYSCTL_FOREACH(oidp, list) {
  138                 if (strcmp(oidp->oid_name, name) == 0) {
  139                         return (oidp);
  140                 }
  141         }
  142         return (NULL);
  143 }
  144 
  145 /*
  146  * Initialization of the MIB tree.
  147  *
  148  * Order by number in each list.
  149  */
  150 void
  151 sysctl_wlock(void)
  152 {
  153 
  154         SYSCTL_WLOCK();
  155 }
  156 
  157 void
  158 sysctl_wunlock(void)
  159 {
  160 
  161         SYSCTL_WUNLOCK();
  162 }
  163 
  164 static int
  165 sysctl_root_handler_locked(struct sysctl_oid *oid, void *arg1, intmax_t arg2,
  166     struct sysctl_req *req, struct rm_priotracker *tracker)
  167 {
  168         int error;
  169 
  170         if (oid->oid_kind & CTLFLAG_DYN)
  171                 atomic_add_int(&oid->oid_running, 1);
  172 
  173         if (tracker != NULL)
  174                 SYSCTL_RUNLOCK(tracker);
  175         else
  176                 SYSCTL_WUNLOCK();
  177 
  178         /*
  179          * Treat set CTLFLAG_NEEDGIANT and unset CTLFLAG_MPSAFE flags the same,
  180          * untill we're ready to remove all traces of Giant from sysctl(9).
  181          */
  182         if ((oid->oid_kind & CTLFLAG_NEEDGIANT) ||
  183             (!(oid->oid_kind & CTLFLAG_MPSAFE)))
  184                 mtx_lock(&Giant);
  185         error = oid->oid_handler(oid, arg1, arg2, req);
  186         if ((oid->oid_kind & CTLFLAG_NEEDGIANT) ||
  187             (!(oid->oid_kind & CTLFLAG_MPSAFE)))
  188                 mtx_unlock(&Giant);
  189 
  190         KFAIL_POINT_ERROR(_debug_fail_point, sysctl_running, error);
  191 
  192         if (tracker != NULL)
  193                 SYSCTL_RLOCK(tracker);
  194         else
  195                 SYSCTL_WLOCK();
  196 
  197         if (oid->oid_kind & CTLFLAG_DYN) {
  198                 if (atomic_fetchadd_int(&oid->oid_running, -1) == 1 &&
  199                     (oid->oid_kind & CTLFLAG_DYING) != 0)
  200                         wakeup(&oid->oid_running);
  201         }
  202 
  203         return (error);
  204 }
  205 
  206 static void
  207 sysctl_load_tunable_by_oid_locked(struct sysctl_oid *oidp)
  208 {
  209         struct sysctl_req req;
  210         struct sysctl_oid *curr;
  211         char *penv = NULL;
  212         char path[96];
  213         ssize_t rem = sizeof(path);
  214         ssize_t len;
  215         uint8_t data[512] __aligned(sizeof(uint64_t));
  216         int size;
  217         int error;
  218 
  219         path[--rem] = 0;
  220 
  221         for (curr = oidp; curr != NULL; curr = SYSCTL_PARENT(curr)) {
  222                 len = strlen(curr->oid_name);
  223                 rem -= len;
  224                 if (curr != oidp)
  225                         rem -= 1;
  226                 if (rem < 0) {
  227                         printf("OID path exceeds %d bytes\n", (int)sizeof(path));
  228                         return;
  229                 }
  230                 memcpy(path + rem, curr->oid_name, len);
  231                 if (curr != oidp)
  232                         path[rem + len] = '.';
  233         }
  234 
  235         memset(&req, 0, sizeof(req));
  236 
  237         req.td = curthread;
  238         req.oldfunc = sysctl_old_kernel;
  239         req.newfunc = sysctl_new_kernel;
  240         req.lock = REQ_UNWIRED;
  241 
  242         switch (oidp->oid_kind & CTLTYPE) {
  243         case CTLTYPE_INT:
  244                 if (getenv_array(path + rem, data, sizeof(data), &size,
  245                     sizeof(int), GETENV_SIGNED) == 0)
  246                         return;
  247                 req.newlen = size;
  248                 req.newptr = data;
  249                 break;
  250         case CTLTYPE_UINT:
  251                 if (getenv_array(path + rem, data, sizeof(data), &size,
  252                     sizeof(int), GETENV_UNSIGNED) == 0)
  253                         return;
  254                 req.newlen = size;
  255                 req.newptr = data;
  256                 break;
  257         case CTLTYPE_LONG:
  258                 if (getenv_array(path + rem, data, sizeof(data), &size,
  259                     sizeof(long), GETENV_SIGNED) == 0)
  260                         return;
  261                 req.newlen = size;
  262                 req.newptr = data;
  263                 break;
  264         case CTLTYPE_ULONG:
  265                 if (getenv_array(path + rem, data, sizeof(data), &size,
  266                     sizeof(long), GETENV_UNSIGNED) == 0)
  267                         return;
  268                 req.newlen = size;
  269                 req.newptr = data;
  270                 break;
  271         case CTLTYPE_S8:
  272                 if (getenv_array(path + rem, data, sizeof(data), &size,
  273                     sizeof(int8_t), GETENV_SIGNED) == 0)
  274                         return;
  275                 req.newlen = size;
  276                 req.newptr = data;
  277                 break;
  278         case CTLTYPE_S16:
  279                 if (getenv_array(path + rem, data, sizeof(data), &size,
  280                     sizeof(int16_t), GETENV_SIGNED) == 0)
  281                         return;
  282                 req.newlen = size;
  283                 req.newptr = data;
  284                 break;
  285         case CTLTYPE_S32:
  286                 if (getenv_array(path + rem, data, sizeof(data), &size,
  287                     sizeof(int32_t), GETENV_SIGNED) == 0)
  288                         return;
  289                 req.newlen = size;
  290                 req.newptr = data;
  291                 break;
  292         case CTLTYPE_S64:
  293                 if (getenv_array(path + rem, data, sizeof(data), &size,
  294                     sizeof(int64_t), GETENV_SIGNED) == 0)
  295                         return;
  296                 req.newlen = size;
  297                 req.newptr = data;
  298                 break;
  299         case CTLTYPE_U8:
  300                 if (getenv_array(path + rem, data, sizeof(data), &size,
  301                     sizeof(uint8_t), GETENV_UNSIGNED) == 0)
  302                         return;
  303                 req.newlen = size;
  304                 req.newptr = data;
  305                 break;
  306         case CTLTYPE_U16:
  307                 if (getenv_array(path + rem, data, sizeof(data), &size,
  308                     sizeof(uint16_t), GETENV_UNSIGNED) == 0)
  309                         return;
  310                 req.newlen = size;
  311                 req.newptr = data;
  312                 break;
  313         case CTLTYPE_U32:
  314                 if (getenv_array(path + rem, data, sizeof(data), &size,
  315                     sizeof(uint32_t), GETENV_UNSIGNED) == 0)
  316                         return;
  317                 req.newlen = size;
  318                 req.newptr = data;
  319                 break;
  320         case CTLTYPE_U64:
  321                 if (getenv_array(path + rem, data, sizeof(data), &size,
  322                     sizeof(uint64_t), GETENV_UNSIGNED) == 0)
  323                         return;
  324                 req.newlen = size;
  325                 req.newptr = data;
  326                 break;
  327         case CTLTYPE_STRING:
  328                 penv = kern_getenv(path + rem);
  329                 if (penv == NULL)
  330                         return;
  331                 req.newlen = strlen(penv);
  332                 req.newptr = penv;
  333                 break;
  334         default:
  335                 return;
  336         }
  337         error = sysctl_root_handler_locked(oidp, oidp->oid_arg1,
  338             oidp->oid_arg2, &req, NULL);
  339         if (error != 0)
  340                 printf("Setting sysctl %s failed: %d\n", path + rem, error);
  341         if (penv != NULL)
  342                 freeenv(penv);
  343 }
  344 
  345 /*
  346  * Locate the path to a given oid.  Returns the length of the resulting path,
  347  * or -1 if the oid was not found.  nodes must have room for CTL_MAXNAME
  348  * elements and be NULL initialized.
  349  */
  350 static int
  351 sysctl_search_oid(struct sysctl_oid **nodes, struct sysctl_oid *needle)
  352 {
  353         int indx;
  354 
  355         SYSCTL_ASSERT_LOCKED();
  356         indx = 0;
  357         while (indx < CTL_MAXNAME && indx >= 0) {
  358                 if (nodes[indx] == NULL && indx == 0)
  359                         nodes[indx] = SLIST_FIRST(&sysctl__children);
  360                 else if (nodes[indx] == NULL)
  361                         nodes[indx] = SLIST_FIRST(&nodes[indx - 1]->oid_children);
  362                 else
  363                         nodes[indx] = SLIST_NEXT(nodes[indx], oid_link);
  364 
  365                 if (nodes[indx] == needle)
  366                         return (indx + 1);
  367 
  368                 if (nodes[indx] == NULL) {
  369                         indx--;
  370                         continue;
  371                 }
  372 
  373                 if ((nodes[indx]->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
  374                         indx++;
  375                         continue;
  376                 }
  377         }
  378         return (-1);
  379 }
  380 
  381 static void
  382 sysctl_warn_reuse(const char *func, struct sysctl_oid *leaf)
  383 {
  384         struct sysctl_oid *nodes[CTL_MAXNAME];
  385         char buf[128];
  386         struct sbuf sb;
  387         int rc, i;
  388 
  389         (void)sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN | SBUF_INCLUDENUL);
  390         sbuf_set_drain(&sb, sbuf_printf_drain, NULL);
  391 
  392         sbuf_printf(&sb, "%s: can't re-use a leaf (", __func__);
  393 
  394         memset(nodes, 0, sizeof(nodes));
  395         rc = sysctl_search_oid(nodes, leaf);
  396         if (rc > 0) {
  397                 for (i = 0; i < rc; i++)
  398                         sbuf_printf(&sb, "%s%.*s", nodes[i]->oid_name,
  399                             i != (rc - 1), ".");
  400         } else {
  401                 sbuf_printf(&sb, "%s", leaf->oid_name);
  402         }
  403         sbuf_printf(&sb, ")!\n");
  404 
  405         (void)sbuf_finish(&sb);
  406 }
  407 
  408 #ifdef SYSCTL_DEBUG
  409 static int
  410 sysctl_reuse_test(SYSCTL_HANDLER_ARGS)
  411 {
  412         struct rm_priotracker tracker;
  413 
  414         SYSCTL_RLOCK(&tracker);
  415         sysctl_warn_reuse(__func__, oidp);
  416         SYSCTL_RUNLOCK(&tracker);
  417         return (0);
  418 }
  419 SYSCTL_PROC(_sysctl, OID_AUTO, reuse_test,
  420     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 0, sysctl_reuse_test, "-",
  421     "");
  422 #endif
  423 
  424 void
  425 sysctl_register_oid(struct sysctl_oid *oidp)
  426 {
  427         struct sysctl_oid_list *parent = oidp->oid_parent;
  428         struct sysctl_oid *p;
  429         struct sysctl_oid *q;
  430         int oid_number;
  431         int timeout = 2;
  432 
  433         /*
  434          * First check if another oid with the same name already
  435          * exists in the parent's list.
  436          */
  437         SYSCTL_ASSERT_WLOCKED();
  438         p = sysctl_find_oidname(oidp->oid_name, parent);
  439         if (p != NULL) {
  440                 if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
  441                         p->oid_refcnt++;
  442                         return;
  443                 } else {
  444                         sysctl_warn_reuse(__func__, p);
  445                         return;
  446                 }
  447         }
  448         /* get current OID number */
  449         oid_number = oidp->oid_number;
  450 
  451 #if (OID_AUTO >= 0)
  452 #error "OID_AUTO is expected to be a negative value"
  453 #endif  
  454         /*
  455          * Any negative OID number qualifies as OID_AUTO. Valid OID
  456          * numbers should always be positive.
  457          *
  458          * NOTE: DO NOT change the starting value here, change it in
  459          * <sys/sysctl.h>, and make sure it is at least 256 to
  460          * accommodate e.g. net.inet.raw as a static sysctl node.
  461          */
  462         if (oid_number < 0) {
  463                 static int newoid;
  464 
  465                 /*
  466                  * By decrementing the next OID number we spend less
  467                  * time inserting the OIDs into a sorted list.
  468                  */
  469                 if (--newoid < CTL_AUTO_START)
  470                         newoid = 0x7fffffff;
  471 
  472                 oid_number = newoid;
  473         }
  474 
  475         /*
  476          * Insert the OID into the parent's list sorted by OID number.
  477          */
  478 retry:
  479         q = NULL;
  480         SLIST_FOREACH(p, parent, oid_link) {
  481                 /* check if the current OID number is in use */
  482                 if (oid_number == p->oid_number) {
  483                         /* get the next valid OID number */
  484                         if (oid_number < CTL_AUTO_START ||
  485                             oid_number == 0x7fffffff) {
  486                                 /* wraparound - restart */
  487                                 oid_number = CTL_AUTO_START;
  488                                 /* don't loop forever */
  489                                 if (!timeout--)
  490                                         panic("sysctl: Out of OID numbers\n");
  491                                 goto retry;
  492                         } else {
  493                                 oid_number++;
  494                         }
  495                 } else if (oid_number < p->oid_number)
  496                         break;
  497                 q = p;
  498         }
  499         /* check for non-auto OID number collision */
  500         if (oidp->oid_number >= 0 && oidp->oid_number < CTL_AUTO_START &&
  501             oid_number >= CTL_AUTO_START) {
  502                 printf("sysctl: OID number(%d) is already in use for '%s'\n",
  503                     oidp->oid_number, oidp->oid_name);
  504         }
  505         /* update the OID number, if any */
  506         oidp->oid_number = oid_number;
  507         if (q != NULL)
  508                 SLIST_INSERT_AFTER(q, oidp, oid_link);
  509         else
  510                 SLIST_INSERT_HEAD(parent, oidp, oid_link);
  511 
  512         if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE &&
  513 #ifdef VIMAGE
  514             (oidp->oid_kind & CTLFLAG_VNET) == 0 &&
  515 #endif
  516             (oidp->oid_kind & CTLFLAG_TUN) != 0 &&
  517             (oidp->oid_kind & CTLFLAG_NOFETCH) == 0) {
  518                 /* only fetch value once */
  519                 oidp->oid_kind |= CTLFLAG_NOFETCH;
  520                 /* try to fetch value from kernel environment */
  521                 sysctl_load_tunable_by_oid_locked(oidp);
  522         }
  523 }
  524 
  525 void
  526 sysctl_register_disabled_oid(struct sysctl_oid *oidp)
  527 {
  528 
  529         /*
  530          * Mark the leaf as dormant if it's not to be immediately enabled.
  531          * We do not disable nodes as they can be shared between modules
  532          * and it is always safe to access a node.
  533          */
  534         KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) == 0,
  535             ("internal flag is set in oid_kind"));
  536         if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
  537                 oidp->oid_kind |= CTLFLAG_DORMANT;
  538         sysctl_register_oid(oidp);
  539 }
  540 
  541 void
  542 sysctl_enable_oid(struct sysctl_oid *oidp)
  543 {
  544 
  545         SYSCTL_ASSERT_WLOCKED();
  546         if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
  547                 KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) == 0,
  548                     ("sysctl node is marked as dormant"));
  549                 return;
  550         }
  551         KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) != 0,
  552             ("enabling already enabled sysctl oid"));
  553         oidp->oid_kind &= ~CTLFLAG_DORMANT;
  554 }
  555 
  556 void
  557 sysctl_unregister_oid(struct sysctl_oid *oidp)
  558 {
  559         struct sysctl_oid *p;
  560         int error;
  561 
  562         SYSCTL_ASSERT_WLOCKED();
  563         if (oidp->oid_number == OID_AUTO) {
  564                 error = EINVAL;
  565         } else {
  566                 error = ENOENT;
  567                 SLIST_FOREACH(p, oidp->oid_parent, oid_link) {
  568                         if (p == oidp) {
  569                                 SLIST_REMOVE(oidp->oid_parent, oidp,
  570                                     sysctl_oid, oid_link);
  571                                 error = 0;
  572                                 break;
  573                         }
  574                 }
  575         }
  576 
  577         /* 
  578          * This can happen when a module fails to register and is
  579          * being unloaded afterwards.  It should not be a panic()
  580          * for normal use.
  581          */
  582         if (error) {
  583                 printf("%s: failed(%d) to unregister sysctl(%s)\n",
  584                     __func__, error, oidp->oid_name);
  585         }
  586 }
  587 
  588 /* Initialize a new context to keep track of dynamically added sysctls. */
  589 int
  590 sysctl_ctx_init(struct sysctl_ctx_list *c)
  591 {
  592 
  593         if (c == NULL) {
  594                 return (EINVAL);
  595         }
  596 
  597         /*
  598          * No locking here, the caller is responsible for not adding
  599          * new nodes to a context until after this function has
  600          * returned.
  601          */
  602         TAILQ_INIT(c);
  603         return (0);
  604 }
  605 
  606 /* Free the context, and destroy all dynamic oids registered in this context */
  607 int
  608 sysctl_ctx_free(struct sysctl_ctx_list *clist)
  609 {
  610         struct sysctl_ctx_entry *e, *e1;
  611         int error;
  612 
  613         error = 0;
  614         /*
  615          * First perform a "dry run" to check if it's ok to remove oids.
  616          * XXX FIXME
  617          * XXX This algorithm is a hack. But I don't know any
  618          * XXX better solution for now...
  619          */
  620         SYSCTL_WLOCK();
  621         TAILQ_FOREACH(e, clist, link) {
  622                 error = sysctl_remove_oid_locked(e->entry, 0, 0);
  623                 if (error)
  624                         break;
  625         }
  626         /*
  627          * Restore deregistered entries, either from the end,
  628          * or from the place where error occurred.
  629          * e contains the entry that was not unregistered
  630          */
  631         if (error)
  632                 e1 = TAILQ_PREV(e, sysctl_ctx_list, link);
  633         else
  634                 e1 = TAILQ_LAST(clist, sysctl_ctx_list);
  635         while (e1 != NULL) {
  636                 sysctl_register_oid(e1->entry);
  637                 e1 = TAILQ_PREV(e1, sysctl_ctx_list, link);
  638         }
  639         if (error) {
  640                 SYSCTL_WUNLOCK();
  641                 return(EBUSY);
  642         }
  643         /* Now really delete the entries */
  644         e = TAILQ_FIRST(clist);
  645         while (e != NULL) {
  646                 e1 = TAILQ_NEXT(e, link);
  647                 error = sysctl_remove_oid_locked(e->entry, 1, 0);
  648                 if (error)
  649                         panic("sysctl_remove_oid: corrupt tree, entry: %s",
  650                             e->entry->oid_name);
  651                 free(e, M_SYSCTLOID);
  652                 e = e1;
  653         }
  654         SYSCTL_WUNLOCK();
  655         return (error);
  656 }
  657 
  658 /* Add an entry to the context */
  659 struct sysctl_ctx_entry *
  660 sysctl_ctx_entry_add(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
  661 {
  662         struct sysctl_ctx_entry *e;
  663 
  664         SYSCTL_ASSERT_WLOCKED();
  665         if (clist == NULL || oidp == NULL)
  666                 return(NULL);
  667         e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK);
  668         e->entry = oidp;
  669         TAILQ_INSERT_HEAD(clist, e, link);
  670         return (e);
  671 }
  672 
  673 /* Find an entry in the context */
  674 struct sysctl_ctx_entry *
  675 sysctl_ctx_entry_find(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
  676 {
  677         struct sysctl_ctx_entry *e;
  678 
  679         SYSCTL_ASSERT_WLOCKED();
  680         if (clist == NULL || oidp == NULL)
  681                 return(NULL);
  682         TAILQ_FOREACH(e, clist, link) {
  683                 if(e->entry == oidp)
  684                         return(e);
  685         }
  686         return (e);
  687 }
  688 
  689 /*
  690  * Delete an entry from the context.
  691  * NOTE: this function doesn't free oidp! You have to remove it
  692  * with sysctl_remove_oid().
  693  */
  694 int
  695 sysctl_ctx_entry_del(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
  696 {
  697         struct sysctl_ctx_entry *e;
  698 
  699         if (clist == NULL || oidp == NULL)
  700                 return (EINVAL);
  701         SYSCTL_WLOCK();
  702         e = sysctl_ctx_entry_find(clist, oidp);
  703         if (e != NULL) {
  704                 TAILQ_REMOVE(clist, e, link);
  705                 SYSCTL_WUNLOCK();
  706                 free(e, M_SYSCTLOID);
  707                 return (0);
  708         } else {
  709                 SYSCTL_WUNLOCK();
  710                 return (ENOENT);
  711         }
  712 }
  713 
  714 /*
  715  * Remove dynamically created sysctl trees.
  716  * oidp - top of the tree to be removed
  717  * del - if 0 - just deregister, otherwise free up entries as well
  718  * recurse - if != 0 traverse the subtree to be deleted
  719  */
  720 int
  721 sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse)
  722 {
  723         int error;
  724 
  725         SYSCTL_WLOCK();
  726         error = sysctl_remove_oid_locked(oidp, del, recurse);
  727         SYSCTL_WUNLOCK();
  728         return (error);
  729 }
  730 
  731 int
  732 sysctl_remove_name(struct sysctl_oid *parent, const char *name,
  733     int del, int recurse)
  734 {
  735         struct sysctl_oid *p, *tmp;
  736         int error;
  737 
  738         error = ENOENT;
  739         SYSCTL_WLOCK();
  740         SLIST_FOREACH_SAFE(p, SYSCTL_CHILDREN(parent), oid_link, tmp) {
  741                 if (strcmp(p->oid_name, name) == 0) {
  742                         error = sysctl_remove_oid_locked(p, del, recurse);
  743                         break;
  744                 }
  745         }
  746         SYSCTL_WUNLOCK();
  747 
  748         return (error);
  749 }
  750 
  751 /*
  752  * Duplicate the provided string, escaping any illegal characters.  The result
  753  * must be freed when no longer in use.
  754  *
  755  * The list of illegal characters is ".".
  756  */
  757 static char*
  758 sysctl_escape_name(const char* orig)
  759 {
  760         int i, s = 0, d = 0, nillegals = 0;
  761         char *new;
  762 
  763         /* First count the number of illegal characters */
  764         for (i = 0; orig[i] != '\0'; i++) {
  765                 if (orig[i] == '.')
  766                         nillegals++;
  767         }
  768 
  769         /* Allocate storage for new string */
  770         new = malloc(i + 2 * nillegals + 1, M_SYSCTLOID, M_WAITOK);
  771 
  772         /* Copy the name, escaping characters as we go */
  773         while (orig[s] != '\0') {
  774                 if (orig[s] == '.') {
  775                         /* %25 is the hexadecimal representation of '.' */
  776                         new[d++] = '%';
  777                         new[d++] = '2';
  778                         new[d++] = '5';
  779                         s++;
  780                 } else {
  781                         new[d++] = orig[s++];
  782                 }
  783         }
  784 
  785         /* Finally, nul-terminate */
  786         new[d] = '\0';
  787 
  788         return (new);
  789 }
  790 
  791 static int
  792 sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse)
  793 {
  794         struct sysctl_oid *p, *tmp;
  795         int error;
  796 
  797         SYSCTL_ASSERT_WLOCKED();
  798         if (oidp == NULL)
  799                 return(EINVAL);
  800         if ((oidp->oid_kind & CTLFLAG_DYN) == 0) {
  801                 printf("Warning: can't remove non-dynamic nodes (%s)!\n",
  802                     oidp->oid_name);
  803                 return (EINVAL);
  804         }
  805         /*
  806          * WARNING: normal method to do this should be through
  807          * sysctl_ctx_free(). Use recursing as the last resort
  808          * method to purge your sysctl tree of leftovers...
  809          * However, if some other code still references these nodes,
  810          * it will panic.
  811          */
  812         if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
  813                 if (oidp->oid_refcnt == 1) {
  814                         SLIST_FOREACH_SAFE(p,
  815                             SYSCTL_CHILDREN(oidp), oid_link, tmp) {
  816                                 if (!recurse) {
  817                                         printf("Warning: failed attempt to "
  818                                             "remove oid %s with child %s\n",
  819                                             oidp->oid_name, p->oid_name);
  820                                         return (ENOTEMPTY);
  821                                 }
  822                                 error = sysctl_remove_oid_locked(p, del,
  823                                     recurse);
  824                                 if (error)
  825                                         return (error);
  826                         }
  827                 }
  828         }
  829         if (oidp->oid_refcnt > 1 ) {
  830                 oidp->oid_refcnt--;
  831         } else {
  832                 if (oidp->oid_refcnt == 0) {
  833                         printf("Warning: bad oid_refcnt=%u (%s)!\n",
  834                                 oidp->oid_refcnt, oidp->oid_name);
  835                         return (EINVAL);
  836                 }
  837                 sysctl_unregister_oid(oidp);
  838                 if (del) {
  839                         /*
  840                          * Wait for all threads running the handler to drain.
  841                          * This preserves the previous behavior when the
  842                          * sysctl lock was held across a handler invocation,
  843                          * and is necessary for module unload correctness.
  844                          */
  845                         while (oidp->oid_running > 0) {
  846                                 oidp->oid_kind |= CTLFLAG_DYING;
  847                                 SYSCTL_SLEEP(&oidp->oid_running, "oidrm", 0);
  848                         }
  849                         if (oidp->oid_descr)
  850                                 free(__DECONST(char *, oidp->oid_descr),
  851                                     M_SYSCTLOID);
  852                         if (oidp->oid_label)
  853                                 free(__DECONST(char *, oidp->oid_label),
  854                                     M_SYSCTLOID);
  855                         free(__DECONST(char *, oidp->oid_name), M_SYSCTLOID);
  856                         free(oidp, M_SYSCTLOID);
  857                 }
  858         }
  859         return (0);
  860 }
  861 /*
  862  * Create new sysctls at run time.
  863  * clist may point to a valid context initialized with sysctl_ctx_init().
  864  */
  865 struct sysctl_oid *
  866 sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
  867         int number, const char *name, int kind, void *arg1, intmax_t arg2,
  868         int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr,
  869         const char *label)
  870 {
  871         struct sysctl_oid *oidp;
  872         char *escaped;
  873 
  874         /* You have to hook up somewhere.. */
  875         if (parent == NULL)
  876                 return(NULL);
  877         escaped = sysctl_escape_name(name);
  878         /* Check if the node already exists, otherwise create it */
  879         SYSCTL_WLOCK();
  880         oidp = sysctl_find_oidname(escaped, parent);
  881         if (oidp != NULL) {
  882                 free(escaped, M_SYSCTLOID);
  883                 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
  884                         oidp->oid_refcnt++;
  885                         /* Update the context */
  886                         if (clist != NULL)
  887                                 sysctl_ctx_entry_add(clist, oidp);
  888                         SYSCTL_WUNLOCK();
  889                         return (oidp);
  890                 } else {
  891                         sysctl_warn_reuse(__func__, oidp);
  892                         SYSCTL_WUNLOCK();
  893                         return (NULL);
  894                 }
  895         }
  896         oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK|M_ZERO);
  897         oidp->oid_parent = parent;
  898         SLIST_INIT(&oidp->oid_children);
  899         oidp->oid_number = number;
  900         oidp->oid_refcnt = 1;
  901         oidp->oid_name = escaped;
  902         oidp->oid_handler = handler;
  903         oidp->oid_kind = CTLFLAG_DYN | kind;
  904         oidp->oid_arg1 = arg1;
  905         oidp->oid_arg2 = arg2;
  906         oidp->oid_fmt = fmt;
  907         if (descr != NULL)
  908                 oidp->oid_descr = strdup(descr, M_SYSCTLOID);
  909         if (label != NULL)
  910                 oidp->oid_label = strdup(label, M_SYSCTLOID);
  911         /* Update the context, if used */
  912         if (clist != NULL)
  913                 sysctl_ctx_entry_add(clist, oidp);
  914         /* Register this oid */
  915         sysctl_register_oid(oidp);
  916         SYSCTL_WUNLOCK();
  917         return (oidp);
  918 }
  919 
  920 /*
  921  * Rename an existing oid.
  922  */
  923 void
  924 sysctl_rename_oid(struct sysctl_oid *oidp, const char *name)
  925 {
  926         char *newname;
  927         char *oldname;
  928 
  929         newname = strdup(name, M_SYSCTLOID);
  930         SYSCTL_WLOCK();
  931         oldname = __DECONST(char *, oidp->oid_name);
  932         oidp->oid_name = newname;
  933         SYSCTL_WUNLOCK();
  934         free(oldname, M_SYSCTLOID);
  935 }
  936 
  937 /*
  938  * Reparent an existing oid.
  939  */
  940 int
  941 sysctl_move_oid(struct sysctl_oid *oid, struct sysctl_oid_list *parent)
  942 {
  943         struct sysctl_oid *oidp;
  944 
  945         SYSCTL_WLOCK();
  946         if (oid->oid_parent == parent) {
  947                 SYSCTL_WUNLOCK();
  948                 return (0);
  949         }
  950         oidp = sysctl_find_oidname(oid->oid_name, parent);
  951         if (oidp != NULL) {
  952                 SYSCTL_WUNLOCK();
  953                 return (EEXIST);
  954         }
  955         sysctl_unregister_oid(oid);
  956         oid->oid_parent = parent;
  957         oid->oid_number = OID_AUTO;
  958         sysctl_register_oid(oid);
  959         SYSCTL_WUNLOCK();
  960         return (0);
  961 }
  962 
  963 /*
  964  * Register the kernel's oids on startup.
  965  */
  966 SET_DECLARE(sysctl_set, struct sysctl_oid);
  967 
  968 static void
  969 sysctl_register_all(void *arg)
  970 {
  971         struct sysctl_oid **oidp;
  972 
  973         sx_init(&sysctlmemlock, "sysctl mem");
  974         sx_init(&sysctlstringlock, "sysctl string handler");
  975         SYSCTL_INIT();
  976         SYSCTL_WLOCK();
  977         SET_FOREACH(oidp, sysctl_set)
  978                 sysctl_register_oid(*oidp);
  979         SYSCTL_WUNLOCK();
  980 }
  981 SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_register_all, NULL);
  982 
  983 /*
  984  * "Staff-functions"
  985  *
  986  * These functions implement a presently undocumented interface 
  987  * used by the sysctl program to walk the tree, and get the type
  988  * so it can print the value.
  989  * This interface is under work and consideration, and should probably
  990  * be killed with a big axe by the first person who can find the time.
  991  * (be aware though, that the proper interface isn't as obvious as it
  992  * may seem, there are various conflicting requirements.
  993  *
  994  * {CTL_SYSCTL, CTL_SYSCTL_DEBUG}               printf the entire MIB-tree.
  995  * {CTL_SYSCTL, CTL_SYSCTL_NAME, ...}           return the name of the "..."
  996  *                                              OID.
  997  * {CTL_SYSCTL, CTL_SYSCTL_NEXT, ...}           return the next OID, honoring
  998  *                                              CTLFLAG_SKIP.
  999  * {CTL_SYSCTL, CTL_SYSCTL_NAME2OID}            return the OID of the name in
 1000  *                                              "new"
 1001  * {CTL_SYSCTL, CTL_SYSCTL_OIDFMT, ...}         return the kind & format info
 1002  *                                              for the "..." OID.
 1003  * {CTL_SYSCTL, CTL_SYSCTL_OIDDESCR, ...}       return the description of the
 1004  *                                              "..." OID.
 1005  * {CTL_SYSCTL, CTL_SYSCTL_OIDLABEL, ...}       return the aggregation label of
 1006  *                                              the "..." OID.
 1007  * {CTL_SYSCTL, CTL_SYSCTL_NEXTNOSKIP, ...}     return the next OID, ignoring
 1008  *                                              CTLFLAG_SKIP.
 1009  */
 1010 
 1011 #ifdef SYSCTL_DEBUG
 1012 static void
 1013 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i)
 1014 {
 1015         int k;
 1016         struct sysctl_oid *oidp;
 1017 
 1018         SYSCTL_ASSERT_LOCKED();
 1019         SYSCTL_FOREACH(oidp, l) {
 1020                 for (k=0; k<i; k++)
 1021                         printf(" ");
 1022 
 1023                 printf("%d %s ", oidp->oid_number, oidp->oid_name);
 1024 
 1025                 printf("%c%c",
 1026                         oidp->oid_kind & CTLFLAG_RD ? 'R':' ',
 1027                         oidp->oid_kind & CTLFLAG_WR ? 'W':' ');
 1028 
 1029                 if (oidp->oid_handler)
 1030                         printf(" *Handler");
 1031 
 1032                 switch (oidp->oid_kind & CTLTYPE) {
 1033                         case CTLTYPE_NODE:
 1034                                 printf(" Node\n");
 1035                                 if (!oidp->oid_handler) {
 1036                                         sysctl_sysctl_debug_dump_node(
 1037                                             SYSCTL_CHILDREN(oidp), i + 2);
 1038                                 }
 1039                                 break;
 1040                         case CTLTYPE_INT:    printf(" Int\n"); break;
 1041                         case CTLTYPE_UINT:   printf(" u_int\n"); break;
 1042                         case CTLTYPE_LONG:   printf(" Long\n"); break;
 1043                         case CTLTYPE_ULONG:  printf(" u_long\n"); break;
 1044                         case CTLTYPE_STRING: printf(" String\n"); break;
 1045                         case CTLTYPE_S8:     printf(" int8_t\n"); break;
 1046                         case CTLTYPE_S16:    printf(" int16_t\n"); break;
 1047                         case CTLTYPE_S32:    printf(" int32_t\n"); break;
 1048                         case CTLTYPE_S64:    printf(" int64_t\n"); break;
 1049                         case CTLTYPE_U8:     printf(" uint8_t\n"); break;
 1050                         case CTLTYPE_U16:    printf(" uint16_t\n"); break;
 1051                         case CTLTYPE_U32:    printf(" uint32_t\n"); break;
 1052                         case CTLTYPE_U64:    printf(" uint64_t\n"); break;
 1053                         case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break;
 1054                         default:             printf("\n");
 1055                 }
 1056         }
 1057 }
 1058 
 1059 static int
 1060 sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS)
 1061 {
 1062         struct rm_priotracker tracker;
 1063         int error;
 1064 
 1065         error = priv_check(req->td, PRIV_SYSCTL_DEBUG);
 1066         if (error)
 1067                 return (error);
 1068         SYSCTL_RLOCK(&tracker);
 1069         sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
 1070         SYSCTL_RUNLOCK(&tracker);
 1071         return (ENOENT);
 1072 }
 1073 
 1074 SYSCTL_PROC(_sysctl, CTL_SYSCTL_DEBUG, debug, CTLTYPE_STRING | CTLFLAG_RD |
 1075     CTLFLAG_MPSAFE, 0, 0, sysctl_sysctl_debug, "-", "");
 1076 #endif
 1077 
 1078 static int
 1079 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
 1080 {
 1081         int *name = (int *) arg1;
 1082         u_int namelen = arg2;
 1083         int error;
 1084         struct sysctl_oid *oid;
 1085         struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;
 1086         struct rm_priotracker tracker;
 1087         char buf[10];
 1088 
 1089         error = sysctl_wire_old_buffer(req, 0);
 1090         if (error)
 1091                 return (error);
 1092 
 1093         SYSCTL_RLOCK(&tracker);
 1094         while (namelen) {
 1095                 if (!lsp) {
 1096                         snprintf(buf,sizeof(buf),"%d",*name);
 1097                         if (req->oldidx)
 1098                                 error = SYSCTL_OUT(req, ".", 1);
 1099                         if (!error)
 1100                                 error = SYSCTL_OUT(req, buf, strlen(buf));
 1101                         if (error)
 1102                                 goto out;
 1103                         namelen--;
 1104                         name++;
 1105                         continue;
 1106                 }
 1107                 lsp2 = NULL;
 1108                 SLIST_FOREACH(oid, lsp, oid_link) {
 1109                         if (oid->oid_number != *name)
 1110                                 continue;
 1111 
 1112                         if (req->oldidx)
 1113                                 error = SYSCTL_OUT(req, ".", 1);
 1114                         if (!error)
 1115                                 error = SYSCTL_OUT(req, oid->oid_name,
 1116                                         strlen(oid->oid_name));
 1117                         if (error)
 1118                                 goto out;
 1119 
 1120                         namelen--;
 1121                         name++;
 1122 
 1123                         if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE) 
 1124                                 break;
 1125 
 1126                         if (oid->oid_handler)
 1127                                 break;
 1128 
 1129                         lsp2 = SYSCTL_CHILDREN(oid);
 1130                         break;
 1131                 }
 1132                 lsp = lsp2;
 1133         }
 1134         error = SYSCTL_OUT(req, "", 1);
 1135  out:
 1136         SYSCTL_RUNLOCK(&tracker);
 1137         return (error);
 1138 }
 1139 
 1140 /*
 1141  * XXXRW/JA: Shouldn't return name data for nodes that we don't permit in
 1142  * capability mode.
 1143  */
 1144 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NAME, name, CTLFLAG_RD |
 1145     CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_name, "");
 1146 
 1147 enum sysctl_iter_action {
 1148         ITER_SIBLINGS,  /* Not matched, continue iterating siblings */
 1149         ITER_CHILDREN,  /* Node has children we need to iterate over them */
 1150         ITER_FOUND,     /* Matching node was found */
 1151 };
 1152 
 1153 /*
 1154  * Tries to find the next node for @name and @namelen.
 1155  *
 1156  * Returns next action to take. 
 1157  */
 1158 static enum sysctl_iter_action
 1159 sysctl_sysctl_next_node(struct sysctl_oid *oidp, int *name, unsigned int namelen,
 1160     bool honor_skip)
 1161 {
 1162 
 1163         if ((oidp->oid_kind & CTLFLAG_DORMANT) != 0)
 1164                 return (ITER_SIBLINGS);
 1165 
 1166         if (honor_skip && (oidp->oid_kind & CTLFLAG_SKIP) != 0)
 1167                 return (ITER_SIBLINGS);
 1168 
 1169         if (namelen == 0) {
 1170                 /*
 1171                  * We have reached a node with a full name match and are
 1172                  * looking for the next oid in its children.
 1173                  *
 1174                  * For CTL_SYSCTL_NEXTNOSKIP we are done.
 1175                  *
 1176                  * For CTL_SYSCTL_NEXT we skip CTLTYPE_NODE (unless it
 1177                  * has a handler) and move on to the children.
 1178                  */
 1179                 if (!honor_skip)
 1180                         return (ITER_FOUND);
 1181                 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 
 1182                         return (ITER_FOUND);
 1183                 /* If node does not have an iterator, treat it as leaf */
 1184                 if (oidp->oid_handler) 
 1185                         return (ITER_FOUND);
 1186 
 1187                 /* Report oid as a node to iterate */
 1188                 return (ITER_CHILDREN);
 1189         }
 1190 
 1191         /*
 1192          * No match yet. Continue seeking the given name.
 1193          *
 1194          * We are iterating in order by oid_number, so skip oids lower
 1195          * than the one we are looking for.
 1196          *
 1197          * When the current oid_number is higher than the one we seek,
 1198          * that means we have reached the next oid in the sequence and
 1199          * should return it.
 1200          *
 1201          * If the oid_number matches the name at this level then we
 1202          * have to find a node to continue searching at the next level.
 1203          */
 1204         if (oidp->oid_number < *name)
 1205                 return (ITER_SIBLINGS);
 1206         if (oidp->oid_number > *name) {
 1207                 /*
 1208                  * We have reached the next oid.
 1209                  *
 1210                  * For CTL_SYSCTL_NEXTNOSKIP we are done.
 1211                  *
 1212                  * For CTL_SYSCTL_NEXT we skip CTLTYPE_NODE (unless it
 1213                  * has a handler) and move on to the children.
 1214                  */
 1215                 if (!honor_skip)
 1216                         return (ITER_FOUND);
 1217                 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
 1218                         return (ITER_FOUND);
 1219                 /* If node does not have an iterator, treat it as leaf */
 1220                 if (oidp->oid_handler)
 1221                         return (ITER_FOUND);
 1222                 return (ITER_CHILDREN);
 1223         }
 1224 
 1225         /* match at a current level */
 1226         if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
 1227                 return (ITER_SIBLINGS);
 1228         if (oidp->oid_handler)
 1229                 return (ITER_SIBLINGS);
 1230 
 1231         return (ITER_CHILDREN);
 1232 }
 1233 
 1234 /*
 1235  * Recursively walk the sysctl subtree at lsp until we find the given name.
 1236  * Returns true and fills in next oid data in @next and @len if oid is found.
 1237  */
 1238 static bool
 1239 sysctl_sysctl_next_action(struct sysctl_oid_list *lsp, int *name, u_int namelen, 
 1240     int *next, int *len, int level, bool honor_skip)
 1241 {
 1242         struct sysctl_oid *oidp;
 1243         bool success = false;
 1244         enum sysctl_iter_action action;
 1245 
 1246         SYSCTL_ASSERT_LOCKED();
 1247         SLIST_FOREACH(oidp, lsp, oid_link) {
 1248                 action = sysctl_sysctl_next_node(oidp, name, namelen, honor_skip);
 1249                 if (action == ITER_SIBLINGS)
 1250                         continue;
 1251                 if (action == ITER_FOUND) {
 1252                         success = true;
 1253                         break;
 1254                 }
 1255                 KASSERT((action== ITER_CHILDREN), ("ret(%d)!=ITER_CHILDREN", action));
 1256 
 1257                 lsp = SYSCTL_CHILDREN(oidp);
 1258                 if (namelen == 0) {
 1259                         success = sysctl_sysctl_next_action(lsp, NULL, 0,
 1260                             next + 1, len, level + 1, honor_skip);
 1261                 } else {
 1262                         success = sysctl_sysctl_next_action(lsp, name + 1, namelen - 1,
 1263                             next + 1, len, level + 1, honor_skip);
 1264                         if (!success) {
 1265 
 1266                                 /*
 1267                                  * We maintain the invariant that current node oid
 1268                                  * is >= the oid provided in @name.
 1269                                  * As there are no usable children at this node,
 1270                                  *  current node oid is strictly > than the requested
 1271                                  *  oid.
 1272                                  * Hence, reduce namelen to 0 to allow for picking first
 1273                                  *  nodes/leafs in the next node in list.
 1274                                  */
 1275                                 namelen = 0;
 1276                         }
 1277                 }
 1278                 if (success)
 1279                         break;
 1280         }
 1281 
 1282         if (success) {
 1283                 *next = oidp->oid_number;
 1284                 if (level > *len)
 1285                         *len = level;
 1286         }
 1287 
 1288         return (success);
 1289 }
 1290 
 1291 static int
 1292 sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
 1293 {
 1294         int *name = (int *) arg1;
 1295         u_int namelen = arg2;
 1296         int len, error;
 1297         bool success;
 1298         struct sysctl_oid_list *lsp = &sysctl__children;
 1299         struct rm_priotracker tracker;
 1300         int next[CTL_MAXNAME];
 1301 
 1302         len = 0;
 1303         SYSCTL_RLOCK(&tracker);
 1304         success = sysctl_sysctl_next_action(lsp, name, namelen, next, &len, 1,
 1305             oidp->oid_number == CTL_SYSCTL_NEXT);
 1306         SYSCTL_RUNLOCK(&tracker);
 1307         if (!success)
 1308                 return (ENOENT);
 1309         error = SYSCTL_OUT(req, next, len * sizeof (int));
 1310         return (error);
 1311 }
 1312 
 1313 /*
 1314  * XXXRW/JA: Shouldn't return next data for nodes that we don't permit in
 1315  * capability mode.
 1316  */
 1317 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NEXT, next, CTLFLAG_RD |
 1318     CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_next, "");
 1319 
 1320 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NEXTNOSKIP, nextnoskip, CTLFLAG_RD |
 1321     CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_next, "");
 1322 
 1323 static int
 1324 name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp)
 1325 {
 1326         struct sysctl_oid *oidp;
 1327         struct sysctl_oid_list *lsp = &sysctl__children;
 1328         char *p;
 1329 
 1330         SYSCTL_ASSERT_LOCKED();
 1331 
 1332         for (*len = 0; *len < CTL_MAXNAME;) {
 1333                 p = strsep(&name, ".");
 1334 
 1335                 SYSCTL_FOREACH(oidp, lsp) {
 1336                         if (strcmp(p, oidp->oid_name) == 0)
 1337                                 break;
 1338                 }
 1339                 if (oidp == NULL)
 1340                         return (ENOENT);
 1341                 *oid++ = oidp->oid_number;
 1342                 (*len)++;
 1343 
 1344                 if (name == NULL || *name == '\0') {
 1345                         if (oidpp)
 1346                                 *oidpp = oidp;
 1347                         return (0);
 1348                 }
 1349 
 1350                 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
 1351                         break;
 1352 
 1353                 if (oidp->oid_handler)
 1354                         break;
 1355 
 1356                 lsp = SYSCTL_CHILDREN(oidp);
 1357         }
 1358         return (ENOENT);
 1359 }
 1360 
 1361 static int
 1362 sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
 1363 {
 1364         char *p;
 1365         int error, oid[CTL_MAXNAME], len = 0;
 1366         struct sysctl_oid *op = NULL;
 1367         struct rm_priotracker tracker;
 1368         char buf[32];
 1369 
 1370         if (!req->newlen) 
 1371                 return (ENOENT);
 1372         if (req->newlen >= MAXPATHLEN)  /* XXX arbitrary, undocumented */
 1373                 return (ENAMETOOLONG);
 1374 
 1375         p = buf;
 1376         if (req->newlen >= sizeof(buf))
 1377                 p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK);
 1378 
 1379         error = SYSCTL_IN(req, p, req->newlen);
 1380         if (error) {
 1381                 if (p != buf)
 1382                         free(p, M_SYSCTL);
 1383                 return (error);
 1384         }
 1385 
 1386         p [req->newlen] = '\0';
 1387 
 1388         SYSCTL_RLOCK(&tracker);
 1389         error = name2oid(p, oid, &len, &op);
 1390         SYSCTL_RUNLOCK(&tracker);
 1391 
 1392         if (p != buf)
 1393                 free(p, M_SYSCTL);
 1394 
 1395         if (error)
 1396                 return (error);
 1397 
 1398         error = SYSCTL_OUT(req, oid, len * sizeof *oid);
 1399         return (error);
 1400 }
 1401 
 1402 /*
 1403  * XXXRW/JA: Shouldn't return name2oid data for nodes that we don't permit in
 1404  * capability mode.
 1405  */
 1406 SYSCTL_PROC(_sysctl, CTL_SYSCTL_NAME2OID, name2oid, CTLTYPE_INT | CTLFLAG_RW |
 1407     CTLFLAG_ANYBODY | CTLFLAG_MPSAFE | CTLFLAG_CAPRW, 0, 0,
 1408     sysctl_sysctl_name2oid, "I", "");
 1409 
 1410 static int
 1411 sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
 1412 {
 1413         struct sysctl_oid *oid;
 1414         struct rm_priotracker tracker;
 1415         int error;
 1416 
 1417         error = sysctl_wire_old_buffer(req, 0);
 1418         if (error)
 1419                 return (error);
 1420 
 1421         SYSCTL_RLOCK(&tracker);
 1422         error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
 1423         if (error)
 1424                 goto out;
 1425 
 1426         if (oid->oid_fmt == NULL) {
 1427                 error = ENOENT;
 1428                 goto out;
 1429         }
 1430         error = SYSCTL_OUT(req, &oid->oid_kind, sizeof(oid->oid_kind));
 1431         if (error)
 1432                 goto out;
 1433         error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1);
 1434  out:
 1435         SYSCTL_RUNLOCK(&tracker);
 1436         return (error);
 1437 }
 1438 
 1439 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_OIDFMT, oidfmt, CTLFLAG_RD |
 1440     CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_oidfmt, "");
 1441 
 1442 static int
 1443 sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)
 1444 {
 1445         struct sysctl_oid *oid;
 1446         struct rm_priotracker tracker;
 1447         int error;
 1448 
 1449         error = sysctl_wire_old_buffer(req, 0);
 1450         if (error)
 1451                 return (error);
 1452 
 1453         SYSCTL_RLOCK(&tracker);
 1454         error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
 1455         if (error)
 1456                 goto out;
 1457 
 1458         if (oid->oid_descr == NULL) {
 1459                 error = ENOENT;
 1460                 goto out;
 1461         }
 1462         error = SYSCTL_OUT(req, oid->oid_descr, strlen(oid->oid_descr) + 1);
 1463  out:
 1464         SYSCTL_RUNLOCK(&tracker);
 1465         return (error);
 1466 }
 1467 
 1468 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_OIDDESCR, oiddescr, CTLFLAG_RD |
 1469     CTLFLAG_MPSAFE|CTLFLAG_CAPRD, sysctl_sysctl_oiddescr, "");
 1470 
 1471 static int
 1472 sysctl_sysctl_oidlabel(SYSCTL_HANDLER_ARGS)
 1473 {
 1474         struct sysctl_oid *oid;
 1475         struct rm_priotracker tracker;
 1476         int error;
 1477 
 1478         error = sysctl_wire_old_buffer(req, 0);
 1479         if (error)
 1480                 return (error);
 1481 
 1482         SYSCTL_RLOCK(&tracker);
 1483         error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
 1484         if (error)
 1485                 goto out;
 1486 
 1487         if (oid->oid_label == NULL) {
 1488                 error = ENOENT;
 1489                 goto out;
 1490         }
 1491         error = SYSCTL_OUT(req, oid->oid_label, strlen(oid->oid_label) + 1);
 1492  out:
 1493         SYSCTL_RUNLOCK(&tracker);
 1494         return (error);
 1495 }
 1496 
 1497 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_OIDLABEL, oidlabel, CTLFLAG_RD |
 1498     CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_oidlabel, "");
 1499 
 1500 /*
 1501  * Default "handler" functions.
 1502  */
 1503 
 1504 /*
 1505  * Handle a bool.
 1506  * Two cases:
 1507  *     a variable:  point arg1 at it.
 1508  *     a constant:  pass it in arg2.
 1509  */
 1510 
 1511 int
 1512 sysctl_handle_bool(SYSCTL_HANDLER_ARGS)
 1513 {
 1514         uint8_t temp;
 1515         int error;
 1516 
 1517         /*
 1518          * Attempt to get a coherent snapshot by making a copy of the data.
 1519          */
 1520         if (arg1)
 1521                 temp = *(bool *)arg1 ? 1 : 0;
 1522         else
 1523                 temp = arg2 ? 1 : 0;
 1524 
 1525         error = SYSCTL_OUT(req, &temp, sizeof(temp));
 1526         if (error || !req->newptr)
 1527                 return (error);
 1528 
 1529         if (!arg1)
 1530                 error = EPERM;
 1531         else {
 1532                 error = SYSCTL_IN(req, &temp, sizeof(temp));
 1533                 if (!error)
 1534                         *(bool *)arg1 = temp ? 1 : 0;
 1535         }
 1536         return (error);
 1537 }
 1538 
 1539 /*
 1540  * Handle an int8_t, signed or unsigned.
 1541  * Two cases:
 1542  *     a variable:  point arg1 at it.
 1543  *     a constant:  pass it in arg2.
 1544  */
 1545 
 1546 int
 1547 sysctl_handle_8(SYSCTL_HANDLER_ARGS)
 1548 {
 1549         int8_t tmpout;
 1550         int error = 0;
 1551 
 1552         /*
 1553          * Attempt to get a coherent snapshot by making a copy of the data.
 1554          */
 1555         if (arg1)
 1556                 tmpout = *(int8_t *)arg1;
 1557         else
 1558                 tmpout = arg2;
 1559         error = SYSCTL_OUT(req, &tmpout, sizeof(tmpout));
 1560 
 1561         if (error || !req->newptr)
 1562                 return (error);
 1563 
 1564         if (!arg1)
 1565                 error = EPERM;
 1566         else
 1567                 error = SYSCTL_IN(req, arg1, sizeof(tmpout));
 1568         return (error);
 1569 }
 1570 
 1571 /*
 1572  * Handle an int16_t, signed or unsigned.
 1573  * Two cases:
 1574  *     a variable:  point arg1 at it.
 1575  *     a constant:  pass it in arg2.
 1576  */
 1577 
 1578 int
 1579 sysctl_handle_16(SYSCTL_HANDLER_ARGS)
 1580 {
 1581         int16_t tmpout;
 1582         int error = 0;
 1583 
 1584         /*
 1585          * Attempt to get a coherent snapshot by making a copy of the data.
 1586          */
 1587         if (arg1)
 1588                 tmpout = *(int16_t *)arg1;
 1589         else
 1590                 tmpout = arg2;
 1591         error = SYSCTL_OUT(req, &tmpout, sizeof(tmpout));
 1592 
 1593         if (error || !req->newptr)
 1594                 return (error);
 1595 
 1596         if (!arg1)
 1597                 error = EPERM;
 1598         else
 1599                 error = SYSCTL_IN(req, arg1, sizeof(tmpout));
 1600         return (error);
 1601 }
 1602 
 1603 /*
 1604  * Handle an int32_t, signed or unsigned.
 1605  * Two cases:
 1606  *     a variable:  point arg1 at it.
 1607  *     a constant:  pass it in arg2.
 1608  */
 1609 
 1610 int
 1611 sysctl_handle_32(SYSCTL_HANDLER_ARGS)
 1612 {
 1613         int32_t tmpout;
 1614         int error = 0;
 1615 
 1616         /*
 1617          * Attempt to get a coherent snapshot by making a copy of the data.
 1618          */
 1619         if (arg1)
 1620                 tmpout = *(int32_t *)arg1;
 1621         else
 1622                 tmpout = arg2;
 1623         error = SYSCTL_OUT(req, &tmpout, sizeof(tmpout));
 1624 
 1625         if (error || !req->newptr)
 1626                 return (error);
 1627 
 1628         if (!arg1)
 1629                 error = EPERM;
 1630         else
 1631                 error = SYSCTL_IN(req, arg1, sizeof(tmpout));
 1632         return (error);
 1633 }
 1634 
 1635 /*
 1636  * Handle an int, signed or unsigned.
 1637  * Two cases:
 1638  *     a variable:  point arg1 at it.
 1639  *     a constant:  pass it in arg2.
 1640  */
 1641 
 1642 int
 1643 sysctl_handle_int(SYSCTL_HANDLER_ARGS)
 1644 {
 1645         int tmpout, error = 0;
 1646 
 1647         /*
 1648          * Attempt to get a coherent snapshot by making a copy of the data.
 1649          */
 1650         if (arg1)
 1651                 tmpout = *(int *)arg1;
 1652         else
 1653                 tmpout = arg2;
 1654         error = SYSCTL_OUT(req, &tmpout, sizeof(int));
 1655 
 1656         if (error || !req->newptr)
 1657                 return (error);
 1658 
 1659         if (!arg1)
 1660                 error = EPERM;
 1661         else
 1662                 error = SYSCTL_IN(req, arg1, sizeof(int));
 1663         return (error);
 1664 }
 1665 
 1666 /*
 1667  * Based on on sysctl_handle_int() convert milliseconds into ticks.
 1668  * Note: this is used by TCP.
 1669  */
 1670 
 1671 int
 1672 sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS)
 1673 {
 1674         int error, s, tt;
 1675 
 1676         tt = *(int *)arg1;
 1677         s = (int)((int64_t)tt * 1000 / hz);
 1678 
 1679         error = sysctl_handle_int(oidp, &s, 0, req);
 1680         if (error || !req->newptr)
 1681                 return (error);
 1682 
 1683         tt = (int)((int64_t)s * hz / 1000);
 1684         if (tt < 1)
 1685                 return (EINVAL);
 1686 
 1687         *(int *)arg1 = tt;
 1688         return (0);
 1689 }
 1690 
 1691 /*
 1692  * Handle a long, signed or unsigned.
 1693  * Two cases:
 1694  *     a variable:  point arg1 at it.
 1695  *     a constant:  pass it in arg2.
 1696  */
 1697 
 1698 int
 1699 sysctl_handle_long(SYSCTL_HANDLER_ARGS)
 1700 {
 1701         int error = 0;
 1702         long tmplong;
 1703 #ifdef SCTL_MASK32
 1704         int tmpint;
 1705 #endif
 1706 
 1707         /*
 1708          * Attempt to get a coherent snapshot by making a copy of the data.
 1709          */
 1710         if (arg1)
 1711                 tmplong = *(long *)arg1;
 1712         else
 1713                 tmplong = arg2;
 1714 #ifdef SCTL_MASK32
 1715         if (req->flags & SCTL_MASK32) {
 1716                 tmpint = tmplong;
 1717                 error = SYSCTL_OUT(req, &tmpint, sizeof(int));
 1718         } else
 1719 #endif
 1720                 error = SYSCTL_OUT(req, &tmplong, sizeof(long));
 1721 
 1722         if (error || !req->newptr)
 1723                 return (error);
 1724 
 1725         if (!arg1)
 1726                 error = EPERM;
 1727 #ifdef SCTL_MASK32
 1728         else if (req->flags & SCTL_MASK32) {
 1729                 error = SYSCTL_IN(req, &tmpint, sizeof(int));
 1730                 *(long *)arg1 = (long)tmpint;
 1731         }
 1732 #endif
 1733         else
 1734                 error = SYSCTL_IN(req, arg1, sizeof(long));
 1735         return (error);
 1736 }
 1737 
 1738 /*
 1739  * Handle a 64 bit int, signed or unsigned.
 1740  * Two cases:
 1741  *     a variable:  point arg1 at it.
 1742  *     a constant:  pass it in arg2.
 1743  */
 1744 int
 1745 sysctl_handle_64(SYSCTL_HANDLER_ARGS)
 1746 {
 1747         int error = 0;
 1748         uint64_t tmpout;
 1749 
 1750         /*
 1751          * Attempt to get a coherent snapshot by making a copy of the data.
 1752          */
 1753         if (arg1)
 1754                 tmpout = *(uint64_t *)arg1;
 1755         else
 1756                 tmpout = arg2;
 1757         error = SYSCTL_OUT(req, &tmpout, sizeof(uint64_t));
 1758 
 1759         if (error || !req->newptr)
 1760                 return (error);
 1761 
 1762         if (!arg1)
 1763                 error = EPERM;
 1764         else
 1765                 error = SYSCTL_IN(req, arg1, sizeof(uint64_t));
 1766         return (error);
 1767 }
 1768 
 1769 /*
 1770  * Handle our generic '\0' terminated 'C' string.
 1771  * Two cases:
 1772  *      a variable string:  point arg1 at it, arg2 is max length.
 1773  *      a constant string:  point arg1 at it, arg2 is zero.
 1774  */
 1775 
 1776 int
 1777 sysctl_handle_string(SYSCTL_HANDLER_ARGS)
 1778 {
 1779         char *tmparg;
 1780         size_t outlen;
 1781         int error = 0, ro_string = 0;
 1782 
 1783         /*
 1784          * If the sysctl isn't writable and isn't a preallocated tunable that
 1785          * can be modified by kenv(2), microoptimise and treat it as a
 1786          * read-only string.
 1787          * A zero-length buffer indicates a fixed size read-only
 1788          * string.  In ddb, don't worry about trying to make a malloced
 1789          * snapshot.
 1790          */
 1791         if ((oidp->oid_kind & (CTLFLAG_WR | CTLFLAG_TUN)) == 0 ||
 1792             arg2 == 0 || kdb_active) {
 1793                 arg2 = strlen((char *)arg1) + 1;
 1794                 ro_string = 1;
 1795         }
 1796 
 1797         if (req->oldptr != NULL) {
 1798                 if (ro_string) {
 1799                         tmparg = arg1;
 1800                         outlen = strlen(tmparg) + 1;
 1801                 } else {
 1802                         tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK);
 1803                         sx_slock(&sysctlstringlock);
 1804                         memcpy(tmparg, arg1, arg2);
 1805                         sx_sunlock(&sysctlstringlock);
 1806                         outlen = strlen(tmparg) + 1;
 1807                 }
 1808 
 1809                 error = SYSCTL_OUT(req, tmparg, outlen);
 1810 
 1811                 if (!ro_string)
 1812                         free(tmparg, M_SYSCTLTMP);
 1813         } else {
 1814                 if (!ro_string)
 1815                         sx_slock(&sysctlstringlock);
 1816                 outlen = strlen((char *)arg1) + 1;
 1817                 if (!ro_string)
 1818                         sx_sunlock(&sysctlstringlock);
 1819                 error = SYSCTL_OUT(req, NULL, outlen);
 1820         }
 1821         if (error || !req->newptr)
 1822                 return (error);
 1823 
 1824         if (req->newlen - req->newidx >= arg2 ||
 1825             req->newlen - req->newidx < 0) {
 1826                 error = EINVAL;
 1827         } else if (req->newlen - req->newidx == 0) {
 1828                 sx_xlock(&sysctlstringlock);
 1829                 ((char *)arg1)[0] = '\0';
 1830                 sx_xunlock(&sysctlstringlock);
 1831         } else if (req->newfunc == sysctl_new_kernel) {
 1832                 arg2 = req->newlen - req->newidx;
 1833                 sx_xlock(&sysctlstringlock);
 1834                 error = SYSCTL_IN(req, arg1, arg2);
 1835                 if (error == 0) {
 1836                         ((char *)arg1)[arg2] = '\0';
 1837                         req->newidx += arg2;
 1838                 }
 1839                 sx_xunlock(&sysctlstringlock);
 1840         } else {
 1841                 arg2 = req->newlen - req->newidx;
 1842                 tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK);
 1843 
 1844                 error = SYSCTL_IN(req, tmparg, arg2);
 1845                 if (error) {
 1846                         free(tmparg, M_SYSCTLTMP);
 1847                         return (error);
 1848                 }
 1849 
 1850                 sx_xlock(&sysctlstringlock);
 1851                 memcpy(arg1, tmparg, arg2);
 1852                 ((char *)arg1)[arg2] = '\0';
 1853                 sx_xunlock(&sysctlstringlock);
 1854                 free(tmparg, M_SYSCTLTMP);
 1855                 req->newidx += arg2;
 1856         }
 1857         return (error);
 1858 }
 1859 
 1860 /*
 1861  * Handle any kind of opaque data.
 1862  * arg1 points to it, arg2 is the size.
 1863  */
 1864 
 1865 int
 1866 sysctl_handle_opaque(SYSCTL_HANDLER_ARGS)
 1867 {
 1868         int error, tries;
 1869         u_int generation;
 1870         struct sysctl_req req2;
 1871 
 1872         /*
 1873          * Attempt to get a coherent snapshot, by using the thread
 1874          * pre-emption counter updated from within mi_switch() to
 1875          * determine if we were pre-empted during a bcopy() or
 1876          * copyout(). Make 3 attempts at doing this before giving up.
 1877          * If we encounter an error, stop immediately.
 1878          */
 1879         tries = 0;
 1880         req2 = *req;
 1881 retry:
 1882         generation = curthread->td_generation;
 1883         error = SYSCTL_OUT(req, arg1, arg2);
 1884         if (error)
 1885                 return (error);
 1886         tries++;
 1887         if (generation != curthread->td_generation && tries < 3) {
 1888                 *req = req2;
 1889                 goto retry;
 1890         }
 1891 
 1892         error = SYSCTL_IN(req, arg1, arg2);
 1893 
 1894         return (error);
 1895 }
 1896 
 1897 /*
 1898  * Based on on sysctl_handle_int() convert microseconds to a sbintime.
 1899  */
 1900 int
 1901 sysctl_usec_to_sbintime(SYSCTL_HANDLER_ARGS)
 1902 {
 1903         int error;
 1904         int64_t tt;
 1905         sbintime_t sb;
 1906 
 1907         tt = *(int64_t *)arg1;
 1908         sb = sbttous(tt);
 1909 
 1910         error = sysctl_handle_64(oidp, &sb, 0, req);
 1911         if (error || !req->newptr)
 1912                 return (error);
 1913 
 1914         tt = ustosbt(sb);
 1915         *(int64_t *)arg1 = tt;
 1916 
 1917         return (0);
 1918 }
 1919 
 1920 /*
 1921  * Based on on sysctl_handle_int() convert milliseconds to a sbintime.
 1922  */
 1923 int
 1924 sysctl_msec_to_sbintime(SYSCTL_HANDLER_ARGS)
 1925 {
 1926         int error;
 1927         int64_t tt;
 1928         sbintime_t sb;
 1929 
 1930         tt = *(int64_t *)arg1;
 1931         sb = sbttoms(tt);
 1932 
 1933         error = sysctl_handle_64(oidp, &sb, 0, req);
 1934         if (error || !req->newptr)
 1935                 return (error);
 1936 
 1937         tt = mstosbt(sb);
 1938         *(int64_t *)arg1 = tt;
 1939 
 1940         return (0);
 1941 }
 1942 
 1943 /*
 1944  * Convert seconds to a struct timeval.  Intended for use with
 1945  * intervals and thus does not permit negative seconds.
 1946  */
 1947 int
 1948 sysctl_sec_to_timeval(SYSCTL_HANDLER_ARGS)
 1949 {
 1950         struct timeval *tv;
 1951         int error, secs;
 1952 
 1953         tv = arg1;
 1954         secs = tv->tv_sec;
 1955 
 1956         error = sysctl_handle_int(oidp, &secs, 0, req);
 1957         if (error || req->newptr == NULL)
 1958                 return (error);
 1959 
 1960         if (secs < 0)
 1961                 return (EINVAL);
 1962         tv->tv_sec = secs;
 1963 
 1964         return (0);
 1965 }
 1966 
 1967 /*
 1968  * Transfer functions to/from kernel space.
 1969  * XXX: rather untested at this point
 1970  */
 1971 static int
 1972 sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l)
 1973 {
 1974         size_t i = 0;
 1975 
 1976         if (req->oldptr) {
 1977                 i = l;
 1978                 if (req->oldlen <= req->oldidx)
 1979                         i = 0;
 1980                 else
 1981                         if (i > req->oldlen - req->oldidx)
 1982                                 i = req->oldlen - req->oldidx;
 1983                 if (i > 0)
 1984                         bcopy(p, (char *)req->oldptr + req->oldidx, i);
 1985         }
 1986         req->oldidx += l;
 1987         if (req->oldptr && i != l)
 1988                 return (ENOMEM);
 1989         return (0);
 1990 }
 1991 
 1992 static int
 1993 sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l)
 1994 {
 1995         if (!req->newptr)
 1996                 return (0);
 1997         if (req->newlen - req->newidx < l)
 1998                 return (EINVAL);
 1999         bcopy((const char *)req->newptr + req->newidx, p, l);
 2000         req->newidx += l;
 2001         return (0);
 2002 }
 2003 
 2004 int
 2005 kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old,
 2006     size_t *oldlenp, void *new, size_t newlen, size_t *retval, int flags)
 2007 {
 2008         int error = 0;
 2009         struct sysctl_req req;
 2010 
 2011         bzero(&req, sizeof req);
 2012 
 2013         req.td = td;
 2014         req.flags = flags;
 2015 
 2016         if (oldlenp) {
 2017                 req.oldlen = *oldlenp;
 2018         }
 2019         req.validlen = req.oldlen;
 2020 
 2021         if (old) {
 2022                 req.oldptr= old;
 2023         }
 2024 
 2025         if (new != NULL) {
 2026                 req.newlen = newlen;
 2027                 req.newptr = new;
 2028         }
 2029 
 2030         req.oldfunc = sysctl_old_kernel;
 2031         req.newfunc = sysctl_new_kernel;
 2032         req.lock = REQ_UNWIRED;
 2033 
 2034         error = sysctl_root(0, name, namelen, &req);
 2035 
 2036         if (req.lock == REQ_WIRED && req.validlen > 0)
 2037                 vsunlock(req.oldptr, req.validlen);
 2038 
 2039         if (error && error != ENOMEM)
 2040                 return (error);
 2041 
 2042         if (retval) {
 2043                 if (req.oldptr && req.oldidx > req.validlen)
 2044                         *retval = req.validlen;
 2045                 else
 2046                         *retval = req.oldidx;
 2047         }
 2048         return (error);
 2049 }
 2050 
 2051 int
 2052 kernel_sysctlbyname(struct thread *td, char *name, void *old, size_t *oldlenp,
 2053     void *new, size_t newlen, size_t *retval, int flags)
 2054 {
 2055         int oid[CTL_MAXNAME];
 2056         size_t oidlen, plen;
 2057         int error;
 2058 
 2059         oid[0] = CTL_SYSCTL;
 2060         oid[1] = CTL_SYSCTL_NAME2OID;
 2061         oidlen = sizeof(oid);
 2062 
 2063         error = kernel_sysctl(td, oid, 2, oid, &oidlen,
 2064             (void *)name, strlen(name), &plen, flags);
 2065         if (error)
 2066                 return (error);
 2067 
 2068         error = kernel_sysctl(td, oid, plen / sizeof(int), old, oldlenp,
 2069             new, newlen, retval, flags);
 2070         return (error);
 2071 }
 2072 
 2073 /*
 2074  * Transfer function to/from user space.
 2075  */
 2076 static int
 2077 sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
 2078 {
 2079         size_t i, len, origidx;
 2080         int error;
 2081 
 2082         origidx = req->oldidx;
 2083         req->oldidx += l;
 2084         if (req->oldptr == NULL)
 2085                 return (0);
 2086         /*
 2087          * If we have not wired the user supplied buffer and we are currently
 2088          * holding locks, drop a witness warning, as it's possible that
 2089          * write operations to the user page can sleep.
 2090          */
 2091         if (req->lock != REQ_WIRED)
 2092                 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
 2093                     "sysctl_old_user()");
 2094         i = l;
 2095         len = req->validlen;
 2096         if (len <= origidx)
 2097                 i = 0;
 2098         else {
 2099                 if (i > len - origidx)
 2100                         i = len - origidx;
 2101                 if (req->lock == REQ_WIRED) {
 2102                         error = copyout_nofault(p, (char *)req->oldptr +
 2103                             origidx, i);
 2104                 } else
 2105                         error = copyout(p, (char *)req->oldptr + origidx, i);
 2106                 if (error != 0)
 2107                         return (error);
 2108         }
 2109         if (i < l)
 2110                 return (ENOMEM);
 2111         return (0);
 2112 }
 2113 
 2114 static int
 2115 sysctl_new_user(struct sysctl_req *req, void *p, size_t l)
 2116 {
 2117         int error;
 2118 
 2119         if (!req->newptr)
 2120                 return (0);
 2121         if (req->newlen - req->newidx < l)
 2122                 return (EINVAL);
 2123         WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
 2124             "sysctl_new_user()");
 2125         error = copyin((const char *)req->newptr + req->newidx, p, l);
 2126         req->newidx += l;
 2127         return (error);
 2128 }
 2129 
 2130 /*
 2131  * Wire the user space destination buffer.  If set to a value greater than
 2132  * zero, the len parameter limits the maximum amount of wired memory.
 2133  */
 2134 int
 2135 sysctl_wire_old_buffer(struct sysctl_req *req, size_t len)
 2136 {
 2137         int ret;
 2138         size_t wiredlen;
 2139 
 2140         wiredlen = (len > 0 && len < req->oldlen) ? len : req->oldlen;
 2141         ret = 0;
 2142         if (req->lock != REQ_WIRED && req->oldptr &&
 2143             req->oldfunc == sysctl_old_user) {
 2144                 if (wiredlen != 0) {
 2145                         ret = vslock(req->oldptr, wiredlen);
 2146                         if (ret != 0) {
 2147                                 if (ret != ENOMEM)
 2148                                         return (ret);
 2149                                 wiredlen = 0;
 2150                         }
 2151                 }
 2152                 req->lock = REQ_WIRED;
 2153                 req->validlen = wiredlen;
 2154         }
 2155         return (0);
 2156 }
 2157 
 2158 int
 2159 sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid,
 2160     int *nindx, struct sysctl_req *req)
 2161 {
 2162         struct sysctl_oid_list *lsp;
 2163         struct sysctl_oid *oid;
 2164         int indx;
 2165 
 2166         SYSCTL_ASSERT_LOCKED();
 2167         lsp = &sysctl__children;
 2168         indx = 0;
 2169         while (indx < CTL_MAXNAME) {
 2170                 SLIST_FOREACH(oid, lsp, oid_link) {
 2171                         if (oid->oid_number == name[indx])
 2172                                 break;
 2173                 }
 2174                 if (oid == NULL)
 2175                         return (ENOENT);
 2176 
 2177                 indx++;
 2178                 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
 2179                         if (oid->oid_handler != NULL || indx == namelen) {
 2180                                 *noid = oid;
 2181                                 if (nindx != NULL)
 2182                                         *nindx = indx;
 2183                                 KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0,
 2184                                     ("%s found DYING node %p", __func__, oid));
 2185                                 return (0);
 2186                         }
 2187                         lsp = SYSCTL_CHILDREN(oid);
 2188                 } else if (indx == namelen) {
 2189                         if ((oid->oid_kind & CTLFLAG_DORMANT) != 0)
 2190                                 return (ENOENT);
 2191                         *noid = oid;
 2192                         if (nindx != NULL)
 2193                                 *nindx = indx;
 2194                         KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0,
 2195                             ("%s found DYING node %p", __func__, oid));
 2196                         return (0);
 2197                 } else {
 2198                         return (ENOTDIR);
 2199                 }
 2200         }
 2201         return (ENOENT);
 2202 }
 2203 
 2204 /*
 2205  * Traverse our tree, and find the right node, execute whatever it points
 2206  * to, and return the resulting error code.
 2207  */
 2208 
 2209 static int
 2210 sysctl_root(SYSCTL_HANDLER_ARGS)
 2211 {
 2212         struct sysctl_oid *oid;
 2213         struct rm_priotracker tracker;
 2214         int error, indx, lvl;
 2215 
 2216         SYSCTL_RLOCK(&tracker);
 2217 
 2218         error = sysctl_find_oid(arg1, arg2, &oid, &indx, req);
 2219         if (error)
 2220                 goto out;
 2221 
 2222         if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
 2223                 /*
 2224                  * You can't call a sysctl when it's a node, but has
 2225                  * no handler.  Inform the user that it's a node.
 2226                  * The indx may or may not be the same as namelen.
 2227                  */
 2228                 if (oid->oid_handler == NULL) {
 2229                         error = EISDIR;
 2230                         goto out;
 2231                 }
 2232         }
 2233 
 2234         /* Is this sysctl writable? */
 2235         if (req->newptr && !(oid->oid_kind & CTLFLAG_WR)) {
 2236                 error = EPERM;
 2237                 goto out;
 2238         }
 2239 
 2240         KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL"));
 2241 
 2242 #ifdef CAPABILITY_MODE
 2243         /*
 2244          * If the process is in capability mode, then don't permit reading or
 2245          * writing unless specifically granted for the node.
 2246          */
 2247         if (IN_CAPABILITY_MODE(req->td)) {
 2248                 if ((req->oldptr && !(oid->oid_kind & CTLFLAG_CAPRD)) ||
 2249                     (req->newptr && !(oid->oid_kind & CTLFLAG_CAPWR))) {
 2250                         error = EPERM;
 2251                         goto out;
 2252                 }
 2253         }
 2254 #endif
 2255 
 2256         /* Is this sysctl sensitive to securelevels? */
 2257         if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) {
 2258                 lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE;
 2259                 error = securelevel_gt(req->td->td_ucred, lvl);
 2260                 if (error)
 2261                         goto out;
 2262         }
 2263 
 2264         /* Is this sysctl writable by only privileged users? */
 2265         if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) {
 2266                 int priv;
 2267 
 2268                 if (oid->oid_kind & CTLFLAG_PRISON)
 2269                         priv = PRIV_SYSCTL_WRITEJAIL;
 2270 #ifdef VIMAGE
 2271                 else if ((oid->oid_kind & CTLFLAG_VNET) &&
 2272                      prison_owns_vnet(req->td->td_ucred))
 2273                         priv = PRIV_SYSCTL_WRITEJAIL;
 2274 #endif
 2275                 else
 2276                         priv = PRIV_SYSCTL_WRITE;
 2277                 error = priv_check(req->td, priv);
 2278                 if (error)
 2279                         goto out;
 2280         }
 2281 
 2282         if (!oid->oid_handler) {
 2283                 error = EINVAL;
 2284                 goto out;
 2285         }
 2286 
 2287         if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
 2288                 arg1 = (int *)arg1 + indx;
 2289                 arg2 -= indx;
 2290         } else {
 2291                 arg1 = oid->oid_arg1;
 2292                 arg2 = oid->oid_arg2;
 2293         }
 2294 #ifdef MAC
 2295         error = mac_system_check_sysctl(req->td->td_ucred, oid, arg1, arg2,
 2296             req);
 2297         if (error != 0)
 2298                 goto out;
 2299 #endif
 2300 #ifdef VIMAGE
 2301         if ((oid->oid_kind & CTLFLAG_VNET) && arg1 != NULL)
 2302                 arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1);
 2303 #endif
 2304         error = sysctl_root_handler_locked(oid, arg1, arg2, req, &tracker);
 2305 
 2306 out:
 2307         SYSCTL_RUNLOCK(&tracker);
 2308         return (error);
 2309 }
 2310 
 2311 #ifndef _SYS_SYSPROTO_H_
 2312 struct sysctl_args {
 2313         int     *name;
 2314         u_int   namelen;
 2315         void    *old;
 2316         size_t  *oldlenp;
 2317         void    *new;
 2318         size_t  newlen;
 2319 };
 2320 #endif
 2321 int
 2322 sys___sysctl(struct thread *td, struct sysctl_args *uap)
 2323 {
 2324         int error, i, name[CTL_MAXNAME];
 2325         size_t j;
 2326 
 2327         if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
 2328                 return (EINVAL);
 2329 
 2330         error = copyin(uap->name, &name, uap->namelen * sizeof(int));
 2331         if (error)
 2332                 return (error);
 2333 
 2334         error = userland_sysctl(td, name, uap->namelen,
 2335                 uap->old, uap->oldlenp, 0,
 2336                 uap->new, uap->newlen, &j, 0);
 2337         if (error && error != ENOMEM)
 2338                 return (error);
 2339         if (uap->oldlenp) {
 2340                 i = copyout(&j, uap->oldlenp, sizeof(j));
 2341                 if (i)
 2342                         return (i);
 2343         }
 2344         return (error);
 2345 }
 2346 
 2347 int
 2348 kern___sysctlbyname(struct thread *td, const char *oname, size_t namelen,
 2349     void *old, size_t *oldlenp, void *new, size_t newlen, size_t *retval,
 2350     int flags, bool inkernel)
 2351 {
 2352         int oid[CTL_MAXNAME];
 2353         char namebuf[16];
 2354         char *name;
 2355         size_t oidlen;
 2356         int error;
 2357 
 2358         if (namelen > MAXPATHLEN || namelen == 0)
 2359                 return (EINVAL);
 2360         name = namebuf;
 2361         if (namelen > sizeof(namebuf))
 2362                 name = malloc(namelen, M_SYSCTL, M_WAITOK);
 2363         error = copyin(oname, name, namelen);
 2364         if (error != 0)
 2365                 goto out;
 2366 
 2367         oid[0] = CTL_SYSCTL;
 2368         oid[1] = CTL_SYSCTL_NAME2OID;
 2369         oidlen = sizeof(oid);
 2370         error = kernel_sysctl(td, oid, 2, oid, &oidlen, (void *)name, namelen,
 2371             retval, flags);
 2372         if (error != 0)
 2373                 goto out;
 2374         error = userland_sysctl(td, oid, *retval / sizeof(int), old, oldlenp,
 2375             inkernel, new, newlen, retval, flags);
 2376 
 2377 out:
 2378         if (namelen > sizeof(namebuf))
 2379                 free(name, M_SYSCTL);
 2380         return (error);
 2381 }
 2382 
 2383 #ifndef _SYS_SYSPROTO_H_
 2384 struct __sysctlbyname_args {
 2385         const char      *name;
 2386         size_t  namelen;
 2387         void    *old;
 2388         size_t  *oldlenp;
 2389         void    *new;
 2390         size_t  newlen;
 2391 };
 2392 #endif
 2393 int
 2394 sys___sysctlbyname(struct thread *td, struct __sysctlbyname_args *uap)
 2395 {
 2396         size_t rv;
 2397         int error;
 2398 
 2399         error = kern___sysctlbyname(td, uap->name, uap->namelen, uap->old,
 2400             uap->oldlenp, uap->new, uap->newlen, &rv, 0, 0);
 2401         if (error != 0)
 2402                 return (error);
 2403         if (uap->oldlenp != NULL)
 2404                 error = copyout(&rv, uap->oldlenp, sizeof(rv));
 2405 
 2406         return (error);
 2407 }
 2408 
 2409 /*
 2410  * This is used from various compatibility syscalls too.  That's why name
 2411  * must be in kernel space.
 2412  */
 2413 int
 2414 userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
 2415     size_t *oldlenp, int inkernel, const void *new, size_t newlen,
 2416     size_t *retval, int flags)
 2417 {
 2418         int error = 0, memlocked;
 2419         struct sysctl_req req;
 2420 
 2421         bzero(&req, sizeof req);
 2422 
 2423         req.td = td;
 2424         req.flags = flags;
 2425 
 2426         if (oldlenp) {
 2427                 if (inkernel) {
 2428                         req.oldlen = *oldlenp;
 2429                 } else {
 2430                         error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp));
 2431                         if (error)
 2432                                 return (error);
 2433                 }
 2434         }
 2435         req.validlen = req.oldlen;
 2436         req.oldptr = old;
 2437 
 2438         if (new != NULL) {
 2439                 req.newlen = newlen;
 2440                 req.newptr = new;
 2441         }
 2442 
 2443         req.oldfunc = sysctl_old_user;
 2444         req.newfunc = sysctl_new_user;
 2445         req.lock = REQ_UNWIRED;
 2446 
 2447 #ifdef KTRACE
 2448         if (KTRPOINT(curthread, KTR_SYSCTL))
 2449                 ktrsysctl(name, namelen);
 2450 #endif
 2451         memlocked = 0;
 2452         if (req.oldptr && req.oldlen > 4 * PAGE_SIZE) {
 2453                 memlocked = 1;
 2454                 sx_xlock(&sysctlmemlock);
 2455         }
 2456         CURVNET_SET(TD_TO_VNET(td));
 2457 
 2458         for (;;) {
 2459                 req.oldidx = 0;
 2460                 req.newidx = 0;
 2461                 error = sysctl_root(0, name, namelen, &req);
 2462                 if (error != EAGAIN)
 2463                         break;
 2464                 kern_yield(PRI_USER);
 2465         }
 2466 
 2467         CURVNET_RESTORE();
 2468 
 2469         if (req.lock == REQ_WIRED && req.validlen > 0)
 2470                 vsunlock(req.oldptr, req.validlen);
 2471         if (memlocked)
 2472                 sx_xunlock(&sysctlmemlock);
 2473 
 2474         if (error && error != ENOMEM)
 2475                 return (error);
 2476 
 2477         if (retval) {
 2478                 if (req.oldptr && req.oldidx > req.validlen)
 2479                         *retval = req.validlen;
 2480                 else
 2481                         *retval = req.oldidx;
 2482         }
 2483         return (error);
 2484 }
 2485 
 2486 /*
 2487  * Drain into a sysctl struct.  The user buffer should be wired if a page
 2488  * fault would cause issue.
 2489  */
 2490 static int
 2491 sbuf_sysctl_drain(void *arg, const char *data, int len)
 2492 {
 2493         struct sysctl_req *req = arg;
 2494         int error;
 2495 
 2496         error = SYSCTL_OUT(req, data, len);
 2497         KASSERT(error >= 0, ("Got unexpected negative value %d", error));
 2498         return (error == 0 ? len : -error);
 2499 }
 2500 
 2501 struct sbuf *
 2502 sbuf_new_for_sysctl(struct sbuf *s, char *buf, int length,
 2503     struct sysctl_req *req)
 2504 {
 2505 
 2506         /* Supply a default buffer size if none given. */
 2507         if (buf == NULL && length == 0)
 2508                 length = 64;
 2509         s = sbuf_new(s, buf, length, SBUF_FIXEDLEN | SBUF_INCLUDENUL);
 2510         sbuf_set_drain(s, sbuf_sysctl_drain, req);
 2511         return (s);
 2512 }
 2513 
 2514 #ifdef DDB
 2515 
 2516 /* The current OID the debugger is working with */
 2517 static struct sysctl_oid *g_ddb_oid;
 2518 
 2519 /* The current flags specified by the user */
 2520 static int g_ddb_sysctl_flags;
 2521 
 2522 /* Check to see if the last sysctl printed */
 2523 static int g_ddb_sysctl_printed;
 2524 
 2525 static const int ctl_sign[CTLTYPE+1] = {
 2526         [CTLTYPE_INT] = 1,
 2527         [CTLTYPE_LONG] = 1,
 2528         [CTLTYPE_S8] = 1,
 2529         [CTLTYPE_S16] = 1,
 2530         [CTLTYPE_S32] = 1,
 2531         [CTLTYPE_S64] = 1,
 2532 };
 2533 
 2534 static const int ctl_size[CTLTYPE+1] = {
 2535         [CTLTYPE_INT] = sizeof(int),
 2536         [CTLTYPE_UINT] = sizeof(u_int),
 2537         [CTLTYPE_LONG] = sizeof(long),
 2538         [CTLTYPE_ULONG] = sizeof(u_long),
 2539         [CTLTYPE_S8] = sizeof(int8_t),
 2540         [CTLTYPE_S16] = sizeof(int16_t),
 2541         [CTLTYPE_S32] = sizeof(int32_t),
 2542         [CTLTYPE_S64] = sizeof(int64_t),
 2543         [CTLTYPE_U8] = sizeof(uint8_t),
 2544         [CTLTYPE_U16] = sizeof(uint16_t),
 2545         [CTLTYPE_U32] = sizeof(uint32_t),
 2546         [CTLTYPE_U64] = sizeof(uint64_t),
 2547 };
 2548 
 2549 #define DB_SYSCTL_NAME_ONLY     0x001   /* Compare with -N */
 2550 #define DB_SYSCTL_VALUE_ONLY    0x002   /* Compare with -n */
 2551 #define DB_SYSCTL_OPAQUE        0x004   /* Compare with -o */
 2552 #define DB_SYSCTL_HEX           0x008   /* Compare with -x */
 2553 
 2554 #define DB_SYSCTL_SAFE_ONLY     0x100   /* Only simple types */
 2555 
 2556 static const char db_sysctl_modifs[] = {
 2557         'N', 'n', 'o', 'x',
 2558 };
 2559 
 2560 static const int db_sysctl_modif_values[] = {
 2561         DB_SYSCTL_NAME_ONLY, DB_SYSCTL_VALUE_ONLY,
 2562         DB_SYSCTL_OPAQUE, DB_SYSCTL_HEX,
 2563 };
 2564 
 2565 /* Handlers considered safe to print while recursing */
 2566 static int (* const db_safe_handlers[])(SYSCTL_HANDLER_ARGS) = {
 2567         sysctl_handle_bool,
 2568         sysctl_handle_8,
 2569         sysctl_handle_16,
 2570         sysctl_handle_32,
 2571         sysctl_handle_64,
 2572         sysctl_handle_int,
 2573         sysctl_handle_long,
 2574         sysctl_handle_string,
 2575         sysctl_handle_opaque,
 2576 };
 2577 
 2578 /*
 2579  * Use in place of sysctl_old_kernel to print sysctl values.
 2580  *
 2581  * Compare to the output handling in show_var from sbin/sysctl/sysctl.c
 2582  */
 2583 static int
 2584 sysctl_old_ddb(struct sysctl_req *req, const void *ptr, size_t len)
 2585 {
 2586         const u_char *val, *p;
 2587         const char *sep1;
 2588         size_t intlen, slen;
 2589         uintmax_t umv;
 2590         intmax_t mv;
 2591         int sign, ctltype, hexlen, xflag, error;
 2592 
 2593         /* Suppress false-positive GCC uninitialized variable warnings */
 2594         mv = 0;
 2595         umv = 0;
 2596 
 2597         slen = len;
 2598         val = p = ptr;
 2599 
 2600         if (ptr == NULL) {
 2601                 error = 0;
 2602                 goto out;
 2603         }
 2604 
 2605         /* We are going to print */
 2606         g_ddb_sysctl_printed = 1;
 2607 
 2608         xflag = g_ddb_sysctl_flags & DB_SYSCTL_HEX;
 2609 
 2610         ctltype = (g_ddb_oid->oid_kind & CTLTYPE);
 2611         sign = ctl_sign[ctltype];
 2612         intlen = ctl_size[ctltype];
 2613 
 2614         switch (ctltype) {
 2615         case CTLTYPE_NODE:
 2616         case CTLTYPE_STRING:
 2617                 db_printf("%.*s", (int) len, (const char *) p);
 2618                 error = 0;
 2619                 goto out;
 2620 
 2621         case CTLTYPE_INT:
 2622         case CTLTYPE_UINT:
 2623         case CTLTYPE_LONG:
 2624         case CTLTYPE_ULONG:
 2625         case CTLTYPE_S8:
 2626         case CTLTYPE_S16:
 2627         case CTLTYPE_S32:
 2628         case CTLTYPE_S64:
 2629         case CTLTYPE_U8:
 2630         case CTLTYPE_U16:
 2631         case CTLTYPE_U32:
 2632         case CTLTYPE_U64:
 2633                 hexlen = 2 + (intlen * CHAR_BIT + 3) / 4;
 2634                 sep1 = "";
 2635                 while (len >= intlen) {
 2636                         switch (ctltype) {
 2637                         case CTLTYPE_INT:
 2638                         case CTLTYPE_UINT:
 2639                                 umv = *(const u_int *)p;
 2640                                 mv = *(const int *)p;
 2641                                 break;
 2642                         case CTLTYPE_LONG:
 2643                         case CTLTYPE_ULONG:
 2644                                 umv = *(const u_long *)p;
 2645                                 mv = *(const long *)p;
 2646                                 break;
 2647                         case CTLTYPE_S8:
 2648                         case CTLTYPE_U8:
 2649                                 umv = *(const uint8_t *)p;
 2650                                 mv = *(const int8_t *)p;
 2651                                 break;
 2652                         case CTLTYPE_S16:
 2653                         case CTLTYPE_U16:
 2654                                 umv = *(const uint16_t *)p;
 2655                                 mv = *(const int16_t *)p;
 2656                                 break;
 2657                         case CTLTYPE_S32:
 2658                         case CTLTYPE_U32:
 2659                                 umv = *(const uint32_t *)p;
 2660                                 mv = *(const int32_t *)p;
 2661                                 break;
 2662                         case CTLTYPE_S64:
 2663                         case CTLTYPE_U64:
 2664                                 umv = *(const uint64_t *)p;
 2665                                 mv = *(const int64_t *)p;
 2666                                 break;
 2667                         }
 2668 
 2669                         db_printf("%s", sep1);
 2670                         if (xflag)
 2671                                 db_printf("%#0*jx", hexlen, umv);
 2672                         else if (!sign)
 2673                                 db_printf("%ju", umv);
 2674                         else if (g_ddb_oid->oid_fmt[1] == 'K') {
 2675                                 /* Kelvins are currently unsupported. */
 2676                                 error = EOPNOTSUPP;
 2677                                 goto out;
 2678                         } else
 2679                                 db_printf("%jd", mv);
 2680 
 2681                         sep1 = " ";
 2682                         len -= intlen;
 2683                         p += intlen;
 2684                 }
 2685                 error = 0;
 2686                 goto out;
 2687 
 2688         case CTLTYPE_OPAQUE:
 2689                 /* TODO: Support struct functions. */
 2690 
 2691                 /* FALLTHROUGH */
 2692         default:
 2693                 db_printf("Format:%s Length:%zu Dump:0x",
 2694                     g_ddb_oid->oid_fmt, len);
 2695                 while (len-- && (xflag || p < val + 16))
 2696                         db_printf("%02x", *p++);
 2697                 if (!xflag && len > 16)
 2698                         db_printf("...");
 2699                 error = 0;
 2700                 goto out;
 2701         }
 2702 
 2703 out:
 2704         req->oldidx += slen;
 2705         return (error);
 2706 }
 2707 
 2708 /*
 2709  * Avoid setting new sysctl values from the debugger
 2710  */
 2711 static int
 2712 sysctl_new_ddb(struct sysctl_req *req, void *p, size_t l)
 2713 {
 2714 
 2715         if (!req->newptr)
 2716                 return (0);
 2717 
 2718         /* Changing sysctls from the debugger is currently unsupported */
 2719         return (EPERM);
 2720 }
 2721 
 2722 /*
 2723  * Run a sysctl handler with the DDB oldfunc and newfunc attached.
 2724  * Instead of copying any output to a buffer we'll dump it right to
 2725  * the console.
 2726  */
 2727 static int
 2728 db_sysctl(struct sysctl_oid *oidp, int *name, u_int namelen,
 2729     void *old, size_t *oldlenp, size_t *retval, int flags)
 2730 {
 2731         struct sysctl_req req;
 2732         int error;
 2733 
 2734         /* Setup the request */
 2735         bzero(&req, sizeof req);
 2736         req.td = kdb_thread;
 2737         req.oldfunc = sysctl_old_ddb;
 2738         req.newfunc = sysctl_new_ddb;
 2739         req.lock = REQ_UNWIRED;
 2740         if (oldlenp) {
 2741                 req.oldlen = *oldlenp;
 2742         }
 2743         req.validlen = req.oldlen;
 2744         if (old) {
 2745                 req.oldptr = old;
 2746         }
 2747 
 2748         /* Setup our globals for sysctl_old_ddb */
 2749         g_ddb_oid = oidp;
 2750         g_ddb_sysctl_flags = flags;
 2751         g_ddb_sysctl_printed = 0;
 2752 
 2753         error = sysctl_root(0, name, namelen, &req);
 2754 
 2755         /* Reset globals */
 2756         g_ddb_oid = NULL;
 2757         g_ddb_sysctl_flags = 0;
 2758 
 2759         if (retval) {
 2760                 if (req.oldptr && req.oldidx > req.validlen)
 2761                         *retval = req.validlen;
 2762                 else
 2763                         *retval = req.oldidx;
 2764         }
 2765         return (error);
 2766 }
 2767 
 2768 /*
 2769  * Show a sysctl's name
 2770  */
 2771 static void
 2772 db_show_oid_name(int *oid, size_t nlen)
 2773 {
 2774         struct sysctl_oid *oidp;
 2775         int qoid[CTL_MAXNAME+2];
 2776         int error;
 2777 
 2778         qoid[0] = 0;
 2779         memcpy(qoid + 2, oid, nlen * sizeof(int));
 2780         qoid[1] = 1;
 2781 
 2782         error = sysctl_find_oid(qoid, nlen + 2, &oidp, NULL, NULL);
 2783         if (error)
 2784                 db_error("sysctl name oid");
 2785 
 2786         error = db_sysctl(oidp, qoid, nlen + 2, NULL, NULL, NULL, 0);
 2787         if (error)
 2788                 db_error("sysctl name");
 2789 }
 2790 
 2791 /*
 2792  * Check to see if an OID is safe to print from ddb.
 2793  */
 2794 static bool
 2795 db_oid_safe(const struct sysctl_oid *oidp)
 2796 {
 2797         for (unsigned int i = 0; i < nitems(db_safe_handlers); ++i) {
 2798                 if (oidp->oid_handler == db_safe_handlers[i])
 2799                         return (true);
 2800         }
 2801 
 2802         return (false);
 2803 }
 2804 
 2805 /*
 2806  * Show a sysctl at a specific OID
 2807  * Compare to the input handling in show_var from sbin/sysctl/sysctl.c
 2808  */
 2809 static int
 2810 db_show_oid(struct sysctl_oid *oidp, int *oid, size_t nlen, int flags)
 2811 {
 2812         int error, xflag, oflag, Nflag, nflag;
 2813         size_t len;
 2814 
 2815         xflag = flags & DB_SYSCTL_HEX;
 2816         oflag = flags & DB_SYSCTL_OPAQUE;
 2817         nflag = flags & DB_SYSCTL_VALUE_ONLY;
 2818         Nflag = flags & DB_SYSCTL_NAME_ONLY;
 2819 
 2820         if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_OPAQUE &&
 2821             (!xflag && !oflag))
 2822                 return (0);
 2823 
 2824         if (Nflag) {
 2825                 db_show_oid_name(oid, nlen);
 2826                 error = 0;
 2827                 goto out;
 2828         }
 2829 
 2830         if (!nflag) {
 2831                 db_show_oid_name(oid, nlen);
 2832                 db_printf(": ");
 2833         }
 2834 
 2835         if ((flags & DB_SYSCTL_SAFE_ONLY) && !db_oid_safe(oidp)) {
 2836                 db_printf("Skipping, unsafe to print while recursing.");
 2837                 error = 0;
 2838                 goto out;
 2839         }
 2840 
 2841         /* Try once, and ask about the size */
 2842         len = 0;
 2843         error = db_sysctl(oidp, oid, nlen,
 2844             NULL, NULL, &len, flags);
 2845         if (error)
 2846                 goto out;
 2847 
 2848         if (!g_ddb_sysctl_printed)
 2849                 /* Lie about the size */
 2850                 error = db_sysctl(oidp, oid, nlen,
 2851                     (void *) 1, &len, NULL, flags);
 2852 
 2853 out:
 2854         db_printf("\n");
 2855         return (error);
 2856 }
 2857 
 2858 /*
 2859  * Show all sysctls under a specific OID
 2860  * Compare to sysctl_all from sbin/sysctl/sysctl.c
 2861  */
 2862 static int
 2863 db_show_sysctl_all(int *oid, size_t len, int flags)
 2864 {
 2865         struct sysctl_oid *oidp;
 2866         int name1[CTL_MAXNAME + 2], name2[CTL_MAXNAME + 2];
 2867         size_t l1, l2;
 2868 
 2869         name1[0] = CTL_SYSCTL;
 2870         name1[1] = CTL_SYSCTL_NEXT;
 2871         l1 = 2;
 2872         if (len) {
 2873                 memcpy(name1 + 2, oid, len * sizeof(int));
 2874                 l1 += len;
 2875         } else {
 2876                 name1[2] = CTL_KERN;
 2877                 l1++;
 2878         }
 2879         for (;;) {
 2880                 int i, error;
 2881 
 2882                 l2 = sizeof(name2);
 2883                 error = kernel_sysctl(kdb_thread, name1, l1,
 2884                     name2, &l2, NULL, 0, &l2, 0);
 2885                 if (error != 0) {
 2886                         if (error == ENOENT)
 2887                                 return (0);
 2888                         else
 2889                                 db_error("sysctl(next)");
 2890                 }
 2891 
 2892                 l2 /= sizeof(int);
 2893 
 2894                 if (l2 < (unsigned int)len)
 2895                         return (0);
 2896 
 2897                 for (i = 0; i < len; i++)
 2898                         if (name2[i] != oid[i])
 2899                                 return (0);
 2900 
 2901                 /* Find the OID in question */
 2902                 error = sysctl_find_oid(name2, l2, &oidp, NULL, NULL);
 2903                 if (error)
 2904                         return (error);
 2905 
 2906                 i = db_show_oid(oidp, name2, l2, flags | DB_SYSCTL_SAFE_ONLY);
 2907 
 2908                 if (db_pager_quit)
 2909                         return (0);
 2910 
 2911                 memcpy(name1+2, name2, l2 * sizeof(int));
 2912                 l1 = 2 + l2;
 2913         }
 2914 }
 2915 
 2916 /*
 2917  * Show a sysctl by its user facing string
 2918  */
 2919 static int
 2920 db_sysctlbyname(char *name, int flags)
 2921 {
 2922         struct sysctl_oid *oidp;
 2923         int oid[CTL_MAXNAME];
 2924         int error, nlen;
 2925 
 2926         error = name2oid(name, oid, &nlen, &oidp);
 2927         if (error) {
 2928                 return (error);
 2929         }
 2930 
 2931         if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
 2932                 db_show_sysctl_all(oid, nlen, flags);
 2933         } else {
 2934                 error = db_show_oid(oidp, oid, nlen, flags);
 2935         }
 2936 
 2937         return (error);
 2938 }
 2939 
 2940 static void
 2941 db_sysctl_cmd_usage(void)
 2942 {
 2943         db_printf(
 2944             " sysctl [/Nnox] <sysctl>                                       \n"
 2945             "                                                               \n"
 2946             " <sysctl> The name of the sysctl to show.                      \n"
 2947             "                                                               \n"
 2948             " Show a sysctl by hooking into SYSCTL_IN and SYSCTL_OUT.       \n"
 2949             " This will work for most sysctls, but should not be used       \n"
 2950             " with sysctls that are known to malloc.                        \n"
 2951             "                                                               \n"
 2952             " While recursing any \"unsafe\" sysctls will be skipped.       \n"
 2953             " Call sysctl directly on the sysctl to try printing the        \n"
 2954             " skipped sysctl. This is unsafe and may make the ddb           \n"
 2955             " session unusable.                                             \n"
 2956             "                                                               \n"
 2957             " Arguments:                                                    \n"
 2958             "   /N      Display only the name of the sysctl.                \n"
 2959             "   /n      Display only the value of the sysctl.               \n"
 2960             "   /o      Display opaque values.                              \n"
 2961             "   /x      Display the sysctl in hex.                          \n"
 2962             "                                                               \n"
 2963             "For example:                                                   \n"
 2964             "sysctl vm.v_free_min                                           \n"
 2965             "vn.v_free_min: 12669                                           \n"
 2966             );
 2967 }
 2968 
 2969 /*
 2970  * Show a specific sysctl similar to sysctl (8).
 2971  */
 2972 DB_COMMAND_FLAGS(sysctl, db_sysctl_cmd, CS_OWN)
 2973 {
 2974         char name[TOK_STRING_SIZE];
 2975         int error, i, t, flags;
 2976 
 2977         /* Parse the modifiers */
 2978         t = db_read_token();
 2979         if (t == tSLASH || t == tMINUS) {
 2980                 t = db_read_token();
 2981                 if (t != tIDENT) {
 2982                         db_printf("Bad modifier\n");
 2983                         error = EINVAL;
 2984                         goto out;
 2985                 }
 2986                 db_strcpy(modif, db_tok_string);
 2987         }
 2988         else {
 2989                 db_unread_token(t);
 2990                 modif[0] = '\0';
 2991         }
 2992 
 2993         flags = 0;
 2994         for (i = 0; i < nitems(db_sysctl_modifs); i++) {
 2995                 if (strchr(modif, db_sysctl_modifs[i])) {
 2996                         flags |= db_sysctl_modif_values[i];
 2997                 }
 2998         }
 2999 
 3000         /* Parse the sysctl names */
 3001         t = db_read_token();
 3002         if (t != tIDENT) {
 3003                 db_printf("Need sysctl name\n");
 3004                 error = EINVAL;
 3005                 goto out;
 3006         }
 3007 
 3008         /* Copy the name into a temporary buffer */
 3009         db_strcpy(name, db_tok_string);
 3010 
 3011         /* Ensure there is no trailing cruft */
 3012         t = db_read_token();
 3013         if (t != tEOL) {
 3014                 db_printf("Unexpected sysctl argument\n");
 3015                 error = EINVAL;
 3016                 goto out;
 3017         }
 3018 
 3019         error = db_sysctlbyname(name, flags);
 3020         if (error == ENOENT) {
 3021                 db_printf("unknown oid: '%s'\n", db_tok_string);
 3022                 goto out;
 3023         } else if (error) {
 3024                 db_printf("%s: error: %d\n", db_tok_string, error);
 3025                 goto out;
 3026         }
 3027 
 3028 out:
 3029         /* Ensure we eat all of our text */
 3030         db_flush_lex();
 3031 
 3032         if (error == EINVAL) {
 3033                 db_sysctl_cmd_usage();
 3034         }
 3035 }
 3036 
 3037 #endif /* DDB */

Cache object: de31e234494ab6528a61f7d2655964d8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.