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 /*      $NetBSD: kern_sysctl.c,v 1.206 2006/11/01 10:17:58 yamt Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 2003 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Andrew Brown.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*-
   40  * Copyright (c) 1982, 1986, 1989, 1993
   41  *      The Regents of the University of California.  All rights reserved.
   42  *
   43  * This code is derived from software contributed to Berkeley by
   44  * Mike Karels at Berkeley Software Design, Inc.
   45  *
   46  * Redistribution and use in source and binary forms, with or without
   47  * modification, are permitted provided that the following conditions
   48  * are met:
   49  * 1. Redistributions of source code must retain the above copyright
   50  *    notice, this list of conditions and the following disclaimer.
   51  * 2. Redistributions in binary form must reproduce the above copyright
   52  *    notice, this list of conditions and the following disclaimer in the
   53  *    documentation and/or other materials provided with the distribution.
   54  * 3. Neither the name of the University nor the names of its contributors
   55  *    may be used to endorse or promote products derived from this software
   56  *    without specific prior written permission.
   57  *
   58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   68  * SUCH DAMAGE.
   69  *
   70  *      @(#)kern_sysctl.c       8.9 (Berkeley) 5/20/95
   71  */
   72 
   73 /*
   74  * sysctl system call.
   75  */
   76 
   77 #include <sys/cdefs.h>
   78 __KERNEL_RCSID(0, "$NetBSD: kern_sysctl.c,v 1.206 2006/11/01 10:17:58 yamt Exp $");
   79 
   80 #include "opt_defcorename.h"
   81 #include "opt_ktrace.h"
   82 #include "ksyms.h"
   83 
   84 #include <sys/param.h>
   85 #define __COMPAT_SYSCTL
   86 #include <sys/sysctl.h>
   87 #include <sys/systm.h>
   88 #include <sys/buf.h>
   89 #include <sys/ksyms.h>
   90 #include <sys/malloc.h>
   91 #include <sys/mount.h>
   92 #include <sys/sa.h>
   93 #include <sys/syscallargs.h>
   94 #include <sys/kauth.h>
   95 #ifdef KTRACE
   96 #include <sys/ktrace.h>
   97 #endif
   98 #include <machine/stdarg.h>
   99 
  100 #define MAXDESCLEN      1024
  101 MALLOC_DEFINE(M_SYSCTLNODE, "sysctlnode", "sysctl node structures");
  102 MALLOC_DEFINE(M_SYSCTLDATA, "sysctldata", "misc sysctl data");
  103 
  104 static int sysctl_mmap(SYSCTLFN_PROTO);
  105 static int sysctl_alloc(struct sysctlnode *, int);
  106 static int sysctl_realloc(struct sysctlnode *);
  107 
  108 static int sysctl_cvt_in(struct lwp *, int *, const void *, size_t,
  109                          struct sysctlnode *);
  110 static int sysctl_cvt_out(struct lwp *, int, const struct sysctlnode *,
  111                           void *, size_t, size_t *);
  112 
  113 static int sysctl_log_add(struct sysctllog **, const struct sysctlnode *);
  114 static int sysctl_log_realloc(struct sysctllog *);
  115 
  116 struct sysctllog {
  117         const struct sysctlnode *log_root;
  118         int *log_num;
  119         int log_size, log_left;
  120 };
  121 
  122 /*
  123  * the "root" of the new sysctl tree
  124  */
  125 struct sysctlnode sysctl_root = {
  126         .sysctl_flags = SYSCTL_VERSION|
  127             CTLFLAG_ROOT|CTLFLAG_READWRITE|
  128             CTLTYPE_NODE,
  129         .sysctl_num = 0,
  130         /*
  131          * XXX once all ports are on gcc3, we can get rid of this
  132          * ugliness and simply make it into
  133          *
  134          *      .sysctl_size = sizeof(struct sysctlnode),
  135          */
  136         sysc_init_field(_sysctl_size, sizeof(struct sysctlnode)),
  137         .sysctl_name = "(root)",
  138 };
  139 
  140 /*
  141  * link set of functions that add nodes at boot time (see also
  142  * sysctl_buildtree())
  143  */
  144 __link_set_decl(sysctl_funcs, sysctl_setup_func);
  145 
  146 /*
  147  * The `sysctl_lock' is intended to serialize access to the sysctl
  148  * tree.  Given that it is now (a) dynamic, and (b) most consumers of
  149  * sysctl are going to be copying data out, the old `sysctl_memlock'
  150  * has been `upgraded' to simply guard the whole tree.
  151  *
  152  * The two new data here are to keep track of the locked chunk of
  153  * memory, if there is one, so that it can be released more easily
  154  * from anywhere.
  155  */
  156 struct lock sysctl_treelock;
  157 caddr_t sysctl_memaddr;
  158 size_t sysctl_memsize;
  159 
  160 /*
  161  * Attributes stored in the kernel.
  162  */
  163 char hostname[MAXHOSTNAMELEN];
  164 int hostnamelen;
  165 
  166 char domainname[MAXHOSTNAMELEN];
  167 int domainnamelen;
  168 
  169 long hostid;
  170 
  171 #ifndef DEFCORENAME
  172 #define DEFCORENAME     "%n.core"
  173 #endif
  174 char defcorename[MAXPATHLEN] = DEFCORENAME;
  175 
  176 /*
  177  * ********************************************************************
  178  * Section 0: Some simple glue
  179  * ********************************************************************
  180  * By wrapping copyin(), copyout(), and copyinstr() like this, we can
  181  * stop caring about who's calling us and simplify some code a bunch.
  182  * ********************************************************************
  183  */
  184 static inline int
  185 sysctl_copyin(struct lwp *l, const void *uaddr, void *kaddr, size_t len)
  186 {
  187         int error;
  188 
  189         if (l != NULL) {
  190                 error = copyin(uaddr, kaddr, len);
  191 #ifdef KTRACE
  192                 if (!error && KTRPOINT(l->l_proc, KTR_MIB)) {
  193                         struct iovec iov;
  194 
  195                         iov.iov_base = (void *)(vaddr_t)uaddr;
  196                         iov.iov_len = len;
  197                         ktrgenio(l, -1, UIO_WRITE, &iov, len, error);
  198                 }
  199 #endif
  200 
  201         } else {
  202                 error = kcopy(uaddr, kaddr, len);
  203         }
  204 
  205         return error;
  206 }
  207 
  208 static inline int
  209 sysctl_copyout(struct lwp *l, const void *kaddr, void *uaddr, size_t len)
  210 {
  211         int error;
  212 
  213         if (l != NULL) {
  214                 error = copyout(kaddr, uaddr, len);
  215 #ifdef KTRACE
  216                 if (!error && KTRPOINT(l->l_proc, KTR_MIB)) {
  217                         struct iovec iov;
  218 
  219                         iov.iov_base = (void *)(vaddr_t)uaddr;
  220                         iov.iov_len = len;
  221                         ktrgenio(l, -1, UIO_READ, &iov, len, error);
  222                 }
  223 #endif
  224         } else {
  225                 error = kcopy(kaddr, uaddr, len);
  226         }
  227         
  228         return error;
  229 }
  230 
  231 static inline int
  232 sysctl_copyinstr(struct lwp *l, const void *uaddr, void *kaddr,
  233                  size_t len, size_t *done)
  234 {
  235         int error;
  236 
  237         if (l != NULL) {
  238                 error = copyinstr(uaddr, kaddr, len, done);
  239 #ifdef KTRACE
  240                 if (!error && KTRPOINT(l->l_proc, KTR_MIB)) {
  241                         struct iovec iov;
  242 
  243                         iov.iov_base = (void *)(vaddr_t)uaddr;
  244                         iov.iov_len = len;
  245                         ktrgenio(l, -1, UIO_WRITE, &iov, len, error);
  246                 }
  247 #endif
  248         } else {
  249                 error = copystr(uaddr, kaddr, len, done);
  250         }
  251 
  252         return error;
  253 }
  254 
  255 /*
  256  * ********************************************************************
  257  * Initialize sysctl subsystem.
  258  * ********************************************************************
  259  */
  260 void
  261 sysctl_init(void)
  262 {
  263         sysctl_setup_func * const *sysctl_setup, f;
  264 
  265         lockinit(&sysctl_treelock, PRIBIO|PCATCH, "sysctl", 0, 0);
  266 
  267         /*
  268          * dynamic mib numbers start here
  269          */
  270         sysctl_root.sysctl_num = CREATE_BASE;
  271 
  272         __link_set_foreach(sysctl_setup, sysctl_funcs) {
  273                 /*
  274                  * XXX - why do i have to coerce the pointers like this?
  275                  */
  276                 f = (void*)*sysctl_setup;
  277                 (*f)(NULL);
  278         }
  279 
  280         /*
  281          * setting this means no more permanent nodes can be added,
  282          * trees that claim to be readonly at the root now are, and if
  283          * the main tree is readonly, *everything* is.
  284          */
  285         sysctl_root.sysctl_flags |= CTLFLAG_PERMANENT;
  286 
  287 }
  288 
  289 /*
  290  * ********************************************************************
  291  * The main native sysctl system call itself.
  292  * ********************************************************************
  293  */
  294 int
  295 sys___sysctl(struct lwp *l, void *v, register_t *retval)
  296 {
  297         struct sys___sysctl_args /* {
  298                 syscallarg(const int *) name;
  299                 syscallarg(u_int) namelen;
  300                 syscallarg(void *) old;
  301                 syscallarg(size_t *) oldlenp;
  302                 syscallarg(const void *) new;
  303                 syscallarg(size_t) newlen;
  304         } */ *uap = v;
  305         int error, nerror, name[CTL_MAXNAME];
  306         size_t oldlen, savelen, *oldlenp;
  307 
  308         /*
  309          * get oldlen
  310          */
  311         oldlen = 0;
  312         oldlenp = SCARG(uap, oldlenp);
  313         if (oldlenp != NULL) {
  314                 error = copyin(oldlenp, &oldlen, sizeof(oldlen));
  315                 if (error)
  316                         return (error);
  317         }
  318         savelen = oldlen;
  319 
  320         /*
  321          * top-level sysctl names may or may not be non-terminal, but
  322          * we don't care
  323          */
  324         if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 1)
  325                 return (EINVAL);
  326         error = copyin(SCARG(uap, name), &name,
  327                        SCARG(uap, namelen) * sizeof(int));
  328         if (error)
  329                 return (error);
  330 
  331 #ifdef KTRACE
  332         if (KTRPOINT(l->l_proc, KTR_MIB)) 
  333                 ktrmib(l, name, SCARG(uap, namelen));
  334 #endif
  335         /*
  336          * wire old so that copyout() is less likely to fail?
  337          */
  338         error = sysctl_lock(l, SCARG(uap, old), savelen);
  339         if (error)
  340                 return (error);
  341 
  342         /*
  343          * do sysctl work (NULL means main built-in default tree)
  344          */
  345         error = sysctl_dispatch(&name[0], SCARG(uap, namelen),
  346                                 SCARG(uap, old), &oldlen,
  347                                 SCARG(uap, new), SCARG(uap, newlen),
  348                                 &name[0], l, NULL);
  349 
  350         /*
  351          * release the sysctl lock
  352          */
  353         sysctl_unlock(l);
  354 
  355         /*
  356          * set caller's oldlen to new value even in the face of an
  357          * error (if this gets an error and they didn't have one, they
  358          * get this one)
  359          */
  360         if (oldlenp) {
  361                 nerror = copyout(&oldlen, oldlenp, sizeof(oldlen));
  362                 if (error == 0)
  363                         error = nerror;
  364         }
  365 
  366         /*
  367          * if the only problem is that we weren't given enough space,
  368          * that's an ENOMEM error
  369          */
  370         if (error == 0 && SCARG(uap, old) != NULL && savelen < oldlen)
  371                 error = ENOMEM;
  372 
  373         return (error);
  374 }
  375 
  376 /*
  377  * ********************************************************************
  378  * Section 1: How the tree is used
  379  * ********************************************************************
  380  * Implementations of sysctl for emulations should typically need only
  381  * these three functions in this order: lock the tree, dispatch
  382  * request into it, unlock the tree.
  383  * ********************************************************************
  384  */
  385 int
  386 sysctl_lock(struct lwp *l, void *oldp, size_t savelen)
  387 {
  388         int error = 0;
  389 
  390         error = lockmgr(&sysctl_treelock, LK_EXCLUSIVE, NULL);
  391         if (error)
  392                 return (error);
  393 
  394         if (l != NULL && oldp != NULL && savelen) {
  395 
  396                 /*
  397                  * be lazy - memory is locked for short time only, so
  398                  * just do a basic check against system limit
  399                  */
  400 
  401                 if (uvmexp.wired + atop(savelen) > uvmexp.wiredmax) {
  402                         lockmgr(&sysctl_treelock, LK_RELEASE, NULL);
  403                         return (ENOMEM);
  404                 }
  405                 error = uvm_vslock(l->l_proc->p_vmspace, oldp, savelen,
  406                                    VM_PROT_WRITE);
  407                 if (error) {
  408                         (void) lockmgr(&sysctl_treelock, LK_RELEASE, NULL);
  409                         return (error);
  410                 }
  411                 sysctl_memaddr = oldp;
  412                 sysctl_memsize = savelen;
  413         }
  414 
  415         return (0);
  416 }
  417 
  418 /*
  419  * ********************************************************************
  420  * the main sysctl dispatch routine.  scans the given tree and picks a
  421  * function to call based on what it finds.
  422  * ********************************************************************
  423  */
  424 int
  425 sysctl_dispatch(SYSCTLFN_ARGS)
  426 {
  427         int error;
  428         sysctlfn fn;
  429         int ni;
  430 
  431         if (rnode && SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) {
  432                 printf("sysctl_dispatch: rnode %p wrong version\n", rnode);
  433                 error = EINVAL;
  434                 goto out;
  435         }
  436 
  437         fn = NULL;
  438         error = sysctl_locate(l, name, namelen, &rnode, &ni);
  439 
  440         if (rnode->sysctl_func != NULL) {
  441                 /*
  442                  * the node we ended up at has a function, so call it.  it can
  443                  * hand off to query or create if it wants to.
  444                  */
  445                 fn = rnode->sysctl_func;
  446         } else if (error == 0) {
  447                 /*
  448                  * we found the node they were looking for, so do a lookup.
  449                  */
  450                 fn = (sysctlfn)sysctl_lookup; /* XXX may write to rnode */
  451         } else if (error == ENOENT && (ni + 1) == namelen && name[ni] < 0) {
  452                 /*
  453                  * prospective parent node found, but the terminal node was
  454                  * not.  generic operations associate with the parent.
  455                  */
  456                 switch (name[ni]) {
  457                 case CTL_QUERY:
  458                         fn = sysctl_query;
  459                         break;
  460                 case CTL_CREATE:
  461 #if NKSYMS > 0
  462                 case CTL_CREATESYM:
  463 #endif /* NKSYMS > 0 */
  464                         fn = (sysctlfn)sysctl_create; /* we own the rnode */
  465                         break;
  466                 case CTL_DESTROY:
  467                         fn = (sysctlfn)sysctl_destroy; /* we own the rnode */
  468                         break;
  469                 case CTL_MMAP:
  470                         fn = (sysctlfn)sysctl_mmap; /* we own the rnode */
  471                         break;
  472                 case CTL_DESCRIBE:
  473                         fn = sysctl_describe;
  474                         break;
  475                 default:
  476                         error = EOPNOTSUPP;
  477                         break;
  478                 }
  479         }
  480 
  481         /*
  482          * after all of that, maybe we found someone who knows how to
  483          * get us what we want?
  484          */
  485         if (fn != NULL)
  486                 error = (*fn)(name + ni, namelen - ni, oldp, oldlenp,
  487                               newp, newlen, name, l, rnode);
  488         else if (error == 0)
  489                 error = EOPNOTSUPP;
  490 
  491 out:
  492         return (error);
  493 }
  494 
  495 /*
  496  * ********************************************************************
  497  * Releases the tree lock.  Note that if uvm_vslock() was called when
  498  * the lock was taken, we release that memory now.  By keeping track
  499  * of where and how much by ourselves, the lock can be released much
  500  * more easily from anywhere.
  501  * ********************************************************************
  502  */
  503 void
  504 sysctl_unlock(struct lwp *l)
  505 {
  506 
  507         if (l != NULL && sysctl_memsize != 0) {
  508                 uvm_vsunlock(l->l_proc->p_vmspace, sysctl_memaddr,
  509                              sysctl_memsize);
  510                 sysctl_memsize = 0;
  511         }
  512 
  513         (void) lockmgr(&sysctl_treelock, LK_RELEASE, NULL);
  514 }
  515 
  516 /*
  517  * ********************************************************************
  518  * Section 2: The main tree interfaces
  519  * ********************************************************************
  520  * This is how sysctl_dispatch() does its work, and you can too, by
  521  * calling these routines from helpers (though typically only
  522  * sysctl_lookup() will be used).  The tree MUST BE LOCKED when these
  523  * are called.
  524  * ********************************************************************
  525  */
  526 
  527 /*
  528  * sysctl_locate -- Finds the node matching the given mib under the
  529  * given tree (via rv).  If no tree is given, we fall back to the
  530  * native tree.  The current process (via l) is used for access
  531  * control on the tree (some nodes may be traversable only by root) and
  532  * on return, nip will show how many numbers in the mib were consumed.
  533  */
  534 int
  535 sysctl_locate(struct lwp *l, const int *name, u_int namelen,
  536               const struct sysctlnode **rnode, int *nip)
  537 {
  538         const struct sysctlnode *node, *pnode;
  539         int tn, si, ni, error, alias;
  540 
  541         /*
  542          * basic checks and setup
  543          */
  544         if (*rnode == NULL)
  545                 *rnode = &sysctl_root;
  546         if (nip)
  547                 *nip = 0;
  548         if (namelen == 0)
  549                 return (0);
  550 
  551         /*
  552          * search starts from "root"
  553          */
  554         pnode = *rnode;
  555         if (SYSCTL_VERS(pnode->sysctl_flags) != SYSCTL_VERSION) {
  556                 printf("sysctl_locate: pnode %p wrong version\n", pnode);
  557                 return (EINVAL);
  558         }
  559         node = pnode->sysctl_child;
  560         error = 0;
  561 
  562         /*
  563          * scan for node to which new node should be attached
  564          */
  565         for (ni = 0; ni < namelen; ni++) {
  566                 /*
  567                  * walked off bottom of tree
  568                  */
  569                 if (node == NULL) {
  570                         if (SYSCTL_TYPE(pnode->sysctl_flags) == CTLTYPE_NODE)
  571                                 error = ENOENT;
  572                         else
  573                                 error = ENOTDIR;
  574                         break;
  575                 }
  576                 /*
  577                  * can anyone traverse this node or only root?
  578                  */
  579                 if (l != NULL && (pnode->sysctl_flags & CTLFLAG_PRIVATE) &&
  580                     (error = kauth_authorize_system(l->l_cred,
  581                     KAUTH_SYSTEM_SYSCTL, KAUTH_REQ_SYSTEM_SYSCTL_PRVT,
  582                     NULL, NULL, NULL)) != 0)
  583                         return (error);
  584                 /*
  585                  * find a child node with the right number
  586                  */
  587                 tn = name[ni];
  588                 alias = 0;
  589 
  590                 si = 0;
  591                 /*
  592                  * Note: ANYNUMBER only matches positive integers.
  593                  * Since ANYNUMBER is only permitted on single-node
  594                  * sub-trees (eg proc), check before the loop and skip
  595                  * it if we can.
  596                  */
  597                 if ((node[si].sysctl_flags & CTLFLAG_ANYNUMBER) && (tn >= 0))
  598                         goto foundit;
  599                 for (; si < pnode->sysctl_clen; si++) {
  600                         if (node[si].sysctl_num == tn) {
  601                                 if (node[si].sysctl_flags & CTLFLAG_ALIAS) {
  602                                         if (alias++ == 4)
  603                                                 break;
  604                                         else {
  605                                                 tn = node[si].sysctl_alias;
  606                                                 si = -1;
  607                                         }
  608                                 } else
  609                                         goto foundit;
  610                         }
  611                 }
  612                 /*
  613                  * if we ran off the end, it obviously doesn't exist
  614                  */
  615                 error = ENOENT;
  616                 break;
  617 
  618                 /*
  619                  * so far so good, move on down the line
  620                  */
  621           foundit:
  622                 pnode = &node[si];
  623                 if (SYSCTL_TYPE(pnode->sysctl_flags) == CTLTYPE_NODE)
  624                         node = node[si].sysctl_child;
  625                 else
  626                         node = NULL;
  627         }
  628 
  629         *rnode = pnode;
  630         if (nip)
  631                 *nip = ni;
  632 
  633         return (error);
  634 }
  635 
  636 /*
  637  * sysctl_query -- The auto-discovery engine.  Copies out the structs
  638  * describing nodes under the given node and handles overlay trees.
  639  */
  640 int
  641 sysctl_query(SYSCTLFN_ARGS)
  642 {
  643         int error, ni, elim, v;
  644         size_t out, left, t;
  645         const struct sysctlnode *enode, *onode;
  646         struct sysctlnode qnode;
  647 
  648         if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) {
  649                 printf("sysctl_query: rnode %p wrong version\n", rnode);
  650                 return (EINVAL);
  651         }
  652 
  653         if (SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE)
  654                 return (ENOTDIR);
  655         if (namelen != 1 || name[0] != CTL_QUERY)
  656                 return (EINVAL);
  657 
  658         error = 0;
  659         out = 0;
  660         left = *oldlenp;
  661         elim = 0;
  662         enode = NULL;
  663 
  664         /*
  665          * translate the given request to a current node
  666          */
  667         error = sysctl_cvt_in(l, &v, newp, newlen, &qnode);
  668         if (error)
  669                 return (error);
  670 
  671         /*
  672          * if the request specifies a version, check it
  673          */
  674         if (qnode.sysctl_ver != 0) {
  675                 enode = rnode;
  676                 if (qnode.sysctl_ver != enode->sysctl_ver &&
  677                     qnode.sysctl_ver != sysctl_rootof(enode)->sysctl_ver)
  678                         return (EINVAL);
  679         }
  680 
  681         /*
  682          * process has overlay tree
  683          */
  684         if (l && l->l_proc->p_emul->e_sysctlovly) {
  685                 enode = l->l_proc->p_emul->e_sysctlovly;
  686                 elim = (name - oname);
  687                 error = sysctl_locate(l, oname, elim, &enode, NULL);
  688                 if (error == 0) {
  689                         /* ah, found parent in overlay */
  690                         elim = enode->sysctl_clen;
  691                         enode = enode->sysctl_child;
  692                 } else {
  693                         error = 0;
  694                         elim = 0;
  695                         enode = NULL;
  696                 }
  697         }
  698 
  699         for (ni = 0; ni < rnode->sysctl_clen; ni++) {
  700                 onode = &rnode->sysctl_child[ni];
  701                 if (enode && enode->sysctl_num == onode->sysctl_num) {
  702                         if (SYSCTL_TYPE(enode->sysctl_flags) != CTLTYPE_NODE)
  703                                 onode = enode;
  704                         if (--elim > 0)
  705                                 enode++;
  706                         else
  707                                 enode = NULL;
  708                 }
  709                 error = sysctl_cvt_out(l, v, onode, oldp, left, &t);
  710                 if (error)
  711                         return (error);
  712                 if (oldp != NULL)
  713                         oldp = (char*)oldp + t;
  714                 out += t;
  715                 left -= MIN(left, t);
  716         }
  717 
  718         /*
  719          * overlay trees *MUST* be entirely consumed
  720          */
  721         KASSERT(enode == NULL);
  722 
  723         *oldlenp = out;
  724 
  725         return (error);
  726 }
  727 
  728 /*
  729  * sysctl_create -- Adds a node (the description of which is taken
  730  * from newp) to the tree, returning a copy of it in the space pointed
  731  * to by oldp.  In the event that the requested slot is already taken
  732  * (either by name or by number), the offending node is returned
  733  * instead.  Yes, this is complex, but we want to make sure everything
  734  * is proper.
  735  */
  736 #ifdef SYSCTL_DEBUG_CREATE
  737 int _sysctl_create(SYSCTLFN_ARGS);
  738 int
  739 _sysctl_create(SYSCTLFN_ARGS)
  740 #else
  741 int
  742 sysctl_create(SYSCTLFN_ARGS)
  743 #endif
  744 {
  745         struct sysctlnode nnode, *node, *pnode;
  746         int error, ni, at, nm, type, sz, flags, anum, v;
  747         void *own;
  748 
  749         error = 0;
  750         own = NULL;
  751         anum = -1;
  752 
  753         if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) {
  754                 printf("sysctl_create: rnode %p wrong version\n", rnode);
  755                 return (EINVAL);
  756         }
  757 
  758         if (namelen != 1 || (name[namelen - 1] != CTL_CREATE
  759 #if NKSYMS > 0
  760                              && name[namelen - 1] != CTL_CREATESYM
  761 #endif /* NKSYMS > 0 */
  762                              ))
  763                 return (EINVAL);
  764 
  765         /*
  766          * processes can only add nodes at securelevel 0, must be
  767          * root, and can't add nodes to a parent that's not writeable
  768          */
  769         if (l != NULL) {
  770 #ifndef SYSCTL_DISALLOW_CREATE
  771                 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SYSCTL,
  772                     KAUTH_REQ_SYSTEM_SYSCTL_ADD, NULL, NULL, NULL);
  773                 if (error)
  774                         return (error);
  775                 if (!(rnode->sysctl_flags & CTLFLAG_READWRITE))
  776 #endif /* SYSCTL_DISALLOW_CREATE */
  777                         return (EPERM);
  778         }
  779 
  780         /*
  781          * nothing can add a node if:
  782          * we've finished initial set up and
  783          * the tree itself is not writeable or
  784          * the entire sysctl system is not writeable
  785          */
  786         if ((sysctl_root.sysctl_flags & CTLFLAG_PERMANENT) &&
  787             (!(sysctl_rootof(rnode)->sysctl_flags & CTLFLAG_READWRITE) ||
  788              !(sysctl_root.sysctl_flags & CTLFLAG_READWRITE)))
  789                 return (EPERM);
  790 
  791         /*
  792          * it must be a "node", not a "int" or something
  793          */
  794         if (SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE)
  795                 return (ENOTDIR);
  796         if (rnode->sysctl_flags & CTLFLAG_ALIAS) {
  797                 printf("sysctl_create: attempt to add node to aliased "
  798                        "node %p\n", rnode);
  799                 return (EINVAL);
  800         }
  801         pnode = __UNCONST(rnode); /* we are adding children to this node */
  802 
  803         if (newp == NULL)
  804                 return (EINVAL);
  805         error = sysctl_cvt_in(l, &v, newp, newlen, &nnode);
  806         if (error)
  807                 return (error);
  808 
  809         /*
  810          * nodes passed in don't *have* parents
  811          */
  812         if (nnode.sysctl_parent != NULL)
  813                 return (EINVAL);
  814 
  815         /*
  816          * if we are indeed adding it, it should be a "good" name and
  817          * number
  818          */
  819         nm = nnode.sysctl_num;
  820 #if NKSYMS > 0
  821         if (nm == CTL_CREATESYM)
  822                 nm = CTL_CREATE;
  823 #endif /* NKSYMS > 0 */
  824         if (nm < 0 && nm != CTL_CREATE)
  825                 return (EINVAL);
  826         sz = 0;
  827 
  828         /*
  829          * the name can't start with a digit
  830          */
  831         if (nnode.sysctl_name[sz] >= '' &&
  832             nnode.sysctl_name[sz] <= '9')
  833                 return (EINVAL);
  834 
  835         /*
  836          * the name must be only alphanumerics or - or _, longer than
  837          * 0 bytes and less that SYSCTL_NAMELEN
  838          */
  839         while (sz < SYSCTL_NAMELEN && nnode.sysctl_name[sz] != '\0') {
  840                 if ((nnode.sysctl_name[sz] >= '' &&
  841                      nnode.sysctl_name[sz] <= '9') ||
  842                     (nnode.sysctl_name[sz] >= 'A' &&
  843                      nnode.sysctl_name[sz] <= 'Z') ||
  844                     (nnode.sysctl_name[sz] >= 'a' &&
  845                      nnode.sysctl_name[sz] <= 'z') ||
  846                     nnode.sysctl_name[sz] == '-' ||
  847                     nnode.sysctl_name[sz] == '_')
  848                         sz++;
  849                 else
  850                         return (EINVAL);
  851         }
  852         if (sz == 0 || sz == SYSCTL_NAMELEN)
  853                 return (EINVAL);
  854 
  855         /*
  856          * various checks revolve around size vs type, etc
  857          */
  858         type = SYSCTL_TYPE(nnode.sysctl_flags);
  859         flags = SYSCTL_FLAGS(nnode.sysctl_flags);
  860         sz = nnode.sysctl_size;
  861 
  862         /*
  863          * find out if there's a collision, and if so, let the caller
  864          * know what they collided with
  865          */
  866         node = pnode->sysctl_child;
  867         at = 0;
  868         if (node) {
  869                 if ((flags | node->sysctl_flags) & CTLFLAG_ANYNUMBER)
  870                         /* No siblings for a CTLFLAG_ANYNUMBER node */
  871                         return EINVAL;
  872                 for (ni = 0; ni < pnode->sysctl_clen; ni++) {
  873                         if (nm == node[ni].sysctl_num ||
  874                             strcmp(nnode.sysctl_name, node[ni].sysctl_name) == 0) {
  875                                 /*
  876                                  * ignore error here, since we
  877                                  * are already fixed on EEXIST
  878                                  */
  879                                 (void)sysctl_cvt_out(l, v, &node[ni], oldp,
  880                                                      *oldlenp, oldlenp);
  881                                 return (EEXIST);
  882                         }
  883                         if (nm > node[ni].sysctl_num)
  884                                 at++;
  885                 }
  886         }
  887 
  888         /*
  889          * use sysctl_ver to add to the tree iff it hasn't changed
  890          */
  891         if (nnode.sysctl_ver != 0) {
  892                 /*
  893                  * a specified value must match either the parent
  894                  * node's version or the root node's version
  895                  */
  896                 if (nnode.sysctl_ver != sysctl_rootof(rnode)->sysctl_ver &&
  897                     nnode.sysctl_ver != rnode->sysctl_ver) {
  898                         return (EINVAL);
  899                 }
  900         }
  901 
  902         /*
  903          * only the kernel can assign functions to entries
  904          */
  905         if (l != NULL && nnode.sysctl_func != NULL)
  906                 return (EPERM);
  907 
  908         /*
  909          * only the kernel can create permanent entries, and only then
  910          * before the kernel is finished setting itself up
  911          */
  912         if (l != NULL && (flags & ~SYSCTL_USERFLAGS))
  913                 return (EPERM);
  914         if ((flags & CTLFLAG_PERMANENT) &
  915             (sysctl_root.sysctl_flags & CTLFLAG_PERMANENT))
  916                 return (EPERM);
  917         if ((flags & (CTLFLAG_OWNDATA | CTLFLAG_IMMEDIATE)) ==
  918             (CTLFLAG_OWNDATA | CTLFLAG_IMMEDIATE))
  919                 return (EINVAL);
  920         if ((flags & CTLFLAG_IMMEDIATE) &&
  921             type != CTLTYPE_INT && type != CTLTYPE_QUAD)
  922                 return (EINVAL);
  923 
  924         /*
  925          * check size, or set it if unset and we can figure it out.
  926          * kernel created nodes are allowed to have a function instead
  927          * of a size (or a data pointer).
  928          */
  929         switch (type) {
  930         case CTLTYPE_NODE:
  931                 /*
  932                  * only *i* can assert the size of a node
  933                  */
  934                 if (flags & CTLFLAG_ALIAS) {
  935                         anum = nnode.sysctl_alias;
  936                         if (anum < 0)
  937                                 return (EINVAL);
  938                         nnode.sysctl_alias = 0;
  939                 }
  940                 if (sz != 0 || nnode.sysctl_data != NULL)
  941                         return (EINVAL);
  942                 if (nnode.sysctl_csize != 0 ||
  943                     nnode.sysctl_clen != 0 ||
  944                     nnode.sysctl_child != 0)
  945                         return (EINVAL);
  946                 if (flags & CTLFLAG_OWNDATA)
  947                         return (EINVAL);
  948                 sz = sizeof(struct sysctlnode);
  949                 break;
  950         case CTLTYPE_INT:
  951                 /*
  952                  * since an int is an int, if the size is not given or
  953                  * is wrong, we can "int-uit" it.
  954                  */
  955                 if (sz != 0 && sz != sizeof(int))
  956                         return (EINVAL);
  957                 sz = sizeof(int);
  958                 break;
  959         case CTLTYPE_STRING:
  960                 /*
  961                  * strings are a little more tricky
  962                  */
  963                 if (sz == 0) {
  964                         if (l == NULL) {
  965                                 if (nnode.sysctl_func == NULL) {
  966                                         if (nnode.sysctl_data == NULL)
  967                                                 return (EINVAL);
  968                                         else
  969                                                 sz = strlen(nnode.sysctl_data) +
  970                                                     1;
  971                                 }
  972                         } else if (nnode.sysctl_data == NULL &&
  973                                  flags & CTLFLAG_OWNDATA) {
  974                                 return (EINVAL);
  975                         } else {
  976                                 char *vp, *e;
  977                                 size_t s;
  978 
  979                                 /*
  980                                  * we want a rough idea of what the
  981                                  * size is now
  982                                  */
  983                                 vp = malloc(PAGE_SIZE, M_SYSCTLDATA,
  984                                              M_WAITOK|M_CANFAIL);
  985                                 if (vp == NULL)
  986                                         return (ENOMEM);
  987                                 e = nnode.sysctl_data;
  988                                 do {
  989                                         error = copyinstr(e, vp, PAGE_SIZE, &s);
  990                                         if (error) {
  991                                                 if (error != ENAMETOOLONG) {
  992                                                         free(vp, M_SYSCTLDATA);
  993                                                         return (error);
  994                                                 }
  995                                                 e += PAGE_SIZE;
  996                                                 if ((e - 32 * PAGE_SIZE) >
  997                                                     (char*)nnode.sysctl_data) {
  998                                                         free(vp, M_SYSCTLDATA);
  999                                                         return (ERANGE);
 1000                                                 }
 1001                                         }
 1002                                 } while (error != 0);
 1003                                 sz = s + (e - (char*)nnode.sysctl_data);
 1004                                 free(vp, M_SYSCTLDATA);
 1005                         }
 1006                 }
 1007                 break;
 1008         case CTLTYPE_QUAD:
 1009                 if (sz != 0 && sz != sizeof(u_quad_t))
 1010                         return (EINVAL);
 1011                 sz = sizeof(u_quad_t);
 1012                 break;
 1013         case CTLTYPE_STRUCT:
 1014                 if (sz == 0) {
 1015                         if (l != NULL || nnode.sysctl_func == NULL)
 1016                                 return (EINVAL);
 1017                         if (flags & CTLFLAG_OWNDATA)
 1018                                 return (EINVAL);
 1019                 }
 1020                 break;
 1021         default:
 1022                 return (EINVAL);
 1023         }
 1024 
 1025         /*
 1026          * at this point, if sz is zero, we *must* have a
 1027          * function to go with it and we can't own it.
 1028          */
 1029 
 1030         /*
 1031          *  l  ptr own
 1032          *  0   0   0  -> EINVAL (if no func)
 1033          *  0   0   1  -> own
 1034          *  0   1   0  -> kptr
 1035          *  0   1   1  -> kptr
 1036          *  1   0   0  -> EINVAL
 1037          *  1   0   1  -> own
 1038          *  1   1   0  -> kptr, no own (fault on lookup)
 1039          *  1   1   1  -> uptr, own
 1040          */
 1041         if (type != CTLTYPE_NODE) {
 1042                 if (sz != 0) {
 1043                         if (flags & CTLFLAG_OWNDATA) {
 1044                                 own = malloc(sz, M_SYSCTLDATA,
 1045                                              M_WAITOK|M_CANFAIL);
 1046                                 if (own == NULL)
 1047                                         return ENOMEM;
 1048                                 if (nnode.sysctl_data == NULL)
 1049                                         memset(own, 0, sz);
 1050                                 else {
 1051                                         error = sysctl_copyin(l,
 1052                                             nnode.sysctl_data, own, sz);
 1053                                         if (error != 0) {
 1054                                                 free(own, M_SYSCTLDATA);
 1055                                                 return (error);
 1056                                         }
 1057                                 }
 1058                         } else if ((nnode.sysctl_data != NULL) &&
 1059                                  !(flags & CTLFLAG_IMMEDIATE)) {
 1060 #if NKSYMS > 0
 1061                                 if (name[namelen - 1] == CTL_CREATESYM) {
 1062                                         char symname[128]; /* XXX enough? */
 1063                                         u_long symaddr;
 1064                                         size_t symlen;
 1065 
 1066                                         error = sysctl_copyinstr(l,
 1067                                             nnode.sysctl_data, symname,
 1068                                             sizeof(symname), &symlen);
 1069                                         if (error)
 1070                                                 return (error);
 1071                                         error = ksyms_getval(NULL, symname,
 1072                                             &symaddr, KSYMS_EXTERN);
 1073                                         if (error)
 1074                                                 return (error); /* EINVAL? */
 1075                                         nnode.sysctl_data = (void*)symaddr;
 1076                                 }
 1077 #endif /* NKSYMS > 0 */
 1078                                 /*
 1079                                  * Ideally, we'd like to verify here
 1080                                  * that this address is acceptable,
 1081                                  * but...
 1082                                  *
 1083                                  * - it might be valid now, only to
 1084                                  *   become invalid later
 1085                                  *
 1086                                  * - it might be invalid only for the
 1087                                  *   moment and valid later
 1088                                  *
 1089                                  * - or something else.
 1090                                  *
 1091                                  * Since we can't get a good answer,
 1092                                  * we'll just accept the address as
 1093                                  * given, and fault on individual
 1094                                  * lookups.
 1095                                  */
 1096                         }
 1097                 } else if (nnode.sysctl_func == NULL)
 1098                         return (EINVAL);
 1099         }
 1100 
 1101         /*
 1102          * a process can't assign a function to a node, and the kernel
 1103          * can't create a node that has no function or data.
 1104          * (XXX somewhat redundant check)
 1105          */
 1106         if (l != NULL || nnode.sysctl_func == NULL) {
 1107                 if (type != CTLTYPE_NODE &&
 1108                     nnode.sysctl_data == NULL &&
 1109                     !(flags & CTLFLAG_IMMEDIATE) &&
 1110                     own == NULL)
 1111                         return (EINVAL);
 1112         }
 1113 
 1114 #ifdef SYSCTL_DISALLOW_KWRITE
 1115         /*
 1116          * a process can't create a writable node unless it refers to
 1117          * new data.
 1118          */
 1119         if (l != NULL && own == NULL && type != CTLTYPE_NODE &&
 1120             (flags & CTLFLAG_READWRITE) != CTLFLAG_READONLY &&
 1121             !(flags & CTLFLAG_IMMEDIATE))
 1122                 return (EPERM);
 1123 #endif /* SYSCTL_DISALLOW_KWRITE */
 1124 
 1125         /*
 1126          * make sure there's somewhere to put the new stuff.
 1127          */
 1128         if (pnode->sysctl_child == NULL) {
 1129                 if (flags & CTLFLAG_ANYNUMBER)
 1130                         error = sysctl_alloc(pnode, 1);
 1131                 else
 1132                         error = sysctl_alloc(pnode, 0);
 1133                 if (error) {
 1134                         if (own != NULL)
 1135                                 free(own, M_SYSCTLDATA);
 1136                         return (error);
 1137                 }
 1138         }
 1139         node = pnode->sysctl_child;
 1140 
 1141         /*
 1142          * no collisions, so pick a good dynamic number if we need to.
 1143          */
 1144         if (nm == CTL_CREATE) {
 1145                 nm = ++sysctl_root.sysctl_num;
 1146                 for (ni = 0; ni < pnode->sysctl_clen; ni++) {
 1147                         if (nm == node[ni].sysctl_num) {
 1148                                 nm++;
 1149                                 ni = -1;
 1150                         } else if (nm > node[ni].sysctl_num)
 1151                                 at = ni + 1;
 1152                 }
 1153         }
 1154 
 1155         /*
 1156          * oops...ran out of space
 1157          */
 1158         if (pnode->sysctl_clen == pnode->sysctl_csize) {
 1159                 error = sysctl_realloc(pnode);
 1160                 if (error) {
 1161                         if (own != NULL)
 1162                                 free(own, M_SYSCTLDATA);
 1163                         return (error);
 1164                 }
 1165                 node = pnode->sysctl_child;
 1166         }
 1167 
 1168         /*
 1169          * insert new node data
 1170          */
 1171         if (at < pnode->sysctl_clen) {
 1172                 int t;
 1173 
 1174                 /*
 1175                  * move the nodes that should come after the new one
 1176                  */
 1177                 memmove(&node[at + 1], &node[at],
 1178                         (pnode->sysctl_clen - at) * sizeof(struct sysctlnode));
 1179                 memset(&node[at], 0, sizeof(struct sysctlnode));
 1180                 node[at].sysctl_parent = pnode;
 1181                 /*
 1182                  * and...reparent any children of any moved nodes
 1183                  */
 1184                 for (ni = at; ni <= pnode->sysctl_clen; ni++)
 1185                         if (SYSCTL_TYPE(node[ni].sysctl_flags) == CTLTYPE_NODE)
 1186                                 for (t = 0; t < node[ni].sysctl_clen; t++)
 1187                                         node[ni].sysctl_child[t].sysctl_parent =
 1188                                                 &node[ni];
 1189         }
 1190         node = &node[at];
 1191         pnode->sysctl_clen++;
 1192 
 1193         strlcpy(node->sysctl_name, nnode.sysctl_name,
 1194                 sizeof(node->sysctl_name));
 1195         node->sysctl_num = nm;
 1196         node->sysctl_size = sz;
 1197         node->sysctl_flags = SYSCTL_VERSION|type|flags; /* XXX other trees */
 1198         node->sysctl_csize = 0;
 1199         node->sysctl_clen = 0;
 1200         if (own) {
 1201                 node->sysctl_data = own;
 1202                 node->sysctl_flags |= CTLFLAG_OWNDATA;
 1203         } else if (flags & CTLFLAG_ALIAS) {
 1204                 node->sysctl_alias = anum;
 1205         } else if (flags & CTLFLAG_IMMEDIATE) {
 1206                 switch (type) {
 1207                 case CTLTYPE_INT:
 1208                         node->sysctl_idata = nnode.sysctl_idata;
 1209                         break;
 1210                 case CTLTYPE_QUAD:
 1211                         node->sysctl_qdata = nnode.sysctl_qdata;
 1212                         break;
 1213                 }
 1214         } else {
 1215                 node->sysctl_data = nnode.sysctl_data;
 1216                 node->sysctl_flags &= ~CTLFLAG_OWNDATA;
 1217         }
 1218         node->sysctl_func = nnode.sysctl_func;
 1219         node->sysctl_child = NULL;
 1220         /* node->sysctl_parent should already be done */
 1221 
 1222         /*
 1223          * update "version" on path to "root"
 1224          */
 1225         for (; rnode->sysctl_parent != NULL; rnode = rnode->sysctl_parent)
 1226                 ;
 1227         pnode = node;
 1228         for (nm = rnode->sysctl_ver + 1; pnode != NULL;
 1229              pnode = pnode->sysctl_parent)
 1230                 pnode->sysctl_ver = nm;
 1231 
 1232         /* If this fails, the node is already added - the user won't know! */
 1233         error = sysctl_cvt_out(l, v, node, oldp, *oldlenp, oldlenp);
 1234 
 1235         return (error);
 1236 }
 1237 
 1238 /*
 1239  * ********************************************************************
 1240  * A wrapper around sysctl_create() that prints the thing we're trying
 1241  * to add.
 1242  * ********************************************************************
 1243  */
 1244 #ifdef SYSCTL_DEBUG_CREATE
 1245 int
 1246 sysctl_create(SYSCTLFN_ARGS)
 1247 {
 1248         const struct sysctlnode *node;
 1249         int k, rc, ni, nl = namelen + (name - oname);
 1250 
 1251         node = newp;
 1252 
 1253         printf("namelen %d (", nl);
 1254         for (ni = 0; ni < nl - 1; ni++)
 1255                 printf(" %d", oname[ni]);
 1256         printf(" %d )\t[%s]\tflags %08x (%08x %d %zu)\n",
 1257                k = node->sysctl_num,
 1258                node->sysctl_name,
 1259                node->sysctl_flags,
 1260                SYSCTL_FLAGS(node->sysctl_flags),
 1261                SYSCTL_TYPE(node->sysctl_flags),
 1262                node->sysctl_size);
 1263 
 1264         node = rnode;
 1265         rc = _sysctl_create(SYSCTLFN_CALL(rnode));
 1266 
 1267         printf("sysctl_create(");
 1268         for (ni = 0; ni < nl - 1; ni++)
 1269                 printf(" %d", oname[ni]);
 1270         printf(" %d ) returned %d\n", k, rc);
 1271 
 1272         return (rc);
 1273 }
 1274 #endif /* SYSCTL_DEBUG_CREATE */
 1275 
 1276 /*
 1277  * sysctl_destroy -- Removes a node (as described by newp) from the
 1278  * given tree, returning (if successful) a copy of the dead node in
 1279  * oldp.  Since we're removing stuff, there's not much to check.
 1280  */
 1281 int
 1282 sysctl_destroy(SYSCTLFN_ARGS)
 1283 {
 1284         struct sysctlnode *node, *pnode, onode, nnode;
 1285         int ni, error, v;
 1286 
 1287         if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) {
 1288                 printf("sysctl_destroy: rnode %p wrong version\n", rnode);
 1289                 return (EINVAL);
 1290         }
 1291 
 1292         error = 0;
 1293 
 1294         if (namelen != 1 || name[namelen - 1] != CTL_DESTROY)
 1295                 return (EINVAL);
 1296 
 1297         /*
 1298          * processes can only destroy nodes at securelevel 0, must be
 1299          * root, and can't remove nodes from a parent that's not
 1300          * writeable
 1301          */
 1302         if (l != NULL) {
 1303 #ifndef SYSCTL_DISALLOW_CREATE
 1304                 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SYSCTL,
 1305                     KAUTH_REQ_SYSTEM_SYSCTL_DELETE, NULL, NULL, NULL);
 1306                 if (error)
 1307                         return (error);
 1308                 if (!(rnode->sysctl_flags & CTLFLAG_READWRITE))
 1309 #endif /* SYSCTL_DISALLOW_CREATE */
 1310                         return (EPERM);
 1311         }
 1312 
 1313         /*
 1314          * nothing can remove a node if:
 1315          * the node is permanent (checked later) or
 1316          * the tree itself is not writeable or
 1317          * the entire sysctl system is not writeable
 1318          *
 1319          * note that we ignore whether setup is complete or not,
 1320          * because these rules always apply.
 1321          */
 1322         if (!(sysctl_rootof(rnode)->sysctl_flags & CTLFLAG_READWRITE) ||
 1323             !(sysctl_root.sysctl_flags & CTLFLAG_READWRITE))
 1324                 return (EPERM);
 1325 
 1326         if (newp == NULL)
 1327                 return (EINVAL);
 1328         error = sysctl_cvt_in(l, &v, newp, newlen, &nnode);
 1329         if (error)
 1330                 return (error);
 1331         memset(&onode, 0, sizeof(struct sysctlnode));
 1332 
 1333         node = rnode->sysctl_child;
 1334         for (ni = 0; ni < rnode->sysctl_clen; ni++) {
 1335                 if (nnode.sysctl_num == node[ni].sysctl_num) {
 1336                         /*
 1337                          * if name specified, must match
 1338                          */
 1339                         if (nnode.sysctl_name[0] != '\0' &&
 1340                             strcmp(nnode.sysctl_name, node[ni].sysctl_name))
 1341                                 continue;
 1342                         /*
 1343                          * if version specified, must match
 1344                          */
 1345                         if (nnode.sysctl_ver != 0 &&
 1346                             nnode.sysctl_ver != node[ni].sysctl_ver)
 1347                                 continue;
 1348                         /*
 1349                          * this must be the one
 1350                          */
 1351                         break;
 1352                 }
 1353         }
 1354         if (ni == rnode->sysctl_clen)
 1355                 return (ENOENT);
 1356         node = &node[ni];
 1357         pnode = node->sysctl_parent;
 1358 
 1359         /*
 1360          * if the kernel says permanent, it is, so there.  nyah.
 1361          */
 1362         if (SYSCTL_FLAGS(node->sysctl_flags) & CTLFLAG_PERMANENT)
 1363                 return (EPERM);
 1364 
 1365         /*
 1366          * can't delete non-empty nodes
 1367          */
 1368         if (SYSCTL_TYPE(node->sysctl_flags) == CTLTYPE_NODE &&
 1369             node->sysctl_clen != 0)
 1370                 return (ENOTEMPTY);
 1371 
 1372         /*
 1373          * if the node "owns" data, release it now
 1374          */
 1375         if (node->sysctl_flags & CTLFLAG_OWNDATA) {
 1376                 if (node->sysctl_data != NULL)
 1377                         free(node->sysctl_data, M_SYSCTLDATA);
 1378                 node->sysctl_data = NULL;
 1379         }
 1380         if (node->sysctl_flags & CTLFLAG_OWNDESC) {
 1381                 if (node->sysctl_desc != NULL)
 1382                         /*XXXUNCONST*/
 1383                         free(__UNCONST(node->sysctl_desc), M_SYSCTLDATA);
 1384                 node->sysctl_desc = NULL;
 1385         }
 1386 
 1387         /*
 1388          * if the node to be removed is not the last one on the list,
 1389          * move the remaining nodes up, and reparent any grandchildren
 1390          */
 1391         onode = *node;
 1392         if (ni < pnode->sysctl_clen - 1) {
 1393                 int t;
 1394 
 1395                 memmove(&pnode->sysctl_child[ni], &pnode->sysctl_child[ni + 1],
 1396                         (pnode->sysctl_clen - ni - 1) *
 1397                         sizeof(struct sysctlnode));
 1398                 for (; ni < pnode->sysctl_clen - 1; ni++)
 1399                         if (SYSCTL_TYPE(pnode->sysctl_child[ni].sysctl_flags) ==
 1400                             CTLTYPE_NODE)
 1401                                 for (t = 0;
 1402                                      t < pnode->sysctl_child[ni].sysctl_clen;
 1403                                      t++)
 1404                                         pnode->sysctl_child[ni].sysctl_child[t].
 1405                                                 sysctl_parent =
 1406                                                 &pnode->sysctl_child[ni];
 1407                 ni = pnode->sysctl_clen - 1;
 1408                 node = &pnode->sysctl_child[ni];
 1409         }
 1410 
 1411         /*
 1412          * reset the space we just vacated
 1413          */
 1414         memset(node, 0, sizeof(struct sysctlnode));
 1415         node->sysctl_parent = pnode;
 1416         pnode->sysctl_clen--;
 1417 
 1418         /*
 1419          * if this parent just lost its last child, nuke the creche
 1420          */
 1421         if (pnode->sysctl_clen == 0) {
 1422                 free(pnode->sysctl_child, M_SYSCTLNODE);
 1423                 pnode->sysctl_csize = 0;
 1424                 pnode->sysctl_child = NULL;
 1425         }
 1426 
 1427         /*
 1428          * update "version" on path to "root"
 1429          */
 1430         for (; rnode->sysctl_parent != NULL; rnode = rnode->sysctl_parent)
 1431                 ;
 1432         for (ni = rnode->sysctl_ver + 1; pnode != NULL;
 1433              pnode = pnode->sysctl_parent)
 1434                 pnode->sysctl_ver = ni;
 1435 
 1436         error = sysctl_cvt_out(l, v, &onode, oldp, *oldlenp, oldlenp);
 1437 
 1438         return (error);
 1439 }
 1440 
 1441 /*
 1442  * sysctl_lookup -- Handles copyin/copyout of new and old values.
 1443  * Partial reads are globally allowed.  Only root can write to things
 1444  * unless the node says otherwise.
 1445  */
 1446 int
 1447 sysctl_lookup(SYSCTLFN_ARGS)
 1448 {
 1449         int error, rw;
 1450         size_t sz, len;
 1451         void *d;
 1452 
 1453         if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) {
 1454                 printf("sysctl_lookup: rnode %p wrong version\n", rnode);
 1455                 return (EINVAL);
 1456         }
 1457 
 1458         error = 0;
 1459 
 1460         /*
 1461          * you can't "look up" a node.  you can "query" it, but you
 1462          * can't "look it up".
 1463          */
 1464         if (SYSCTL_TYPE(rnode->sysctl_flags) == CTLTYPE_NODE || namelen != 0)
 1465                 return (EINVAL);
 1466 
 1467         /*
 1468          * some nodes are private, so only root can look into them.
 1469          */
 1470         if (l != NULL && (rnode->sysctl_flags & CTLFLAG_PRIVATE) &&
 1471             (error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SYSCTL,
 1472             KAUTH_REQ_SYSTEM_SYSCTL_PRVT, NULL, NULL, NULL)) != 0)
 1473                 return (error);
 1474 
 1475         /*
 1476          * if a node wants to be writable according to different rules
 1477          * other than "only root can write to stuff unless a flag is
 1478          * set", then it needs its own function which should have been
 1479          * called and not us.
 1480          */
 1481         if (l != NULL && newp != NULL &&
 1482             !(rnode->sysctl_flags & CTLFLAG_ANYWRITE) &&
 1483             (error = kauth_authorize_generic(l->l_cred,
 1484             KAUTH_GENERIC_ISSUSER, &l->l_acflag)) != 0)
 1485                 return (error);
 1486 
 1487         /*
 1488          * is this node supposedly writable?
 1489          */
 1490         rw = (rnode->sysctl_flags & CTLFLAG_READWRITE) ? 1 : 0;
 1491 
 1492         /*
 1493          * it appears not to be writable at this time, so if someone
 1494          * tried to write to it, we must tell them to go away
 1495          */
 1496         if (!rw && newp != NULL)
 1497                 return (EPERM);
 1498 
 1499         /*
 1500          * step one, copy out the stuff we have presently
 1501          */
 1502         if (rnode->sysctl_flags & CTLFLAG_IMMEDIATE) {
 1503                 /*
 1504                  * note that we discard const here because we are
 1505                  * modifying the contents of the node (which is okay
 1506                  * because it's ours)
 1507                  */
 1508                 switch (SYSCTL_TYPE(rnode->sysctl_flags)) {
 1509                 case CTLTYPE_INT:
 1510                         d = __UNCONST(&rnode->sysctl_idata);
 1511                         break;
 1512                 case CTLTYPE_QUAD:
 1513                         d = __UNCONST(&rnode->sysctl_qdata);
 1514                         break;
 1515                 default:
 1516                         return (EINVAL);
 1517                 }
 1518         } else
 1519                 d = rnode->sysctl_data;
 1520         if (SYSCTL_TYPE(rnode->sysctl_flags) == CTLTYPE_STRING)
 1521                 sz = strlen(d) + 1; /* XXX@@@ possible fault here */
 1522         else
 1523                 sz = rnode->sysctl_size;
 1524         if (oldp != NULL)
 1525                 error = sysctl_copyout(l, d, oldp, MIN(sz, *oldlenp));
 1526         if (error)
 1527                 return (error);
 1528         *oldlenp = sz;
 1529 
 1530         /*
 1531          * are we done?
 1532          */
 1533         if (newp == NULL || newlen == 0)
 1534                 return (0);
 1535 
 1536         /*
 1537          * hmm...not done.  must now "copy in" new value.  re-adjust
 1538          * sz to maximum value (strings are "weird").
 1539          */
 1540         sz = rnode->sysctl_size;
 1541         switch (SYSCTL_TYPE(rnode->sysctl_flags)) {
 1542         case CTLTYPE_INT:
 1543         case CTLTYPE_QUAD:
 1544         case CTLTYPE_STRUCT:
 1545                 /*
 1546                  * these data must be *exactly* the same size coming
 1547                  * in.
 1548                  */
 1549                 if (newlen != sz)
 1550                         return (EINVAL);
 1551                 error = sysctl_copyin(l, newp, d, sz);
 1552                 break;
 1553         case CTLTYPE_STRING: {
 1554                 /*
 1555                  * strings, on the other hand, can be shorter, and we
 1556                  * let userland be sloppy about the trailing nul.
 1557                  */
 1558                 char *newbuf;
 1559 
 1560                 /*
 1561                  * too much new string?
 1562                  */
 1563                 if (newlen > sz)
 1564                         return (EINVAL);
 1565 
 1566                 /*
 1567                  * temporary copy of new inbound string
 1568                  */
 1569                 len = MIN(sz, newlen);
 1570                 newbuf = malloc(len, M_SYSCTLDATA, M_WAITOK|M_CANFAIL);
 1571                 if (newbuf == NULL)
 1572                         return (ENOMEM);
 1573                 error = sysctl_copyin(l, newp, newbuf, len);
 1574                 if (error) {
 1575                         free(newbuf, M_SYSCTLDATA);
 1576                         return (error);
 1577                 }
 1578 
 1579                 /*
 1580                  * did they null terminate it, or do we have space
 1581                  * left to do it ourselves?
 1582                  */
 1583                 if (newbuf[len - 1] != '\0' && len == sz) {
 1584                         free(newbuf, M_SYSCTLDATA);
 1585                         return (EINVAL);
 1586                 }
 1587 
 1588                 /*
 1589                  * looks good, so pop it into place and zero the rest.
 1590                  */
 1591                 if (len > 0)
 1592                         memcpy(d, newbuf, len);
 1593                 if (sz != len)
 1594                         memset((char*)d + len, 0, sz - len);
 1595                 free(newbuf, M_SYSCTLDATA);
 1596                 break;
 1597         }
 1598         default:
 1599                 return (EINVAL);
 1600         }
 1601 
 1602         return (error);
 1603 }
 1604 
 1605 /*
 1606  * sysctl_mmap -- Dispatches sysctl mmap requests to those nodes that
 1607  * purport to handle it.  This interface isn't fully fleshed out yet,
 1608  * unfortunately.
 1609  */
 1610 static int
 1611 sysctl_mmap(SYSCTLFN_ARGS)
 1612 {
 1613         const struct sysctlnode *node;
 1614         struct sysctlnode nnode;
 1615         int error;
 1616 
 1617         if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) {
 1618                 printf("sysctl_mmap: rnode %p wrong version\n", rnode);
 1619                 return (EINVAL);
 1620         }
 1621 
 1622         /*
 1623          * let's just pretend that didn't happen, m'kay?
 1624          */
 1625         if (l == NULL)
 1626                 return (EPERM);
 1627 
 1628         /*
 1629          * is this a sysctlnode description of an mmap request?
 1630          */
 1631         if (newp == NULL || newlen != sizeof(struct sysctlnode))
 1632                 return (EINVAL);
 1633         error = sysctl_copyin(l, newp, &nnode, sizeof(nnode));
 1634         if (error)
 1635                 return (error);
 1636 
 1637         /*
 1638          * does the node they asked for exist?
 1639          */
 1640         if (namelen != 1)
 1641                 return (EOPNOTSUPP);
 1642         node = rnode;
 1643         error = sysctl_locate(l, &nnode.sysctl_num, 1, &node, NULL);
 1644         if (error)
 1645                 return (error);
 1646 
 1647         /*
 1648          * does this node that we have found purport to handle mmap?
 1649          */
 1650         if (node->sysctl_func == NULL ||
 1651             !(node->sysctl_flags & CTLFLAG_MMAP))
 1652                 return (EOPNOTSUPP);
 1653 
 1654         /*
 1655          * well...okay, they asked for it.
 1656          */
 1657         return ((*node->sysctl_func)(SYSCTLFN_CALL(node)));
 1658 }
 1659 
 1660 int
 1661 sysctl_describe(SYSCTLFN_ARGS)
 1662 {
 1663         struct sysctldesc *d;
 1664         void *bf;
 1665         size_t sz, left, tot;
 1666         int i, error, v = -1;
 1667         struct sysctlnode *node;
 1668         struct sysctlnode dnode;
 1669 
 1670         if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) {
 1671                 printf("sysctl_query: rnode %p wrong version\n", rnode);
 1672                 return (EINVAL);
 1673         }
 1674 
 1675         if (SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE)
 1676                 return (ENOTDIR);
 1677         if (namelen != 1 || name[0] != CTL_DESCRIBE)
 1678                 return (EINVAL);
 1679 
 1680         /*
 1681          * get ready...
 1682          */
 1683         error = 0;
 1684         d = bf = malloc(MAXDESCLEN, M_TEMP, M_WAITOK|M_CANFAIL);
 1685         if (bf == NULL)
 1686                 return ENOMEM;
 1687         tot = 0;
 1688         node = rnode->sysctl_child;
 1689         left = *oldlenp;
 1690 
 1691         /*
 1692          * no request -> all descriptions at this level
 1693          * request with desc unset -> just this node
 1694          * request with desc set -> set descr for this node
 1695          */
 1696         if (newp != NULL) {
 1697                 error = sysctl_cvt_in(l, &v, newp, newlen, &dnode);
 1698                 if (error)
 1699                         goto out;
 1700                 if (dnode.sysctl_desc != NULL) {
 1701                         /*
 1702                          * processes cannot set descriptions above
 1703                          * securelevel 0.  and must be root.  blah
 1704                          * blah blah.  a couple more checks are made
 1705                          * once we find the node we want.
 1706                          */
 1707                         if (l != NULL) {
 1708 #ifndef SYSCTL_DISALLOW_CREATE
 1709                                 error = kauth_authorize_system(l->l_cred,
 1710                                     KAUTH_SYSTEM_SYSCTL,
 1711                                     KAUTH_REQ_SYSTEM_SYSCTL_DESC, NULL,
 1712                                     NULL, NULL);
 1713                                 if (error)
 1714                                         goto out;
 1715 #else /* SYSCTL_DISALLOW_CREATE */
 1716                                 error = EPERM;
 1717                                 goto out;
 1718 #endif /* SYSCTL_DISALLOW_CREATE */
 1719                         }
 1720 
 1721                         /*
 1722                          * find node and try to set the description on it
 1723                          */
 1724                         for (i = 0; i < rnode->sysctl_clen; i++)
 1725                                 if (node[i].sysctl_num == dnode.sysctl_num)
 1726                                         break;
 1727                         if (i == rnode->sysctl_clen) {
 1728                                 error = ENOENT;
 1729                                 goto out;
 1730                         }
 1731                         node = &node[i];
 1732 
 1733                         /*
 1734                          * did the caller specify a node version?
 1735                          */
 1736                         if (dnode.sysctl_ver != 0 &&
 1737                             dnode.sysctl_ver != node->sysctl_ver) {
 1738                                 error = EINVAL;
 1739                                 goto out;
 1740                         }
 1741 
 1742                         /*
 1743                          * okay...some rules:
 1744                          * (1) if setup is done and the tree is
 1745                          *     read-only or the whole system is
 1746                          *     read-only
 1747                          * (2) no one can set a description on a
 1748                          *     permanent node (it must be set when
 1749                          *     using createv)
 1750                          * (3) processes cannot *change* a description
 1751                          * (4) processes *can*, however, set a
 1752                          *     description on a read-only node so that
 1753                          *     one can be created and then described
 1754                          *     in two steps
 1755                          * anything else come to mind?
 1756                          */
 1757                         if ((sysctl_root.sysctl_flags & CTLFLAG_PERMANENT) &&
 1758                             (!(sysctl_rootof(node)->sysctl_flags &
 1759                                CTLFLAG_READWRITE) ||
 1760                              !(sysctl_root.sysctl_flags & CTLFLAG_READWRITE))) {
 1761                                 error = EPERM;
 1762                                 goto out;
 1763                         }
 1764                         if (node->sysctl_flags & CTLFLAG_PERMANENT) {
 1765                                 error = EPERM;
 1766                                 goto out;
 1767                         }
 1768                         if (l != NULL && node->sysctl_desc != NULL) {
 1769                                 error = EPERM;
 1770                                 goto out;
 1771                         }
 1772 
 1773                         /*
 1774                          * right, let's go ahead.  the first step is
 1775                          * making the description into something the
 1776                          * node can "own", if need be.
 1777                          */
 1778                         if (l != NULL ||
 1779                             dnode.sysctl_flags & CTLFLAG_OWNDESC) {
 1780                                 char *nd, *k;
 1781 
 1782                                 k = malloc(MAXDESCLEN, M_TEMP,
 1783                                     M_WAITOK|M_CANFAIL);
 1784                                 if (k == NULL) {
 1785                                         error = ENOMEM;
 1786                                         goto out;
 1787                                 }
 1788                                 error = sysctl_copyinstr(l, dnode.sysctl_desc,
 1789                                                          k, MAXDESCLEN, &sz);
 1790                                 if (error) {
 1791                                         free(k, M_TEMP);
 1792                                         goto out;
 1793                                 }
 1794                                 nd = malloc(sz, M_SYSCTLDATA,
 1795                                             M_WAITOK|M_CANFAIL);
 1796                                 if (nd == NULL) {
 1797                                         free(k, M_TEMP);
 1798                                         error = ENOMEM;
 1799                                         goto out;
 1800                                 }
 1801                                 memcpy(nd, k, sz);
 1802                                 dnode.sysctl_flags |= CTLFLAG_OWNDESC;
 1803                                 dnode.sysctl_desc = nd;
 1804                                 free(k, M_TEMP);
 1805                         }
 1806 
 1807                         /*
 1808                          * now "release" the old description and
 1809                          * attach the new one.  ta-da.
 1810                          */
 1811                         if ((node->sysctl_flags & CTLFLAG_OWNDESC) &&
 1812                             node->sysctl_desc != NULL)
 1813                                 /*XXXUNCONST*/
 1814                                 free(__UNCONST(node->sysctl_desc), M_SYSCTLDATA);
 1815                         node->sysctl_desc = dnode.sysctl_desc;
 1816                         node->sysctl_flags |=
 1817                                 (dnode.sysctl_flags & CTLFLAG_OWNDESC);
 1818 
 1819                         /*
 1820                          * now we "fall out" and into the loop which
 1821                          * will copy the new description back out for
 1822                          * those interested parties
 1823                          */
 1824                 }
 1825         }
 1826 
 1827         /*
 1828          * scan for one description or just retrieve all descriptions
 1829          */
 1830         for (i = 0; i < rnode->sysctl_clen; i++) {
 1831                 /*
 1832                  * did they ask for the description of only one node?
 1833                  */
 1834                 if (v != -1 && node[i].sysctl_num != dnode.sysctl_num)
 1835                         continue;
 1836 
 1837                 /*
 1838                  * don't describe "private" nodes to non-suser users
 1839                  */
 1840                 if ((node[i].sysctl_flags & CTLFLAG_PRIVATE) && (l != NULL) &&
 1841                     !(kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SYSCTL,
 1842                     KAUTH_REQ_SYSTEM_SYSCTL_PRVT, NULL, NULL, NULL)))
 1843                         continue;
 1844 
 1845                 /*
 1846                  * is this description "valid"?
 1847                  */
 1848                 memset(bf, 0, MAXDESCLEN);
 1849                 if (node[i].sysctl_desc == NULL)
 1850                         sz = 1;
 1851                 else if (copystr(node[i].sysctl_desc, &d->descr_str[0],
 1852                                  MAXDESCLEN - sizeof(*d), &sz) != 0) {
 1853                         /*
 1854                          * erase possible partial description
 1855                          */
 1856                         memset(bf, 0, MAXDESCLEN);
 1857                         sz = 1;
 1858                 }
 1859 
 1860                 /*
 1861                  * we've got it, stuff it into the caller's buffer
 1862                  */
 1863                 d->descr_num = node[i].sysctl_num;
 1864                 d->descr_ver = node[i].sysctl_ver;
 1865                 d->descr_len = sz; /* includes trailing nul */
 1866                 sz = (caddr_t)NEXT_DESCR(d) - (caddr_t)d;
 1867                 if (oldp != NULL && left >= sz) {
 1868                         error = sysctl_copyout(l, d, oldp, sz);
 1869                         if (error)
 1870                                 goto out;
 1871                         left -= sz;
 1872                         oldp = (void *)__sysc_desc_adv(oldp, d->descr_len);
 1873                 }
 1874                 tot += sz;
 1875 
 1876                 /*
 1877                  * if we get this far with v not "unset", they asked
 1878                  * for a specific node and we found it
 1879                  */
 1880                 if (v != -1)
 1881                         break;
 1882         }
 1883 
 1884         /*
 1885          * did we find it after all?
 1886          */
 1887         if (v != -1 && tot == 0)
 1888                 error = ENOENT;
 1889         else
 1890                 *oldlenp = tot;
 1891 
 1892 out:
 1893         free(bf, M_TEMP);
 1894         return (error);
 1895 }
 1896 
 1897 /*
 1898  * ********************************************************************
 1899  * Section 3: Create and destroy from inside the kernel
 1900  * ********************************************************************
 1901  * sysctl_createv() and sysctl_destroyv() are simpler-to-use
 1902  * interfaces for the kernel to fling new entries into the mib and rip
 1903  * them out later.  In the case of sysctl_createv(), the returned copy
 1904  * of the node (see sysctl_create()) will be translated back into a
 1905  * pointer to the actual node.
 1906  *
 1907  * Note that sysctl_createv() will return 0 if the create request
 1908  * matches an existing node (ala mkdir -p), and that sysctl_destroyv()
 1909  * will return 0 if the node to be destroyed already does not exist
 1910  * (aka rm -f) or if it is a parent of other nodes.
 1911  *
 1912  * This allows two (or more) different subsystems to assert sub-tree
 1913  * existence before populating their own nodes, and to remove their
 1914  * own nodes without orphaning the others when they are done.
 1915  * ********************************************************************
 1916  */
 1917 int
 1918 sysctl_createv(struct sysctllog **log, int cflags,
 1919                const struct sysctlnode **rnode, const struct sysctlnode **cnode,
 1920                int flags, int type, const char *namep, const char *descr,
 1921                sysctlfn func, u_quad_t qv, void *newp, size_t newlen,
 1922                ...)
 1923 {
 1924         va_list ap;
 1925         int error, ni, namelen, name[CTL_MAXNAME];
 1926         const struct sysctlnode *root, *pnode;
 1927         struct sysctlnode nnode, onode, *dnode;
 1928         size_t sz;
 1929 
 1930         /*
 1931          * where are we putting this?
 1932          */
 1933         if (rnode != NULL && *rnode == NULL) {
 1934                 printf("sysctl_createv: rnode NULL\n");
 1935                 return (EINVAL);
 1936         }
 1937         root = rnode ? *rnode : NULL;
 1938         if (cnode != NULL)
 1939                 *cnode = NULL;
 1940         if (cflags != 0)
 1941                 return (EINVAL);
 1942 
 1943         /*
 1944          * what is it?
 1945          */
 1946         flags = SYSCTL_VERSION|SYSCTL_TYPE(type)|SYSCTL_FLAGS(flags);
 1947         if (log != NULL)
 1948                 flags &= ~CTLFLAG_PERMANENT;
 1949 
 1950         /*
 1951          * where do we put it?
 1952          */
 1953         va_start(ap, newlen);
 1954         namelen = 0;
 1955         ni = -1;
 1956         do {
 1957                 if (++ni == CTL_MAXNAME)
 1958                         return (ENAMETOOLONG);
 1959                 name[ni] = va_arg(ap, int);
 1960                 /*
 1961                  * sorry, this is not supported from here
 1962                  */
 1963                 if (name[ni] == CTL_CREATESYM)
 1964                         return (EINVAL);
 1965         } while (name[ni] != CTL_EOL && name[ni] != CTL_CREATE);
 1966         namelen = ni + (name[ni] == CTL_CREATE ? 1 : 0);
 1967         va_end(ap);
 1968 
 1969         /*
 1970          * what's it called
 1971          */
 1972         if (strlcpy(nnode.sysctl_name, namep, sizeof(nnode.sysctl_name)) >=
 1973             sizeof(nnode.sysctl_name))
 1974                 return (ENAMETOOLONG);
 1975 
 1976         /*
 1977          * cons up the description of the new node
 1978          */
 1979         nnode.sysctl_num = name[namelen - 1];
 1980         name[namelen - 1] = CTL_CREATE;
 1981         nnode.sysctl_size = newlen;
 1982         nnode.sysctl_flags = flags;
 1983         if (type == CTLTYPE_NODE) {
 1984                 nnode.sysctl_csize = 0;
 1985                 nnode.sysctl_clen = 0;
 1986                 nnode.sysctl_child = NULL;
 1987                 if (flags & CTLFLAG_ALIAS)
 1988                         nnode.sysctl_alias = qv;
 1989         } else if (flags & CTLFLAG_IMMEDIATE) {
 1990                 switch (type) {
 1991                 case CTLTYPE_INT:
 1992                         nnode.sysctl_idata = qv;
 1993                         break;
 1994                 case CTLTYPE_QUAD:
 1995                         nnode.sysctl_qdata = qv;
 1996                         break;
 1997                 default:
 1998                         return (EINVAL);
 1999                 }
 2000         } else {
 2001                 nnode.sysctl_data = newp;
 2002         }
 2003         nnode.sysctl_func = func;
 2004         nnode.sysctl_parent = NULL;
 2005         nnode.sysctl_ver = 0;
 2006 
 2007         /*
 2008          * initialize lock state -- we need locks if the main tree has
 2009          * been marked as complete, but since we could be called from
 2010          * either there, or from a device driver (say, at device
 2011          * insertion), or from an lkm (at lkm load time, say), we
 2012          * don't really want to "wait"...
 2013          */
 2014         error = sysctl_lock(NULL, NULL, 0);
 2015         if (error)
 2016                 return (error);
 2017 
 2018         /*
 2019          * locate the prospective parent of the new node, and if we
 2020          * find it, add the new node.
 2021          */
 2022         sz = sizeof(onode);
 2023         pnode = root;
 2024         error = sysctl_locate(NULL, &name[0], namelen - 1, &pnode, &ni);
 2025         if (error) {
 2026                 printf("sysctl_createv: sysctl_locate(%s) returned %d\n",
 2027                        nnode.sysctl_name, error);
 2028                 sysctl_unlock(NULL);
 2029                 return (error);
 2030         }
 2031         error = sysctl_create(&name[ni], namelen - ni, &onode, &sz,
 2032                               &nnode, sizeof(nnode), &name[0], NULL,
 2033                               pnode);
 2034 
 2035         /*
 2036          * unfortunately the node we wanted to create is already
 2037          * there.  if the node that's already there is a reasonable
 2038          * facsimile of the node we wanted to create, just pretend
 2039          * (for the caller's benefit) that we managed to create the
 2040          * node they wanted.
 2041          */
 2042         if (error == EEXIST) {
 2043                 /* name is the same as requested... */
 2044                 if (strcmp(nnode.sysctl_name, onode.sysctl_name) == 0 &&
 2045                     /* they want the same function... */
 2046                     nnode.sysctl_func == onode.sysctl_func &&
 2047                     /* number is the same as requested, or... */
 2048                     (nnode.sysctl_num == onode.sysctl_num ||
 2049                      /* they didn't pick a number... */
 2050                      nnode.sysctl_num == CTL_CREATE)) {
 2051                         /*
 2052                          * collision here from trying to create
 2053                          * something that already existed; let's give
 2054                          * our customers a hand and tell them they got
 2055                          * what they wanted.
 2056                          */
 2057 #ifdef SYSCTL_DEBUG_CREATE
 2058                         printf("cleared\n");
 2059 #endif /* SYSCTL_DEBUG_CREATE */
 2060                         error = 0;
 2061                 }
 2062         }
 2063 
 2064         if (error == 0 &&
 2065             (cnode != NULL || log != NULL || descr != NULL)) {
 2066                 /*
 2067                  * sysctl_create() gave us back a copy of the node,
 2068                  * but we need to know where it actually is...
 2069                  */
 2070                 pnode = root;
 2071                 error = sysctl_locate(NULL, &name[0], namelen - 1, &pnode, &ni);
 2072 
 2073                 /*
 2074                  * manual scan of last layer so that aliased nodes
 2075                  * aren't followed.
 2076                  */
 2077                 if (error == 0) {
 2078                         for (ni = 0; ni < pnode->sysctl_clen; ni++)
 2079                                 if (pnode->sysctl_child[ni].sysctl_num ==
 2080                                     onode.sysctl_num)
 2081                                         break;
 2082                         if (ni < pnode->sysctl_clen)
 2083                                 pnode = &pnode->sysctl_child[ni];
 2084                         else
 2085                                 error = ENOENT;
 2086                 }
 2087 
 2088                 /*
 2089                  * not expecting an error here, but...
 2090                  */
 2091                 if (error == 0) {
 2092                         if (log != NULL)
 2093                                 sysctl_log_add(log, pnode);
 2094                         if (cnode != NULL)
 2095                                 *cnode = pnode;
 2096                         if (descr != NULL) {
 2097                                 /*
 2098                                  * allow first caller to *set* a
 2099                                  * description actually to set it
 2100                                  * 
 2101                                  * discard const here so we can attach
 2102                                  * the description
 2103                                  */
 2104                                 dnode = __UNCONST(pnode);
 2105                                 if (pnode->sysctl_desc != NULL)
 2106                                         /* skip it...we've got one */;
 2107                                 else if (flags & CTLFLAG_OWNDESC) {
 2108                                         size_t l = strlen(descr) + 1;
 2109                                         char *d = malloc(l, M_SYSCTLDATA,
 2110                                                          M_WAITOK|M_CANFAIL);
 2111                                         if (d != NULL) {
 2112                                                 memcpy(d, descr, l);
 2113                                                 dnode->sysctl_desc = d;
 2114                                                 dnode->sysctl_flags |=
 2115                                                     CTLFLAG_OWNDESC;
 2116                                         }
 2117                                 } else
 2118                                         dnode->sysctl_desc = descr;
 2119                         }
 2120                 } else {
 2121                         printf("sysctl_create succeeded but node not found?!\n");
 2122                         /*
 2123                          *  confusing, but the create said it
 2124                          * succeeded, so...
 2125                          */
 2126                         error = 0;
 2127                 }
 2128         }
 2129 
 2130         /*
 2131          * now it should be safe to release the lock state.  note that
 2132          * the pointer to the newly created node being passed back may
 2133          * not be "good" for very long.
 2134          */
 2135         sysctl_unlock(NULL);
 2136 
 2137         if (error != 0) {
 2138                 printf("sysctl_createv: sysctl_create(%s) returned %d\n",
 2139                        nnode.sysctl_name, error);
 2140 #if 0
 2141                 if (error != ENOENT)
 2142                         sysctl_dump(&onode);
 2143 #endif
 2144         }
 2145 
 2146         return (error);
 2147 }
 2148 
 2149 int
 2150 sysctl_destroyv(struct sysctlnode *rnode, ...)
 2151 {
 2152         va_list ap;
 2153         int error, name[CTL_MAXNAME], namelen, ni;
 2154         const struct sysctlnode *pnode, *node;
 2155         struct sysctlnode dnode, *onode;
 2156         size_t sz;
 2157 
 2158         va_start(ap, rnode);
 2159         namelen = 0;
 2160         ni = 0;
 2161         do {
 2162                 if (ni == CTL_MAXNAME)
 2163                         return (ENAMETOOLONG);
 2164                 name[ni] = va_arg(ap, int);
 2165         } while (name[ni++] != CTL_EOL);
 2166         namelen = ni - 1;
 2167         va_end(ap);
 2168 
 2169         /*
 2170          * i can't imagine why we'd be destroying a node when the tree
 2171          * wasn't complete, but who knows?
 2172          */
 2173         error = sysctl_lock(NULL, NULL, 0);
 2174         if (error)
 2175                 return (error);
 2176 
 2177         /*
 2178          * where is it?
 2179          */
 2180         node = rnode;
 2181         error = sysctl_locate(NULL, &name[0], namelen - 1, &node, &ni);
 2182         if (error) {
 2183                 /* they want it gone and it's not there, so... */
 2184                 sysctl_unlock(NULL);
 2185                 return (error == ENOENT ? 0 : error);
 2186         }
 2187 
 2188         /*
 2189          * set up the deletion
 2190          */
 2191         pnode = node;
 2192         node = &dnode;
 2193         memset(&dnode, 0, sizeof(dnode));
 2194         dnode.sysctl_flags = SYSCTL_VERSION;
 2195         dnode.sysctl_num = name[namelen - 1];
 2196 
 2197         /*
 2198          * we found it, now let's nuke it
 2199          */
 2200         name[namelen - 1] = CTL_DESTROY;
 2201         sz = 0;
 2202         error = sysctl_destroy(&name[namelen - 1], 1, NULL, &sz,
 2203                                node, sizeof(*node), &name[0], NULL,
 2204                                pnode);
 2205         if (error == ENOTEMPTY) {
 2206                 /*
 2207                  * think of trying to delete "foo" when "foo.bar"
 2208                  * (which someone else put there) is still in
 2209                  * existence
 2210                  */
 2211                 error = 0;
 2212 
 2213                 /*
 2214                  * dunno who put the description there, but if this
 2215                  * node can ever be removed, we need to make sure the
 2216                  * string doesn't go out of context.  that means we
 2217                  * need to find the node that's still there (don't use
 2218                  * sysctl_locate() because that follows aliasing).
 2219                  */
 2220                 node = pnode->sysctl_child;
 2221                 for (ni = 0; ni < pnode->sysctl_clen; ni++)
 2222                         if (node[ni].sysctl_num == dnode.sysctl_num)
 2223                                 break;
 2224                 node = (ni < pnode->sysctl_clen) ? &node[ni] : NULL;
 2225 
 2226                 /*
 2227                  * if we found it, and this node has a description,
 2228                  * and this node can be released, and it doesn't
 2229                  * already own its own description...sigh.  :)
 2230                  */
 2231                 if (node != NULL && node->sysctl_desc != NULL &&
 2232                     !(node->sysctl_flags & CTLFLAG_PERMANENT) &&
 2233                     !(node->sysctl_flags & CTLFLAG_OWNDESC)) {
 2234                         char *d;
 2235 
 2236                         sz = strlen(node->sysctl_desc) + 1;
 2237                         d = malloc(sz, M_SYSCTLDATA, M_WAITOK|M_CANFAIL);
 2238                         if (d != NULL) {
 2239                                 /*
 2240                                  * discard const so that we can
 2241                                  * re-attach the description
 2242                                  */
 2243                                 memcpy(d, node->sysctl_desc, sz);
 2244                                 onode = __UNCONST(node);
 2245                                 onode->sysctl_desc = d;
 2246                                 onode->sysctl_flags |= CTLFLAG_OWNDESC;
 2247                         } else {
 2248                                 /*
 2249                                  * XXX drop the description?  be
 2250                                  * afraid?  don't care?
 2251                                  */
 2252                         }
 2253                 }
 2254         }
 2255 
 2256         sysctl_unlock(NULL);
 2257 
 2258         return (error);
 2259 }
 2260 
 2261 #if 0
 2262 /*
 2263  * ********************************************************************
 2264  * the dump routine.  i haven't yet decided how (if at all) i'll call
 2265  * this from userland when it's in the kernel.
 2266  * ********************************************************************
 2267  */
 2268 static const char *
 2269 sf(int f)
 2270 {
 2271         static char s[256];
 2272         char *c;
 2273 
 2274         s[0] = '\0';
 2275         c = "";
 2276 
 2277 #define print_flag(_f, _s, _c, _q, _x) \
 2278         if (((_f) & (__CONCAT(CTLFLAG_,_x))) == (__CONCAT(CTLFLAG_,_q))) { \
 2279                 strlcat((_s), (_c), sizeof(_s)); \
 2280                 strlcat((_s), __STRING(_q), sizeof(_s)); \
 2281                 (_c) = ","; \
 2282                 (_f) &= ~__CONCAT(CTLFLAG_,_x); \
 2283         }
 2284 
 2285         print_flag(f, s, c, READONLY,  READWRITE);
 2286         print_flag(f, s, c, READWRITE, READWRITE);
 2287         print_flag(f, s, c, ANYWRITE,  ANYWRITE);
 2288         print_flag(f, s, c, PRIVATE,   PRIVATE);
 2289         print_flag(f, s, c, PERMANENT, PERMANENT);
 2290         print_flag(f, s, c, OWNDATA,   OWNDATA);
 2291         print_flag(f, s, c, IMMEDIATE, IMMEDIATE);
 2292         print_flag(f, s, c, HEX,       HEX);
 2293         print_flag(f, s, c, ROOT,      ROOT);
 2294         print_flag(f, s, c, ANYNUMBER, ANYNUMBER);
 2295         print_flag(f, s, c, HIDDEN,    HIDDEN);
 2296         print_flag(f, s, c, ALIAS,     ALIAS);
 2297 #undef print_flag
 2298 
 2299         if (f) {
 2300                 char foo[9];
 2301                 snprintf(foo, sizeof(foo), "%x", f);
 2302                 strlcat(s, c, sizeof(s));
 2303                 strlcat(s, foo, sizeof(s));
 2304         }
 2305 
 2306         return (s);
 2307 }
 2308 
 2309 static const char *
 2310 st(int t)
 2311 {
 2312 
 2313         switch (t) {
 2314         case CTLTYPE_NODE:
 2315                 return "NODE";
 2316         case CTLTYPE_INT:
 2317                 return "INT";
 2318         case CTLTYPE_STRING:
 2319                 return "STRING";
 2320         case CTLTYPE_QUAD:
 2321                 return "QUAD";
 2322         case CTLTYPE_STRUCT:
 2323                 return "STRUCT";
 2324         }
 2325 
 2326         return "???";
 2327 }
 2328 
 2329 void
 2330 sysctl_dump(const struct sysctlnode *d)
 2331 {
 2332         static char nmib[64], smib[256];
 2333         static int indent;
 2334         struct sysctlnode *n;
 2335         char *np, *sp, tmp[20];
 2336         int i;
 2337 
 2338         if (d == NULL)
 2339                 return;
 2340 
 2341         np = &nmib[strlen(nmib)];
 2342         sp = &smib[strlen(smib)];
 2343 
 2344         if (!(d->sysctl_flags & CTLFLAG_ROOT)) {
 2345                 snprintf(tmp, sizeof(tmp), "%d", d->sysctl_num);
 2346                 strcat(nmib, ".");
 2347                 strcat(smib, ".");
 2348                 strcat(nmib, tmp);
 2349                 strcat(smib, d->sysctl_name);
 2350                 printf("%s -> %s (%d)\n", &nmib[1], &smib[1],
 2351                        SYSCTL_TYPE(d->sysctl_flags));
 2352         }
 2353 
 2354         if (1) {
 2355                 printf("%*s%p:\tsysctl_name  [%s]\n", indent, "",
 2356                        d, d->sysctl_name);
 2357                 printf("%*s\t\tsysctl_num    %d\n",   indent, "",
 2358                        d->sysctl_num);
 2359                 printf("%*s\t\tsysctl_flags  %x (flags=%x<%s> type=%d<%s> "
 2360                        "size=%zu)\n",
 2361                        indent, "", d->sysctl_flags,
 2362                        SYSCTL_FLAGS(d->sysctl_flags),
 2363                        sf(SYSCTL_FLAGS(d->sysctl_flags)),
 2364                        SYSCTL_TYPE(d->sysctl_flags),
 2365                        st(SYSCTL_TYPE(d->sysctl_flags)),
 2366                        d->sysctl_size);
 2367                 if (SYSCTL_TYPE(d->sysctl_flags) == CTLTYPE_NODE) {
 2368                         printf("%*s\t\tsysctl_csize  %d\n",   indent, "",
 2369                                d->sysctl_csize);
 2370                         printf("%*s\t\tsysctl_clen   %d\n",   indent, "",
 2371                                d->sysctl_clen);
 2372                         printf("%*s\t\tsysctl_child  %p\n",   indent, "",
 2373                                d->sysctl_child);
 2374                 } else
 2375                         printf("%*s\t\tsysctl_data   %p\n",   indent, "",
 2376                                d->sysctl_data);
 2377                 printf("%*s\t\tsysctl_func   %p\n",   indent, "",
 2378                        d->sysctl_func);
 2379                 printf("%*s\t\tsysctl_parent %p\n",   indent, "",
 2380                        d->sysctl_parent);
 2381                 printf("%*s\t\tsysctl_ver    %d\n",   indent, "",
 2382                        d->sysctl_ver);
 2383         }
 2384 
 2385         if (SYSCTL_TYPE(d->sysctl_flags) == CTLTYPE_NODE) {
 2386                 indent += 8;
 2387                 n = d->sysctl_child;
 2388                 for (i = 0; i < d->sysctl_clen; i++) {
 2389                         sysctl_dump(&n[i]);
 2390                 }
 2391                 indent -= 8;
 2392         }
 2393 
 2394         np[0] = '\0';
 2395         sp[0] = '\0';
 2396 }
 2397 #endif /* 0 */
 2398 
 2399 /*
 2400  * ********************************************************************
 2401  * Deletes an entire n-ary tree.  Not recommended unless you know why
 2402  * you're doing it.  Personally, I don't know why you'd even think
 2403  * about it.
 2404  * ********************************************************************
 2405  */
 2406 void
 2407 sysctl_free(struct sysctlnode *rnode)
 2408 {
 2409         struct sysctlnode *node, *pnode;
 2410 
 2411         if (rnode == NULL)
 2412                 rnode = &sysctl_root;
 2413 
 2414         if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) {
 2415                 printf("sysctl_free: rnode %p wrong version\n", rnode);
 2416                 return;
 2417         }
 2418 
 2419         pnode = rnode;
 2420 
 2421         node = pnode->sysctl_child;
 2422         do {
 2423                 while (node != NULL && pnode->sysctl_csize > 0) {
 2424                         while (node <
 2425                                &pnode->sysctl_child[pnode->sysctl_clen] &&
 2426                                (SYSCTL_TYPE(node->sysctl_flags) !=
 2427                                 CTLTYPE_NODE ||
 2428                                 node->sysctl_csize == 0)) {
 2429                                 if (SYSCTL_FLAGS(node->sysctl_flags) &
 2430                                     CTLFLAG_OWNDATA) {
 2431                                         if (node->sysctl_data != NULL) {
 2432                                                 free(node->sysctl_data,
 2433                                                      M_SYSCTLDATA);
 2434                                                 node->sysctl_data = NULL;
 2435                                         }
 2436                                 }
 2437                                 if (SYSCTL_FLAGS(node->sysctl_flags) &
 2438                                     CTLFLAG_OWNDESC) {
 2439                                         if (node->sysctl_desc != NULL) {
 2440                                                 /*XXXUNCONST*/
 2441                                                 free(__UNCONST(node->sysctl_desc),
 2442                                                      M_SYSCTLDATA);
 2443                                                 node->sysctl_desc = NULL;
 2444                                         }
 2445                                 }
 2446                                 node++;
 2447                         }
 2448                         if (node < &pnode->sysctl_child[pnode->sysctl_clen]) {
 2449                                 pnode = node;
 2450                                 node = node->sysctl_child;
 2451                         } else
 2452                                 break;
 2453                 }
 2454                 if (pnode->sysctl_child != NULL)
 2455                         free(pnode->sysctl_child, M_SYSCTLNODE);
 2456                 pnode->sysctl_clen = 0;
 2457                 pnode->sysctl_csize = 0;
 2458                 pnode->sysctl_child = NULL;
 2459                 node = pnode;
 2460                 pnode = node->sysctl_parent;
 2461         } while (pnode != NULL && node != rnode);
 2462 }
 2463 
 2464 int
 2465 sysctl_log_add(struct sysctllog **logp, const struct sysctlnode *node)
 2466 {
 2467         int name[CTL_MAXNAME], namelen, i;
 2468         const struct sysctlnode *pnode;
 2469         struct sysctllog *log;
 2470 
 2471         if (node->sysctl_flags & CTLFLAG_PERMANENT)
 2472                 return (0);
 2473 
 2474         if (logp == NULL)
 2475                 return (0);
 2476 
 2477         if (*logp == NULL) {
 2478                 log = malloc(sizeof(struct sysctllog),
 2479                        M_SYSCTLDATA, M_WAITOK|M_CANFAIL);
 2480                 if (log == NULL) {
 2481                         /* XXX print error message? */
 2482                         return (-1);
 2483                 }
 2484                 log->log_num = malloc(16 * sizeof(int),
 2485                        M_SYSCTLDATA, M_WAITOK|M_CANFAIL);
 2486                 if (log->log_num == NULL) {
 2487                         /* XXX print error message? */
 2488                         free(log, M_SYSCTLDATA);
 2489                         return (-1);
 2490                 }
 2491                 memset(log->log_num, 0, 16 * sizeof(int));
 2492                 log->log_root = NULL;
 2493                 log->log_size = 16;
 2494                 log->log_left = 16;
 2495                 *logp = log;
 2496         } else
 2497                 log = *logp;
 2498 
 2499         /*
 2500          * check that the root is proper.  it's okay to record the
 2501          * address of the root of a tree.  it's the only thing that's
 2502          * guaranteed not to shift around as nodes come and go.
 2503          */
 2504         if (log->log_root == NULL)
 2505                 log->log_root = sysctl_rootof(node);
 2506         else if (log->log_root != sysctl_rootof(node)) {
 2507                 printf("sysctl: log %p root mismatch (%p)\n",
 2508                        log->log_root, sysctl_rootof(node));
 2509                 return (-1);
 2510         }
 2511 
 2512         /*
 2513          * we will copy out name in reverse order
 2514          */
 2515         for (pnode = node, namelen = 0;
 2516              pnode != NULL && !(pnode->sysctl_flags & CTLFLAG_ROOT);
 2517              pnode = pnode->sysctl_parent)
 2518                 name[namelen++] = pnode->sysctl_num;
 2519 
 2520         /*
 2521          * do we have space?
 2522          */
 2523         if (log->log_left < (namelen + 3))
 2524                 sysctl_log_realloc(log);
 2525         if (log->log_left < (namelen + 3))
 2526                 return (-1);
 2527 
 2528         /*
 2529          * stuff name in, then namelen, then node type, and finally,
 2530          * the version for non-node nodes.
 2531          */
 2532         for (i = 0; i < namelen; i++)
 2533                 log->log_num[--log->log_left] = name[i];
 2534         log->log_num[--log->log_left] = namelen;
 2535         log->log_num[--log->log_left] = SYSCTL_TYPE(node->sysctl_flags);
 2536         if (log->log_num[log->log_left] != CTLTYPE_NODE)
 2537                 log->log_num[--log->log_left] = node->sysctl_ver;
 2538         else
 2539                 log->log_num[--log->log_left] = 0;
 2540 
 2541         return (0);
 2542 }
 2543 
 2544 void
 2545 sysctl_teardown(struct sysctllog **logp)
 2546 {
 2547         const struct sysctlnode *rnode;
 2548         struct sysctlnode node;
 2549         struct sysctllog *log;
 2550         uint namelen;
 2551         int *name, t, v, error, ni;
 2552         size_t sz;
 2553 
 2554         if (logp == NULL || *logp == NULL)
 2555                 return;
 2556         log = *logp;
 2557 
 2558         error = sysctl_lock(NULL, NULL, 0);
 2559         if (error)
 2560                 return;
 2561 
 2562         memset(&node, 0, sizeof(node));
 2563 
 2564         while (log->log_left < log->log_size) {
 2565                 KASSERT((log->log_left + 3 < log->log_size) &&
 2566                         (log->log_left + log->log_num[log->log_left + 2] <=
 2567                          log->log_size));
 2568                 v = log->log_num[log->log_left++];
 2569                 t = log->log_num[log->log_left++];
 2570                 namelen = log->log_num[log->log_left++];
 2571                 name = &log->log_num[log->log_left];
 2572 
 2573                 node.sysctl_num = name[namelen - 1];
 2574                 node.sysctl_flags = SYSCTL_VERSION|t;
 2575                 node.sysctl_ver = v;
 2576 
 2577                 rnode = log->log_root;
 2578                 error = sysctl_locate(NULL, &name[0], namelen, &rnode, &ni);
 2579                 if (error == 0) {
 2580                         name[namelen - 1] = CTL_DESTROY;
 2581                         rnode = rnode->sysctl_parent;
 2582                         sz = 0;
 2583                         (void)sysctl_destroy(&name[namelen - 1], 1, NULL,
 2584                                              &sz, &node, sizeof(node),
 2585                                              &name[0], NULL, rnode);
 2586                 }
 2587 
 2588                 log->log_left += namelen;
 2589         }
 2590 
 2591         KASSERT(log->log_size == log->log_left);
 2592         free(log->log_num, M_SYSCTLDATA);
 2593         free(log, M_SYSCTLDATA);
 2594         *logp = NULL;
 2595 
 2596         sysctl_unlock(NULL);
 2597 }
 2598 
 2599 /*
 2600  * ********************************************************************
 2601  * old_sysctl -- A routine to bridge old-style internal calls to the
 2602  * new infrastructure.
 2603  * ********************************************************************
 2604  */
 2605 int
 2606 old_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
 2607            void *newp, size_t newlen, struct lwp *l)
 2608 {
 2609         int error;
 2610         size_t oldlen = 0;
 2611         size_t savelen;
 2612 
 2613         if (oldlenp) {
 2614                 oldlen = *oldlenp;
 2615         }
 2616         savelen = oldlen;
 2617 
 2618         error = sysctl_lock(l, oldp, savelen);
 2619         if (error)
 2620                 return (error);
 2621         error = sysctl_dispatch(name, namelen, oldp, &oldlen,
 2622                                 newp, newlen, name, l, NULL);
 2623         sysctl_unlock(l);
 2624         if (error == 0 && oldp != NULL && savelen < oldlen)
 2625                 error = ENOMEM;
 2626 
 2627         if (oldlenp) {
 2628                 *oldlenp = oldlen;
 2629         }
 2630 
 2631         return (error);
 2632 }
 2633 
 2634 /*
 2635  * ********************************************************************
 2636  * Section 4: Generic helper routines
 2637  * ********************************************************************
 2638  * "helper" routines that can do more finely grained access control,
 2639  * construct structures from disparate information, create the
 2640  * appearance of more nodes and sub-trees, etc.  for example, if
 2641  * CTL_PROC wanted a helper function, it could respond to a CTL_QUERY
 2642  * with a dynamically created list of nodes that represented the
 2643  * currently running processes at that instant.
 2644  * ********************************************************************
 2645  */
 2646 
 2647 /*
 2648  * first, a few generic helpers that provide:
 2649  *
 2650  * sysctl_needfunc()            a readonly interface that emits a warning
 2651  * sysctl_notavail()            returns EOPNOTSUPP (generic error)
 2652  * sysctl_null()                an empty return buffer with no error
 2653  */
 2654 int
 2655 sysctl_needfunc(SYSCTLFN_ARGS)
 2656 {
 2657         int error;
 2658 
 2659         printf("!!SYSCTL_NEEDFUNC!!\n");
 2660 
 2661         if (newp != NULL || namelen != 0)
 2662                 return (EOPNOTSUPP);
 2663 
 2664         error = 0;
 2665         if (oldp != NULL)
 2666                 error = sysctl_copyout(l, rnode->sysctl_data, oldp,
 2667                                        MIN(rnode->sysctl_size, *oldlenp));
 2668         *oldlenp = rnode->sysctl_size;
 2669 
 2670         return (error);
 2671 }
 2672 
 2673 int
 2674 sysctl_notavail(SYSCTLFN_ARGS)
 2675 {
 2676 
 2677         if (namelen == 1 && name[0] == CTL_QUERY)
 2678                 return (sysctl_query(SYSCTLFN_CALL(rnode)));
 2679 
 2680         return (EOPNOTSUPP);
 2681 }
 2682 
 2683 int
 2684 sysctl_null(SYSCTLFN_ARGS)
 2685 {
 2686 
 2687         *oldlenp = 0;
 2688 
 2689         return (0);
 2690 }
 2691 
 2692 /*
 2693  * ********************************************************************
 2694  * Section 5: The machinery that makes it all go
 2695  * ********************************************************************
 2696  * Memory "manglement" routines.  Not much to this, eh?
 2697  * ********************************************************************
 2698  */
 2699 static int
 2700 sysctl_alloc(struct sysctlnode *p, int x)
 2701 {
 2702         int i;
 2703         struct sysctlnode *n;
 2704 
 2705         assert(p->sysctl_child == NULL);
 2706 
 2707         if (x == 1)
 2708                 n = malloc(sizeof(struct sysctlnode),
 2709                        M_SYSCTLNODE, M_WAITOK|M_CANFAIL);
 2710         else
 2711                 n = malloc(SYSCTL_DEFSIZE * sizeof(struct sysctlnode),
 2712                        M_SYSCTLNODE, M_WAITOK|M_CANFAIL);
 2713         if (n == NULL)
 2714                 return (ENOMEM);
 2715 
 2716         if (x == 1) {
 2717                 memset(n, 0, sizeof(struct sysctlnode));
 2718                 p->sysctl_csize = 1;
 2719         } else {
 2720                 memset(n, 0, SYSCTL_DEFSIZE * sizeof(struct sysctlnode));
 2721                 p->sysctl_csize = SYSCTL_DEFSIZE;
 2722         }
 2723         p->sysctl_clen = 0;
 2724 
 2725         for (i = 0; i < p->sysctl_csize; i++)
 2726                 n[i].sysctl_parent = p;
 2727 
 2728         p->sysctl_child = n;
 2729         return (0);
 2730 }
 2731 
 2732 static int
 2733 sysctl_realloc(struct sysctlnode *p)
 2734 {
 2735         int i, j;
 2736         struct sysctlnode *n;
 2737 
 2738         assert(p->sysctl_csize == p->sysctl_clen);
 2739 
 2740         /*
 2741          * how many do we have...how many should we make?
 2742          */
 2743         i = p->sysctl_clen;
 2744         n = malloc(2 * i * sizeof(struct sysctlnode), M_SYSCTLNODE,
 2745                    M_WAITOK|M_CANFAIL);
 2746         if (n == NULL)
 2747                 return (ENOMEM);
 2748 
 2749         /*
 2750          * move old children over...initialize new children
 2751          */
 2752         memcpy(n, p->sysctl_child, i * sizeof(struct sysctlnode));
 2753         memset(&n[i], 0, i * sizeof(struct sysctlnode));
 2754         p->sysctl_csize = 2 * i;
 2755 
 2756         /*
 2757          * reattach moved (and new) children to parent; if a moved
 2758          * child node has children, reattach the parent pointers of
 2759          * grandchildren
 2760          */
 2761         for (i = 0; i < p->sysctl_csize; i++) {
 2762                 n[i].sysctl_parent = p;
 2763                 if (n[i].sysctl_child != NULL) {
 2764                         for (j = 0; j < n[i].sysctl_csize; j++)
 2765                                 n[i].sysctl_child[j].sysctl_parent = &n[i];
 2766                 }
 2767         }
 2768 
 2769         /*
 2770          * get out with the old and in with the new
 2771          */
 2772         free(p->sysctl_child, M_SYSCTLNODE);
 2773         p->sysctl_child = n;
 2774 
 2775         return (0);
 2776 }
 2777 
 2778 static int
 2779 sysctl_log_realloc(struct sysctllog *log)
 2780 {
 2781         int *n, s, d;
 2782 
 2783         s = log->log_size * 2;
 2784         d = log->log_size;
 2785 
 2786         n = malloc(s * sizeof(int), M_SYSCTLDATA, M_WAITOK|M_CANFAIL);
 2787         if (n == NULL)
 2788                 return (-1);
 2789 
 2790         memset(n, 0, s * sizeof(int));
 2791         memcpy(&n[d], log->log_num, d * sizeof(int));
 2792         free(log->log_num, M_SYSCTLDATA);
 2793         log->log_num = n;
 2794         if (d)
 2795                 log->log_left += d;
 2796         else
 2797                 log->log_left = s;
 2798         log->log_size = s;
 2799 
 2800         return (0);
 2801 }
 2802 
 2803 /*
 2804  * ********************************************************************
 2805  * Section 6: Conversion between API versions wrt the sysctlnode
 2806  * ********************************************************************
 2807  */
 2808 static int
 2809 sysctl_cvt_in(struct lwp *l, int *vp, const void *i, size_t sz,
 2810               struct sysctlnode *node)
 2811 {
 2812         int error, flags;
 2813 
 2814         if (i == NULL || sz < sizeof(flags))
 2815                 return (EINVAL);
 2816 
 2817         error = sysctl_copyin(l, i, &flags, sizeof(flags));
 2818         if (error)
 2819                 return (error);
 2820 
 2821 #if (SYSCTL_VERSION != SYSCTL_VERS_1)
 2822 #error sysctl_cvt_in: no support for SYSCTL_VERSION
 2823 #endif /*  (SYSCTL_VERSION != SYSCTL_VERS_1) */
 2824 
 2825         if (sz == sizeof(*node) &&
 2826             SYSCTL_VERS(flags) == SYSCTL_VERSION) {
 2827                 error = sysctl_copyin(l, i, node, sizeof(*node));
 2828                 if (error)
 2829                         return (error);
 2830                 *vp = SYSCTL_VERSION;
 2831                 return (0);
 2832         }
 2833 
 2834         return (EINVAL);
 2835 }
 2836 
 2837 static int
 2838 sysctl_cvt_out(struct lwp *l, int v, const struct sysctlnode *i,
 2839                void *ovp, size_t left, size_t *szp)
 2840 {
 2841         size_t sz = sizeof(*i);
 2842         const void *src = i;
 2843         int error;
 2844 
 2845         switch (v) {
 2846         case SYSCTL_VERS_0:
 2847                 return (EINVAL);
 2848 
 2849 #if (SYSCTL_VERSION != SYSCTL_VERS_1)
 2850 #error sysctl_cvt_out: no support for SYSCTL_VERSION
 2851 #endif /*  (SYSCTL_VERSION != SYSCTL_VERS_1) */
 2852 
 2853         case SYSCTL_VERSION:
 2854                 /* nothing more to do here */
 2855                 break;
 2856         }
 2857 
 2858         if (ovp != NULL && left >= sz) {
 2859                 error = sysctl_copyout(l, src, ovp, sz);
 2860                 if (error)
 2861                         return (error);
 2862         }
 2863 
 2864         if (szp != NULL)
 2865                 *szp = sz;
 2866 
 2867         return (0);
 2868 }

Cache object: 9a300669c0ef210aca9ca541bb68701c


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