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

Cache object: 8da4259d4b661fdab2bf6977f35119ea


[ 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.