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  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: 40040f57591d1774943034fa9a576de4


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