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


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

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

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

    1 /*      $OpenBSD: kern_sysctl.c,v 1.411 2023/01/22 12:05:44 mvs Exp $   */
    2 /*      $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $     */
    3 
    4 /*-
    5  * Copyright (c) 1982, 1986, 1989, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * This code is derived from software contributed to Berkeley by
    9  * Mike Karels at Berkeley Software Design, Inc.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  *      @(#)kern_sysctl.c       8.4 (Berkeley) 4/14/94
   36  */
   37 
   38 /*
   39  * sysctl system call.
   40  */
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/malloc.h>
   46 #include <sys/pool.h>
   47 #include <sys/proc.h>
   48 #include <sys/resourcevar.h>
   49 #include <sys/signalvar.h>
   50 #include <sys/fcntl.h>
   51 #include <sys/file.h>
   52 #include <sys/filedesc.h>
   53 #include <sys/vnode.h>
   54 #include <sys/unistd.h>
   55 #include <sys/buf.h>
   56 #include <sys/clockintr.h>
   57 #include <sys/tty.h>
   58 #include <sys/disklabel.h>
   59 #include <sys/disk.h>
   60 #include <sys/sysctl.h>
   61 #include <sys/msgbuf.h>
   62 #include <sys/vmmeter.h>
   63 #include <sys/namei.h>
   64 #include <sys/exec.h>
   65 #include <sys/mbuf.h>
   66 #include <sys/percpu.h>
   67 #include <sys/sensors.h>
   68 #include <sys/pipe.h>
   69 #include <sys/eventvar.h>
   70 #include <sys/socketvar.h>
   71 #include <sys/socket.h>
   72 #include <sys/domain.h>
   73 #include <sys/protosw.h>
   74 #include <sys/pledge.h>
   75 #include <sys/timetc.h>
   76 #include <sys/evcount.h>
   77 #include <sys/un.h>
   78 #include <sys/unpcb.h>
   79 #include <sys/sched.h>
   80 #include <sys/mount.h>
   81 #include <sys/syscallargs.h>
   82 #include <sys/wait.h>
   83 #include <sys/witness.h>
   84 
   85 #include <uvm/uvm_extern.h>
   86 
   87 #include <dev/cons.h>
   88 
   89 #include <net/route.h>
   90 #include <netinet/in.h>
   91 #include <netinet/ip.h>
   92 #include <netinet/ip_var.h>
   93 #include <netinet/in_pcb.h>
   94 #include <netinet/ip6.h>
   95 #include <netinet/tcp.h>
   96 #include <netinet/tcp_timer.h>
   97 #include <netinet/tcp_var.h>
   98 #include <netinet/udp.h>
   99 #include <netinet/udp_var.h>
  100 #include <netinet6/ip6_var.h>
  101 
  102 #ifdef DDB
  103 #include <ddb/db_var.h>
  104 #endif
  105 
  106 #ifdef SYSVMSG
  107 #include <sys/msg.h>
  108 #endif
  109 #ifdef SYSVSEM
  110 #include <sys/sem.h>
  111 #endif
  112 #ifdef SYSVSHM
  113 #include <sys/shm.h>
  114 #endif
  115 
  116 #include "audio.h"
  117 #include "dt.h"
  118 #include "pf.h"
  119 #include "video.h"
  120 
  121 extern struct forkstat forkstat;
  122 extern struct nchstats nchstats;
  123 extern int fscale;
  124 extern fixpt_t ccpu;
  125 extern long numvnodes;
  126 extern int allowdt;
  127 extern int audio_record_enable;
  128 extern int video_record_enable;
  129 extern int autoconf_serial;
  130 
  131 int allowkmem;
  132 
  133 int sysctl_diskinit(int, struct proc *);
  134 int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *);
  135 int sysctl_proc_cwd(int *, u_int, void *, size_t *, struct proc *);
  136 int sysctl_proc_nobroadcastkill(int *, u_int, void *, size_t, void *, size_t *,
  137         struct proc *);
  138 int sysctl_proc_vmmap(int *, u_int, void *, size_t *, struct proc *);
  139 int sysctl_intrcnt(int *, u_int, void *, size_t *);
  140 int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t);
  141 int sysctl_cptime2(int *, u_int, void *, size_t *, void *, size_t);
  142 int sysctl_audio(int *, u_int, void *, size_t *, void *, size_t);
  143 int sysctl_video(int *, u_int, void *, size_t *, void *, size_t);
  144 int sysctl_cpustats(int *, u_int, void *, size_t *, void *, size_t);
  145 int sysctl_utc_offset(void *, size_t *, void *, size_t);
  146 
  147 void fill_file(struct kinfo_file *, struct file *, struct filedesc *, int,
  148     struct vnode *, struct process *, struct proc *, struct socket *, int);
  149 void fill_kproc(struct process *, struct kinfo_proc *, struct proc *, int);
  150 
  151 int (*cpu_cpuspeed)(int *);
  152 
  153 /*
  154  * Lock to avoid too many processes vslocking a large amount of memory
  155  * at the same time.
  156  */
  157 struct rwlock sysctl_lock = RWLOCK_INITIALIZER("sysctllk");
  158 struct rwlock sysctl_disklock = RWLOCK_INITIALIZER("sysctldlk");
  159 
  160 int
  161 sys_sysctl(struct proc *p, void *v, register_t *retval)
  162 {
  163         struct sys_sysctl_args /* {
  164                 syscallarg(const int *) name;
  165                 syscallarg(u_int) namelen;
  166                 syscallarg(void *) old;
  167                 syscallarg(size_t *) oldlenp;
  168                 syscallarg(void *) new;
  169                 syscallarg(size_t) newlen;
  170         } */ *uap = v;
  171         int error, dolock = 1;
  172         size_t savelen = 0, oldlen = 0;
  173         sysctlfn *fn;
  174         int name[CTL_MAXNAME];
  175 
  176         if (SCARG(uap, new) != NULL &&
  177             (error = suser(p)))
  178                 return (error);
  179         /*
  180          * all top-level sysctl names are non-terminal
  181          */
  182         if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2)
  183                 return (EINVAL);
  184         error = copyin(SCARG(uap, name), name,
  185                        SCARG(uap, namelen) * sizeof(int));
  186         if (error)
  187                 return (error);
  188 
  189         error = pledge_sysctl(p, SCARG(uap, namelen),
  190             name, SCARG(uap, new));
  191         if (error)
  192                 return (error);
  193 
  194         switch (name[0]) {
  195         case CTL_KERN:
  196                 fn = kern_sysctl;
  197                 break;
  198         case CTL_HW:
  199                 fn = hw_sysctl;
  200                 break;
  201         case CTL_VM:
  202                 fn = uvm_sysctl;
  203                 break;
  204         case CTL_NET:
  205                 fn = net_sysctl;
  206                 break;
  207         case CTL_FS:
  208                 fn = fs_sysctl;
  209                 break;
  210         case CTL_VFS:
  211                 fn = vfs_sysctl;
  212                 break;
  213         case CTL_MACHDEP:
  214                 fn = cpu_sysctl;
  215                 break;
  216 #ifdef DEBUG_SYSCTL
  217         case CTL_DEBUG:
  218                 fn = debug_sysctl;
  219                 break;
  220 #endif
  221 #ifdef DDB
  222         case CTL_DDB:
  223                 fn = ddb_sysctl;
  224                 break;
  225 #endif
  226         default:
  227                 return (EOPNOTSUPP);
  228         }
  229 
  230         if (SCARG(uap, oldlenp) &&
  231             (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
  232                 return (error);
  233         if (SCARG(uap, old) != NULL) {
  234                 if ((error = rw_enter(&sysctl_lock, RW_WRITE|RW_INTR)) != 0)
  235                         return (error);
  236                 if (dolock) {
  237                         if (atop(oldlen) > uvmexp.wiredmax - uvmexp.wired) {
  238                                 rw_exit_write(&sysctl_lock);
  239                                 return (ENOMEM);
  240                         }
  241                         error = uvm_vslock(p, SCARG(uap, old), oldlen,
  242                             PROT_READ | PROT_WRITE);
  243                         if (error) {
  244                                 rw_exit_write(&sysctl_lock);
  245                                 return (error);
  246                         }
  247                 }
  248                 savelen = oldlen;
  249         }
  250         error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old),
  251             &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
  252         if (SCARG(uap, old) != NULL) {
  253                 if (dolock)
  254                         uvm_vsunlock(p, SCARG(uap, old), savelen);
  255                 rw_exit_write(&sysctl_lock);
  256         }
  257         if (error)
  258                 return (error);
  259         if (SCARG(uap, oldlenp))
  260                 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen));
  261         return (error);
  262 }
  263 
  264 /*
  265  * Attributes stored in the kernel.
  266  */
  267 char hostname[MAXHOSTNAMELEN];
  268 int hostnamelen;
  269 char domainname[MAXHOSTNAMELEN];
  270 int domainnamelen;
  271 long hostid;
  272 char *disknames = NULL;
  273 size_t disknameslen;
  274 struct diskstats *diskstats = NULL;
  275 size_t diskstatslen;
  276 int securelevel;
  277 
  278 /* morally const values reported by sysctl_bounded_arr */
  279 static int arg_max = ARG_MAX;
  280 static int openbsd = OpenBSD;
  281 static int posix_version = _POSIX_VERSION;
  282 static int ngroups_max = NGROUPS_MAX;
  283 static int int_zero = 0;
  284 static int int_one = 1;
  285 static int maxpartitions = MAXPARTITIONS;
  286 static int raw_part = RAW_PART;
  287 
  288 extern int somaxconn, sominconn;
  289 extern int nosuidcoredump;
  290 extern int maxlocksperuid;
  291 extern int uvm_wxabort;
  292 extern int global_ptrace;
  293 
  294 const struct sysctl_bounded_args kern_vars[] = {
  295         {KERN_OSREV, &openbsd, SYSCTL_INT_READONLY},
  296         {KERN_MAXVNODES, &maxvnodes, 0, INT_MAX},
  297         {KERN_MAXPROC, &maxprocess, 0, INT_MAX},
  298         {KERN_MAXFILES, &maxfiles, 0, INT_MAX},
  299         {KERN_NFILES, &numfiles, SYSCTL_INT_READONLY},
  300         {KERN_TTYCOUNT, &tty_count, SYSCTL_INT_READONLY},
  301         {KERN_ARGMAX, &arg_max, SYSCTL_INT_READONLY},
  302         {KERN_POSIX1, &posix_version, SYSCTL_INT_READONLY},
  303         {KERN_NGROUPS, &ngroups_max, SYSCTL_INT_READONLY},
  304         {KERN_JOB_CONTROL, &int_one, SYSCTL_INT_READONLY},
  305         {KERN_SAVED_IDS, &int_one, SYSCTL_INT_READONLY},
  306         {KERN_MAXPARTITIONS, &maxpartitions, SYSCTL_INT_READONLY},
  307         {KERN_RAWPARTITION, &raw_part, SYSCTL_INT_READONLY},
  308         {KERN_MAXTHREAD, &maxthread, 0, INT_MAX},
  309         {KERN_NTHREADS, &nthreads, SYSCTL_INT_READONLY},
  310         {KERN_SOMAXCONN, &somaxconn, 0, SHRT_MAX},
  311         {KERN_SOMINCONN, &sominconn, 0, SHRT_MAX},
  312         {KERN_NOSUIDCOREDUMP, &nosuidcoredump, 0, 3},
  313         {KERN_FSYNC, &int_one, SYSCTL_INT_READONLY},
  314         {KERN_SYSVMSG,
  315 #ifdef SYSVMSG
  316          &int_one,
  317 #else
  318          &int_zero,
  319 #endif
  320          SYSCTL_INT_READONLY},
  321         {KERN_SYSVSEM,
  322 #ifdef SYSVSEM
  323          &int_one,
  324 #else
  325          &int_zero,
  326 #endif
  327          SYSCTL_INT_READONLY},
  328         {KERN_SYSVSHM,
  329 #ifdef SYSVSHM
  330          &int_one,
  331 #else
  332          &int_zero,
  333 #endif
  334          SYSCTL_INT_READONLY},
  335         {KERN_FSCALE, &fscale, SYSCTL_INT_READONLY},
  336         {KERN_CCPU, &ccpu, SYSCTL_INT_READONLY},
  337         {KERN_NPROCS, &nprocesses, SYSCTL_INT_READONLY},
  338         {KERN_SPLASSERT, &splassert_ctl, 0, 3},
  339         {KERN_MAXLOCKSPERUID, &maxlocksperuid, 0, INT_MAX},
  340         {KERN_WXABORT, &uvm_wxabort, 0, 1},
  341         {KERN_NETLIVELOCKS, &int_zero, SYSCTL_INT_READONLY},
  342 #ifdef PTRACE
  343         {KERN_GLOBAL_PTRACE, &global_ptrace, 0, 1},
  344 #endif
  345         {KERN_AUTOCONF_SERIAL, &autoconf_serial, SYSCTL_INT_READONLY},
  346 };
  347 
  348 int
  349 kern_sysctl_dirs(int top_name, int *name, u_int namelen,
  350     void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p)
  351 {
  352         switch (top_name) {
  353 #ifndef SMALL_KERNEL
  354         case KERN_PROC:
  355                 return (sysctl_doproc(name, namelen, oldp, oldlenp));
  356         case KERN_PROC_ARGS:
  357                 return (sysctl_proc_args(name, namelen, oldp, oldlenp, p));
  358         case KERN_PROC_CWD:
  359                 return (sysctl_proc_cwd(name, namelen, oldp, oldlenp, p));
  360         case KERN_PROC_NOBROADCASTKILL:
  361                 return (sysctl_proc_nobroadcastkill(name, namelen,
  362                      newp, newlen, oldp, oldlenp, p));
  363         case KERN_PROC_VMMAP:
  364                 return (sysctl_proc_vmmap(name, namelen, oldp, oldlenp, p));
  365         case KERN_FILE:
  366                 return (sysctl_file(name, namelen, oldp, oldlenp, p));
  367 #endif
  368 #if defined(GPROF) || defined(DDBPROF)
  369         case KERN_PROF:
  370                 return (sysctl_doprof(name, namelen, oldp, oldlenp,
  371                     newp, newlen));
  372 #endif
  373         case KERN_MALLOCSTATS:
  374                 return (sysctl_malloc(name, namelen, oldp, oldlenp,
  375                     newp, newlen, p));
  376         case KERN_TTY:
  377                 return (sysctl_tty(name, namelen, oldp, oldlenp,
  378                     newp, newlen));
  379         case KERN_POOL:
  380                 return (sysctl_dopool(name, namelen, oldp, oldlenp));
  381 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
  382         case KERN_SYSVIPC_INFO:
  383                 return (sysctl_sysvipc(name, namelen, oldp, oldlenp));
  384 #endif
  385 #ifdef SYSVSEM
  386         case KERN_SEMINFO:
  387                 return (sysctl_sysvsem(name, namelen, oldp, oldlenp,
  388                     newp, newlen));
  389 #endif
  390 #ifdef SYSVSHM
  391         case KERN_SHMINFO:
  392                 return (sysctl_sysvshm(name, namelen, oldp, oldlenp,
  393                     newp, newlen));
  394 #endif
  395 #ifndef SMALL_KERNEL
  396         case KERN_INTRCNT:
  397                 return (sysctl_intrcnt(name, namelen, oldp, oldlenp));
  398         case KERN_WATCHDOG:
  399                 return (sysctl_wdog(name, namelen, oldp, oldlenp,
  400                     newp, newlen));
  401 #endif
  402 #ifndef SMALL_KERNEL
  403         case KERN_EVCOUNT:
  404                 return (evcount_sysctl(name, namelen, oldp, oldlenp,
  405                     newp, newlen));
  406 #endif
  407         case KERN_TIMECOUNTER:
  408                 return (sysctl_tc(name, namelen, oldp, oldlenp, newp, newlen));
  409         case KERN_CPTIME2:
  410                 return (sysctl_cptime2(name, namelen, oldp, oldlenp,
  411                     newp, newlen));
  412 #ifdef WITNESS
  413         case KERN_WITNESSWATCH:
  414                 return witness_sysctl_watch(oldp, oldlenp, newp, newlen);
  415         case KERN_WITNESS:
  416                 return witness_sysctl(name, namelen, oldp, oldlenp,
  417                     newp, newlen);
  418 #endif
  419 #if NAUDIO > 0
  420         case KERN_AUDIO:
  421                 return (sysctl_audio(name, namelen, oldp, oldlenp,
  422                     newp, newlen));
  423 #endif
  424 #if NVIDEO > 0
  425         case KERN_VIDEO:
  426                 return (sysctl_video(name, namelen, oldp, oldlenp,
  427                     newp, newlen));
  428 #endif
  429         case KERN_CPUSTATS:
  430                 return (sysctl_cpustats(name, namelen, oldp, oldlenp,
  431                     newp, newlen));
  432 #ifdef __HAVE_CLOCKINTR
  433         case KERN_CLOCKINTR:
  434                 return sysctl_clockintr(name, namelen, oldp, oldlenp, newp,
  435                     newlen);
  436 #endif
  437         default:
  438                 return (ENOTDIR);       /* overloaded */
  439         }
  440 }
  441 
  442 /*
  443  * kernel related system variables.
  444  */
  445 int
  446 kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
  447     size_t newlen, struct proc *p)
  448 {
  449         int error, level, inthostid, stackgap;
  450         dev_t dev;
  451         extern int pool_debug;
  452 
  453         /* dispatch the non-terminal nodes first */
  454         if (namelen != 1) {
  455                 return kern_sysctl_dirs(name[0], name + 1, namelen - 1,
  456                     oldp, oldlenp, newp, newlen, p);
  457         }
  458 
  459         switch (name[0]) {
  460         case KERN_OSTYPE:
  461                 return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
  462         case KERN_OSRELEASE:
  463                 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
  464         case KERN_OSVERSION:
  465                 return (sysctl_rdstring(oldp, oldlenp, newp, osversion));
  466         case KERN_VERSION:
  467                 return (sysctl_rdstring(oldp, oldlenp, newp, version));
  468         case KERN_NUMVNODES:  /* XXX numvnodes is a long */
  469                 return (sysctl_rdint(oldp, oldlenp, newp, numvnodes));
  470         case KERN_SECURELVL:
  471                 level = securelevel;
  472                 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
  473                     newp == NULL)
  474                         return (error);
  475                 if ((securelevel > 0 || level < -1) &&
  476                     level < securelevel && p->p_p->ps_pid != 1)
  477                         return (EPERM);
  478                 securelevel = level;
  479                 return (0);
  480 #if NDT > 0
  481         case KERN_ALLOWDT:
  482                 return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen,
  483                     &allowdt));
  484 #endif
  485         case KERN_ALLOWKMEM:
  486                 return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen,
  487                     &allowkmem));
  488         case KERN_HOSTNAME:
  489                 error = sysctl_tstring(oldp, oldlenp, newp, newlen,
  490                     hostname, sizeof(hostname));
  491                 if (newp && !error)
  492                         hostnamelen = newlen;
  493                 return (error);
  494         case KERN_DOMAINNAME:
  495                 if (securelevel >= 1 && domainnamelen && newp)
  496                         error = EPERM;
  497                 else
  498                         error = sysctl_tstring(oldp, oldlenp, newp, newlen,
  499                             domainname, sizeof(domainname));
  500                 if (newp && !error)
  501                         domainnamelen = newlen;
  502                 return (error);
  503         case KERN_HOSTID:
  504                 inthostid = hostid;  /* XXX assumes sizeof long <= sizeof int */
  505                 error =  sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
  506                 hostid = inthostid;
  507                 return (error);
  508         case KERN_CLOCKRATE:
  509                 return (sysctl_clockrate(oldp, oldlenp, newp));
  510         case KERN_BOOTTIME: {
  511                 struct timeval bt;
  512                 memset(&bt, 0, sizeof bt);
  513                 microboottime(&bt);
  514                 return (sysctl_rdstruct(oldp, oldlenp, newp, &bt, sizeof bt));
  515           }
  516         case KERN_MBSTAT: {
  517                 extern struct cpumem *mbstat;
  518                 uint64_t counters[MBSTAT_COUNT];
  519                 struct mbstat mbs;
  520                 unsigned int i;
  521 
  522                 memset(&mbs, 0, sizeof(mbs));
  523                 counters_read(mbstat, counters, MBSTAT_COUNT);
  524                 for (i = 0; i < MBSTAT_TYPES; i++)
  525                         mbs.m_mtypes[i] = counters[i];
  526 
  527                 mbs.m_drops = counters[MBSTAT_DROPS];
  528                 mbs.m_wait = counters[MBSTAT_WAIT];
  529                 mbs.m_drain = counters[MBSTAT_DRAIN];
  530 
  531                 return (sysctl_rdstruct(oldp, oldlenp, newp,
  532                     &mbs, sizeof(mbs)));
  533         }
  534         case KERN_MSGBUFSIZE:
  535         case KERN_CONSBUFSIZE: {
  536                 struct msgbuf *mp;
  537                 mp = (name[0] == KERN_MSGBUFSIZE) ? msgbufp : consbufp;
  538                 /*
  539                  * deal with cases where the message buffer has
  540                  * become corrupted.
  541                  */
  542                 if (!mp || mp->msg_magic != MSG_MAGIC)
  543                         return (ENXIO);
  544                 return (sysctl_rdint(oldp, oldlenp, newp, mp->msg_bufs));
  545         }
  546         case KERN_CONSBUF:
  547                 if ((error = suser(p)))
  548                         return (error);
  549                 /* FALLTHROUGH */
  550         case KERN_MSGBUF: {
  551                 struct msgbuf *mp;
  552                 mp = (name[0] == KERN_MSGBUF) ? msgbufp : consbufp;
  553                 /* see note above */
  554                 if (!mp || mp->msg_magic != MSG_MAGIC)
  555                         return (ENXIO);
  556                 return (sysctl_rdstruct(oldp, oldlenp, newp, mp,
  557                     mp->msg_bufs + offsetof(struct msgbuf, msg_bufc)));
  558         }
  559         case KERN_CPTIME:
  560         {
  561                 CPU_INFO_ITERATOR cii;
  562                 struct cpu_info *ci;
  563                 long cp_time[CPUSTATES];
  564                 int i, n = 0;
  565 
  566                 memset(cp_time, 0, sizeof(cp_time));
  567 
  568                 CPU_INFO_FOREACH(cii, ci) {
  569                         if (!cpu_is_online(ci))
  570                                 continue;
  571                         n++;
  572                         for (i = 0; i < CPUSTATES; i++)
  573                                 cp_time[i] += ci->ci_schedstate.spc_cp_time[i];
  574                 }
  575 
  576                 for (i = 0; i < CPUSTATES; i++)
  577                         cp_time[i] /= n;
  578 
  579                 return (sysctl_rdstruct(oldp, oldlenp, newp, &cp_time,
  580                     sizeof(cp_time)));
  581         }
  582         case KERN_NCHSTATS:
  583                 return (sysctl_rdstruct(oldp, oldlenp, newp, &nchstats,
  584                     sizeof(struct nchstats)));
  585         case KERN_FORKSTAT:
  586                 return (sysctl_rdstruct(oldp, oldlenp, newp, &forkstat,
  587                     sizeof(struct forkstat)));
  588         case KERN_STACKGAPRANDOM:
  589                 stackgap = stackgap_random;
  590                 error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap);
  591                 if (error)
  592                         return (error);
  593                 /*
  594                  * Safety harness.
  595                  */
  596                 if ((stackgap < ALIGNBYTES && stackgap != 0) ||
  597                     !powerof2(stackgap) || stackgap >= MAXSSIZ)
  598                         return (EINVAL);
  599                 stackgap_random = stackgap;
  600                 return (0);
  601         case KERN_MAXCLUSTERS: {
  602                 int val = nmbclust;
  603                 error = sysctl_int(oldp, oldlenp, newp, newlen, &val);
  604                 if (error == 0 && val != nmbclust)
  605                         error = nmbclust_update(val);
  606                 return (error);
  607         }
  608         case KERN_CACHEPCT: {
  609                 u_int64_t dmapages;
  610                 int opct, pgs;
  611                 opct = bufcachepercent;
  612                 error = sysctl_int(oldp, oldlenp, newp, newlen,
  613                     &bufcachepercent);
  614                 if (error)
  615                         return(error);
  616                 if (bufcachepercent > 90 || bufcachepercent < 5) {
  617                         bufcachepercent = opct;
  618                         return (EINVAL);
  619                 }
  620                 dmapages = uvm_pagecount(&dma_constraint);
  621                 if (bufcachepercent != opct) {
  622                         pgs = bufcachepercent * dmapages / 100;
  623                         bufadjust(pgs); /* adjust bufpages */
  624                         bufhighpages = bufpages; /* set high water mark */
  625                 }
  626                 return(0);
  627         }
  628         case KERN_CONSDEV:
  629                 if (cn_tab != NULL)
  630                         dev = cn_tab->cn_dev;
  631                 else
  632                         dev = NODEV;
  633                 return sysctl_rdstruct(oldp, oldlenp, newp, &dev, sizeof(dev));
  634         case KERN_POOL_DEBUG: {
  635                 int old_pool_debug = pool_debug;
  636 
  637                 error = sysctl_int(oldp, oldlenp, newp, newlen,
  638                     &pool_debug);
  639                 if (error == 0 && pool_debug != old_pool_debug)
  640                         pool_reclaim_all();
  641                 return (error);
  642         }
  643 #if NPF > 0
  644         case KERN_PFSTATUS:
  645                 return (pf_sysctl(oldp, oldlenp, newp, newlen));
  646 #endif
  647         case KERN_TIMEOUT_STATS:
  648                 return (timeout_sysctl(oldp, oldlenp, newp, newlen));
  649         case KERN_UTC_OFFSET:
  650                 return (sysctl_utc_offset(oldp, oldlenp, newp, newlen));
  651         default:
  652                 return (sysctl_bounded_arr(kern_vars, nitems(kern_vars), name,
  653                     namelen, oldp, oldlenp, newp, newlen));
  654         }
  655         /* NOTREACHED */
  656 }
  657 
  658 /*
  659  * hardware related system variables.
  660  */
  661 char *hw_vendor, *hw_prod, *hw_uuid, *hw_serial, *hw_ver;
  662 int allowpowerdown = 1;
  663 int hw_power = 1;
  664 
  665 /* morally const values reported by sysctl_bounded_arr */
  666 static int byte_order = BYTE_ORDER;
  667 static int page_size = PAGE_SIZE;
  668 
  669 const struct sysctl_bounded_args hw_vars[] = {
  670         {HW_NCPU, &ncpus, SYSCTL_INT_READONLY},
  671         {HW_NCPUFOUND, &ncpusfound, SYSCTL_INT_READONLY},
  672         {HW_BYTEORDER, &byte_order, SYSCTL_INT_READONLY},
  673         {HW_PAGESIZE, &page_size, SYSCTL_INT_READONLY},
  674         {HW_DISKCOUNT, &disk_count, SYSCTL_INT_READONLY},
  675         {HW_POWER, &hw_power, SYSCTL_INT_READONLY},
  676 };
  677 
  678 int
  679 hw_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
  680     size_t newlen, struct proc *p)
  681 {
  682         extern char machine[], cpu_model[];
  683         int err, cpuspeed;
  684 
  685         /* all sysctl names at this level except sensors are terminal */
  686         if (name[0] != HW_SENSORS && namelen != 1)
  687                 return (ENOTDIR);               /* overloaded */
  688 
  689         switch (name[0]) {
  690         case HW_MACHINE:
  691                 return (sysctl_rdstring(oldp, oldlenp, newp, machine));
  692         case HW_MODEL:
  693                 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
  694         case HW_NCPUONLINE:
  695                 return (sysctl_rdint(oldp, oldlenp, newp,
  696                     sysctl_hwncpuonline()));
  697         case HW_PHYSMEM:
  698                 return (sysctl_rdint(oldp, oldlenp, newp, ptoa(physmem)));
  699         case HW_USERMEM:
  700                 return (sysctl_rdint(oldp, oldlenp, newp,
  701                     ptoa(physmem - uvmexp.wired)));
  702         case HW_DISKNAMES:
  703                 err = sysctl_diskinit(0, p);
  704                 if (err)
  705                         return err;
  706                 if (disknames)
  707                         return (sysctl_rdstring(oldp, oldlenp, newp,
  708                             disknames));
  709                 else
  710                         return (sysctl_rdstring(oldp, oldlenp, newp, ""));
  711         case HW_DISKSTATS:
  712                 err = sysctl_diskinit(1, p);
  713                 if (err)
  714                         return err;
  715                 return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats,
  716                     disk_count * sizeof(struct diskstats)));
  717         case HW_CPUSPEED:
  718                 if (!cpu_cpuspeed)
  719                         return (EOPNOTSUPP);
  720                 err = cpu_cpuspeed(&cpuspeed);
  721                 if (err)
  722                         return err;
  723                 return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed));
  724 #ifndef SMALL_KERNEL
  725         case HW_SENSORS:
  726                 return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp,
  727                     newp, newlen));
  728         case HW_SETPERF:
  729                 return (sysctl_hwsetperf(oldp, oldlenp, newp, newlen));
  730         case HW_PERFPOLICY:
  731                 return (sysctl_hwperfpolicy(oldp, oldlenp, newp, newlen));
  732 #endif /* !SMALL_KERNEL */
  733         case HW_VENDOR:
  734                 if (hw_vendor)
  735                         return (sysctl_rdstring(oldp, oldlenp, newp,
  736                             hw_vendor));
  737                 else
  738                         return (EOPNOTSUPP);
  739         case HW_PRODUCT:
  740                 if (hw_prod)
  741                         return (sysctl_rdstring(oldp, oldlenp, newp, hw_prod));
  742                 else
  743                         return (EOPNOTSUPP);
  744         case HW_VERSION:
  745                 if (hw_ver)
  746                         return (sysctl_rdstring(oldp, oldlenp, newp, hw_ver));
  747                 else
  748                         return (EOPNOTSUPP);
  749         case HW_SERIALNO:
  750                 if (hw_serial)
  751                         return (sysctl_rdstring(oldp, oldlenp, newp,
  752                             hw_serial));
  753                 else
  754                         return (EOPNOTSUPP);
  755         case HW_UUID:
  756                 if (hw_uuid)
  757                         return (sysctl_rdstring(oldp, oldlenp, newp, hw_uuid));
  758                 else
  759                         return (EOPNOTSUPP);
  760         case HW_PHYSMEM64:
  761                 return (sysctl_rdquad(oldp, oldlenp, newp,
  762                     ptoa((psize_t)physmem)));
  763         case HW_USERMEM64:
  764                 return (sysctl_rdquad(oldp, oldlenp, newp,
  765                     ptoa((psize_t)physmem - uvmexp.wired)));
  766         case HW_ALLOWPOWERDOWN:
  767                 return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen,
  768                     &allowpowerdown));
  769 #ifdef __HAVE_CPU_TOPOLOGY
  770         case HW_SMT:
  771                 return (sysctl_hwsmt(oldp, oldlenp, newp, newlen));
  772 #endif
  773         default:
  774                 return sysctl_bounded_arr(hw_vars, nitems(hw_vars), name,
  775                     namelen, oldp, oldlenp, newp, newlen);
  776         }
  777         /* NOTREACHED */
  778 }
  779 
  780 #ifdef DEBUG_SYSCTL
  781 /*
  782  * Debugging related system variables.
  783  */
  784 extern struct ctldebug debug_vfs_busyprt;
  785 struct ctldebug debug1, debug2, debug3, debug4;
  786 struct ctldebug debug5, debug6, debug7, debug8, debug9;
  787 struct ctldebug debug10, debug11, debug12, debug13, debug14;
  788 struct ctldebug debug15, debug16, debug17, debug18, debug19;
  789 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
  790         &debug_vfs_busyprt,
  791         &debug1, &debug2, &debug3, &debug4,
  792         &debug5, &debug6, &debug7, &debug8, &debug9,
  793         &debug10, &debug11, &debug12, &debug13, &debug14,
  794         &debug15, &debug16, &debug17, &debug18, &debug19,
  795 };
  796 int
  797 debug_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
  798     size_t newlen, struct proc *p)
  799 {
  800         struct ctldebug *cdp;
  801 
  802         /* all sysctl names at this level are name and field */
  803         if (namelen != 2)
  804                 return (ENOTDIR);               /* overloaded */
  805         if (name[0] < 0 || name[0] >= nitems(debugvars))
  806                 return (EOPNOTSUPP);
  807         cdp = debugvars[name[0]];
  808         if (cdp->debugname == 0)
  809                 return (EOPNOTSUPP);
  810         switch (name[1]) {
  811         case CTL_DEBUG_NAME:
  812                 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
  813         case CTL_DEBUG_VALUE:
  814                 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
  815         default:
  816                 return (EOPNOTSUPP);
  817         }
  818         /* NOTREACHED */
  819 }
  820 #endif /* DEBUG_SYSCTL */
  821 
  822 /*
  823  * Reads, or writes that lower the value
  824  */
  825 int
  826 sysctl_int_lower(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
  827     int *valp)
  828 {
  829         unsigned int oval = *valp, val = *valp;
  830         int error;
  831 
  832         if (newp == NULL)
  833                 return (sysctl_rdint(oldp, oldlenp, newp, val));
  834 
  835         if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val)))
  836                 return (error);
  837         if (val > oval)
  838                 return (EPERM);         /* do not allow raising */
  839         *(unsigned int *)valp = val;
  840         return (0);
  841 }
  842 
  843 /*
  844  * Validate parameters and get old / set new parameters
  845  * for an integer-valued sysctl function.
  846  */
  847 int
  848 sysctl_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp)
  849 {
  850         int error = 0;
  851 
  852         if (oldp && *oldlenp < sizeof(int))
  853                 return (ENOMEM);
  854         if (newp && newlen != sizeof(int))
  855                 return (EINVAL);
  856         *oldlenp = sizeof(int);
  857         if (oldp)
  858                 error = copyout(valp, oldp, sizeof(int));
  859         if (error == 0 && newp)
  860                 error = copyin(newp, valp, sizeof(int));
  861         return (error);
  862 }
  863 
  864 /*
  865  * As above, but read-only.
  866  */
  867 int
  868 sysctl_rdint(void *oldp, size_t *oldlenp, void *newp, int val)
  869 {
  870         int error = 0;
  871 
  872         if (oldp && *oldlenp < sizeof(int))
  873                 return (ENOMEM);
  874         if (newp)
  875                 return (EPERM);
  876         *oldlenp = sizeof(int);
  877         if (oldp)
  878                 error = copyout((caddr_t)&val, oldp, sizeof(int));
  879         return (error);
  880 }
  881 
  882 /*
  883  * Selects between sysctl_rdint and sysctl_int according to securelevel.
  884  */
  885 int
  886 sysctl_securelevel_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
  887     int *valp)
  888 {
  889         if (securelevel > 0)
  890                 return (sysctl_rdint(oldp, oldlenp, newp, *valp));
  891         return (sysctl_int(oldp, oldlenp, newp, newlen, valp));
  892 }
  893 
  894 /*
  895  * Read-only or bounded integer values.
  896  */
  897 int
  898 sysctl_int_bounded(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
  899     int *valp, int minimum, int maximum)
  900 {
  901         int val = *valp;
  902         int error;
  903 
  904         /* read only */
  905         if (newp == NULL || minimum > maximum)
  906                 return (sysctl_rdint(oldp, oldlenp, newp, val));
  907 
  908         if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val)))
  909                 return (error);
  910         /* outside limits */
  911         if (val < minimum || maximum < val)
  912                 return (EINVAL);
  913         *valp = val;
  914         return (0);
  915 }
  916 
  917 /*
  918  * Array of read-only or bounded integer values.
  919  */
  920 int
  921 sysctl_bounded_arr(const struct sysctl_bounded_args *valpp, u_int valplen,
  922     int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
  923     size_t newlen)
  924 {
  925         u_int i;
  926         if (namelen != 1)
  927                 return (ENOTDIR);
  928         for (i = 0; i < valplen; ++i) {
  929                 if (valpp[i].mib == name[0]) {
  930                         return (sysctl_int_bounded(oldp, oldlenp, newp, newlen,
  931                             valpp[i].var, valpp[i].minimum, valpp[i].maximum));
  932                 }
  933         }
  934         return (EOPNOTSUPP);
  935 }
  936 
  937 /*
  938  * Validate parameters and get old / set new parameters
  939  * for an integer-valued sysctl function.
  940  */
  941 int
  942 sysctl_quad(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
  943     int64_t *valp)
  944 {
  945         int error = 0;
  946 
  947         if (oldp && *oldlenp < sizeof(int64_t))
  948                 return (ENOMEM);
  949         if (newp && newlen != sizeof(int64_t))
  950                 return (EINVAL);
  951         *oldlenp = sizeof(int64_t);
  952         if (oldp)
  953                 error = copyout(valp, oldp, sizeof(int64_t));
  954         if (error == 0 && newp)
  955                 error = copyin(newp, valp, sizeof(int64_t));
  956         return (error);
  957 }
  958 
  959 /*
  960  * As above, but read-only.
  961  */
  962 int
  963 sysctl_rdquad(void *oldp, size_t *oldlenp, void *newp, int64_t val)
  964 {
  965         int error = 0;
  966 
  967         if (oldp && *oldlenp < sizeof(int64_t))
  968                 return (ENOMEM);
  969         if (newp)
  970                 return (EPERM);
  971         *oldlenp = sizeof(int64_t);
  972         if (oldp)
  973                 error = copyout((caddr_t)&val, oldp, sizeof(int64_t));
  974         return (error);
  975 }
  976 
  977 /*
  978  * Validate parameters and get old / set new parameters
  979  * for a string-valued sysctl function.
  980  */
  981 int
  982 sysctl_string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, char *str,
  983     size_t maxlen)
  984 {
  985         return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0);
  986 }
  987 
  988 int
  989 sysctl_tstring(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
  990     char *str, size_t maxlen)
  991 {
  992         return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1);
  993 }
  994 
  995 int
  996 sysctl__string(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
  997     char *str, size_t maxlen, int trunc)
  998 {
  999         size_t len;
 1000         int error = 0;
 1001 
 1002         len = strlen(str) + 1;
 1003         if (oldp && *oldlenp < len) {
 1004                 if (trunc == 0 || *oldlenp == 0)
 1005                         return (ENOMEM);
 1006         }
 1007         if (newp && newlen >= maxlen)
 1008                 return (EINVAL);
 1009         if (oldp) {
 1010                 if (trunc && *oldlenp < len) {
 1011                         len = *oldlenp;
 1012                         error = copyout(str, oldp, len - 1);
 1013                         if (error == 0)
 1014                                 error = copyout("", (char *)oldp + len - 1, 1);
 1015                 } else {
 1016                         error = copyout(str, oldp, len);
 1017                 }
 1018         }
 1019         *oldlenp = len;
 1020         if (error == 0 && newp) {
 1021                 error = copyin(newp, str, newlen);
 1022                 str[newlen] = 0;
 1023         }
 1024         return (error);
 1025 }
 1026 
 1027 /*
 1028  * As above, but read-only.
 1029  */
 1030 int
 1031 sysctl_rdstring(void *oldp, size_t *oldlenp, void *newp, const char *str)
 1032 {
 1033         size_t len;
 1034         int error = 0;
 1035 
 1036         len = strlen(str) + 1;
 1037         if (oldp && *oldlenp < len)
 1038                 return (ENOMEM);
 1039         if (newp)
 1040                 return (EPERM);
 1041         *oldlenp = len;
 1042         if (oldp)
 1043                 error = copyout(str, oldp, len);
 1044         return (error);
 1045 }
 1046 
 1047 /*
 1048  * Validate parameters and get old / set new parameters
 1049  * for a structure oriented sysctl function.
 1050  */
 1051 int
 1052 sysctl_struct(void *oldp, size_t *oldlenp, void *newp, size_t newlen, void *sp,
 1053     size_t len)
 1054 {
 1055         int error = 0;
 1056 
 1057         if (oldp && *oldlenp < len)
 1058                 return (ENOMEM);
 1059         if (newp && newlen > len)
 1060                 return (EINVAL);
 1061         if (oldp) {
 1062                 *oldlenp = len;
 1063                 error = copyout(sp, oldp, len);
 1064         }
 1065         if (error == 0 && newp)
 1066                 error = copyin(newp, sp, len);
 1067         return (error);
 1068 }
 1069 
 1070 /*
 1071  * Validate parameters and get old parameters
 1072  * for a structure oriented sysctl function.
 1073  */
 1074 int
 1075 sysctl_rdstruct(void *oldp, size_t *oldlenp, void *newp, const void *sp,
 1076     size_t len)
 1077 {
 1078         int error = 0;
 1079 
 1080         if (oldp && *oldlenp < len)
 1081                 return (ENOMEM);
 1082         if (newp)
 1083                 return (EPERM);
 1084         *oldlenp = len;
 1085         if (oldp)
 1086                 error = copyout(sp, oldp, len);
 1087         return (error);
 1088 }
 1089 
 1090 #ifndef SMALL_KERNEL
 1091 void
 1092 fill_file(struct kinfo_file *kf, struct file *fp, struct filedesc *fdp,
 1093           int fd, struct vnode *vp, struct process *pr, struct proc *p,
 1094           struct socket *so, int show_pointers)
 1095 {
 1096         struct vattr va;
 1097 
 1098         memset(kf, 0, sizeof(*kf));
 1099 
 1100         kf->fd_fd = fd;         /* might not really be an fd */
 1101 
 1102         if (fp != NULL) {
 1103                 if (show_pointers)
 1104                         kf->f_fileaddr = PTRTOINT64(fp);
 1105                 kf->f_flag = fp->f_flag;
 1106                 kf->f_iflags = fp->f_iflags;
 1107                 kf->f_type = fp->f_type;
 1108                 kf->f_count = fp->f_count;
 1109                 if (show_pointers)
 1110                         kf->f_ucred = PTRTOINT64(fp->f_cred);
 1111                 kf->f_uid = fp->f_cred->cr_uid;
 1112                 kf->f_gid = fp->f_cred->cr_gid;
 1113                 if (show_pointers)
 1114                         kf->f_ops = PTRTOINT64(fp->f_ops);
 1115                 if (show_pointers)
 1116                         kf->f_data = PTRTOINT64(fp->f_data);
 1117                 kf->f_usecount = 0;
 1118 
 1119                 if (suser(p) == 0 || p->p_ucred->cr_uid == fp->f_cred->cr_uid) {
 1120                         mtx_enter(&fp->f_mtx);
 1121                         kf->f_offset = fp->f_offset;
 1122                         kf->f_rxfer = fp->f_rxfer;
 1123                         kf->f_rwfer = fp->f_wxfer;
 1124                         kf->f_seek = fp->f_seek;
 1125                         kf->f_rbytes = fp->f_rbytes;
 1126                         kf->f_wbytes = fp->f_wbytes;
 1127                         mtx_leave(&fp->f_mtx);
 1128                 } else
 1129                         kf->f_offset = -1;
 1130         } else if (vp != NULL) {
 1131                 /* fake it */
 1132                 kf->f_type = DTYPE_VNODE;
 1133                 kf->f_flag = FREAD;
 1134                 if (fd == KERN_FILE_TRACE)
 1135                         kf->f_flag |= FWRITE;
 1136         } else if (so != NULL) {
 1137                 /* fake it */
 1138                 kf->f_type = DTYPE_SOCKET;
 1139         }
 1140 
 1141         /* information about the object associated with this file */
 1142         switch (kf->f_type) {
 1143         case DTYPE_VNODE:
 1144                 if (fp != NULL)
 1145                         vp = (struct vnode *)fp->f_data;
 1146 
 1147                 if (show_pointers)
 1148                         kf->v_un = PTRTOINT64(vp->v_un.vu_socket);
 1149                 kf->v_type = vp->v_type;
 1150                 kf->v_tag = vp->v_tag;
 1151                 kf->v_flag = vp->v_flag;
 1152                 if (show_pointers)
 1153                         kf->v_data = PTRTOINT64(vp->v_data);
 1154                 if (show_pointers)
 1155                         kf->v_mount = PTRTOINT64(vp->v_mount);
 1156                 if (vp->v_mount)
 1157                         strlcpy(kf->f_mntonname,
 1158                             vp->v_mount->mnt_stat.f_mntonname,
 1159                             sizeof(kf->f_mntonname));
 1160 
 1161                 if (VOP_GETATTR(vp, &va, p->p_ucred, p) == 0) {
 1162                         kf->va_fileid = va.va_fileid;
 1163                         kf->va_mode = MAKEIMODE(va.va_type, va.va_mode);
 1164                         kf->va_size = va.va_size;
 1165                         kf->va_rdev = va.va_rdev;
 1166                         kf->va_fsid = va.va_fsid & 0xffffffff;
 1167                         kf->va_nlink = va.va_nlink;
 1168                 }
 1169                 break;
 1170 
 1171         case DTYPE_SOCKET: {
 1172                 int locked = 0;
 1173 
 1174                 if (so == NULL) {
 1175                         so = (struct socket *)fp->f_data;
 1176                         /* if so is passed as parameter it is already locked */
 1177                         switch (so->so_proto->pr_domain->dom_family) {
 1178                         case AF_INET:
 1179                         case AF_INET6:
 1180                                 NET_LOCK();
 1181                                 locked = 1;
 1182                                 break;
 1183                         }
 1184                 }
 1185 
 1186                 kf->so_type = so->so_type;
 1187                 kf->so_state = so->so_state | so->so_snd.sb_state |
 1188                     so->so_rcv.sb_state;
 1189                 if (show_pointers)
 1190                         kf->so_pcb = PTRTOINT64(so->so_pcb);
 1191                 else
 1192                         kf->so_pcb = -1;
 1193                 kf->so_protocol = so->so_proto->pr_protocol;
 1194                 kf->so_family = so->so_proto->pr_domain->dom_family;
 1195                 kf->so_rcv_cc = so->so_rcv.sb_cc;
 1196                 kf->so_snd_cc = so->so_snd.sb_cc;
 1197                 if (isspliced(so)) {
 1198                         if (show_pointers)
 1199                                 kf->so_splice =
 1200                                     PTRTOINT64(so->so_sp->ssp_socket);
 1201                         kf->so_splicelen = so->so_sp->ssp_len;
 1202                 } else if (issplicedback(so))
 1203                         kf->so_splicelen = -1;
 1204                 if (so->so_pcb == NULL) {
 1205                         if (locked)
 1206                                 NET_UNLOCK();
 1207                         break;
 1208                 }
 1209                 switch (kf->so_family) {
 1210                 case AF_INET: {
 1211                         struct inpcb *inpcb = so->so_pcb;
 1212 
 1213                         NET_ASSERT_LOCKED();
 1214                         if (show_pointers)
 1215                                 kf->inp_ppcb = PTRTOINT64(inpcb->inp_ppcb);
 1216                         kf->inp_lport = inpcb->inp_lport;
 1217                         kf->inp_laddru[0] = inpcb->inp_laddr.s_addr;
 1218                         kf->inp_fport = inpcb->inp_fport;
 1219                         kf->inp_faddru[0] = inpcb->inp_faddr.s_addr;
 1220                         kf->inp_rtableid = inpcb->inp_rtableid;
 1221                         if (so->so_type == SOCK_RAW)
 1222                                 kf->inp_proto = inpcb->inp_ip.ip_p;
 1223                         if (so->so_proto->pr_protocol == IPPROTO_TCP) {
 1224                                 struct tcpcb *tcpcb = (void *)inpcb->inp_ppcb;
 1225                                 kf->t_rcv_wnd = tcpcb->rcv_wnd;
 1226                                 kf->t_snd_wnd = tcpcb->snd_wnd;
 1227                                 kf->t_snd_cwnd = tcpcb->snd_cwnd;
 1228                                 kf->t_state = tcpcb->t_state;
 1229                         }
 1230                         break;
 1231                     }
 1232                 case AF_INET6: {
 1233                         struct inpcb *inpcb = so->so_pcb;
 1234 
 1235                         NET_ASSERT_LOCKED();
 1236                         if (show_pointers)
 1237                                 kf->inp_ppcb = PTRTOINT64(inpcb->inp_ppcb);
 1238                         kf->inp_lport = inpcb->inp_lport;
 1239                         kf->inp_laddru[0] = inpcb->inp_laddr6.s6_addr32[0];
 1240                         kf->inp_laddru[1] = inpcb->inp_laddr6.s6_addr32[1];
 1241                         kf->inp_laddru[2] = inpcb->inp_laddr6.s6_addr32[2];
 1242                         kf->inp_laddru[3] = inpcb->inp_laddr6.s6_addr32[3];
 1243                         kf->inp_fport = inpcb->inp_fport;
 1244                         kf->inp_faddru[0] = inpcb->inp_faddr6.s6_addr32[0];
 1245                         kf->inp_faddru[1] = inpcb->inp_faddr6.s6_addr32[1];
 1246                         kf->inp_faddru[2] = inpcb->inp_faddr6.s6_addr32[2];
 1247                         kf->inp_faddru[3] = inpcb->inp_faddr6.s6_addr32[3];
 1248                         kf->inp_rtableid = inpcb->inp_rtableid;
 1249                         if (so->so_type == SOCK_RAW)
 1250                                 kf->inp_proto = inpcb->inp_ipv6.ip6_nxt;
 1251                         if (so->so_proto->pr_protocol == IPPROTO_TCP) {
 1252                                 struct tcpcb *tcpcb = (void *)inpcb->inp_ppcb;
 1253                                 kf->t_rcv_wnd = tcpcb->rcv_wnd;
 1254                                 kf->t_snd_wnd = tcpcb->snd_wnd;
 1255                                 kf->t_state = tcpcb->t_state;
 1256                         }
 1257                         break;
 1258                     }
 1259                 case AF_UNIX: {
 1260                         struct unpcb *unpcb = so->so_pcb;
 1261 
 1262                         kf->f_msgcount = unpcb->unp_msgcount;
 1263                         if (show_pointers) {
 1264                                 kf->unp_conn    = PTRTOINT64(unpcb->unp_conn);
 1265                                 kf->unp_refs    = PTRTOINT64(
 1266                                     SLIST_FIRST(&unpcb->unp_refs));
 1267                                 kf->unp_nextref = PTRTOINT64(
 1268                                     SLIST_NEXT(unpcb, unp_nextref));
 1269                                 kf->v_un        = PTRTOINT64(unpcb->unp_vnode);
 1270                                 kf->unp_addr    = PTRTOINT64(unpcb->unp_addr);
 1271                         }
 1272                         if (unpcb->unp_addr != NULL) {
 1273                                 struct sockaddr_un *un = mtod(unpcb->unp_addr,
 1274                                     struct sockaddr_un *);
 1275                                 memcpy(kf->unp_path, un->sun_path, un->sun_len
 1276                                     - offsetof(struct sockaddr_un,sun_path));
 1277                         }
 1278                         break;
 1279                     }
 1280                 }
 1281                 if (locked)
 1282                         NET_UNLOCK();
 1283                 break;
 1284             }
 1285 
 1286         case DTYPE_PIPE: {
 1287                 struct pipe *pipe = (struct pipe *)fp->f_data;
 1288 
 1289                 if (show_pointers)
 1290                         kf->pipe_peer = PTRTOINT64(pipe->pipe_peer);
 1291                 kf->pipe_state = pipe->pipe_state;
 1292                 break;
 1293             }
 1294 
 1295         case DTYPE_KQUEUE: {
 1296                 struct kqueue *kqi = (struct kqueue *)fp->f_data;
 1297 
 1298                 kf->kq_count = kqi->kq_count;
 1299                 kf->kq_state = kqi->kq_state;
 1300                 break;
 1301             }
 1302         }
 1303 
 1304         /* per-process information for KERN_FILE_BY[PU]ID */
 1305         if (pr != NULL) {
 1306                 kf->p_pid = pr->ps_pid;
 1307                 kf->p_uid = pr->ps_ucred->cr_uid;
 1308                 kf->p_gid = pr->ps_ucred->cr_gid;
 1309                 kf->p_tid = -1;
 1310                 strlcpy(kf->p_comm, pr->ps_comm, sizeof(kf->p_comm));
 1311         }
 1312         if (fdp != NULL) {
 1313                 fdplock(fdp);
 1314                 kf->fd_ofileflags = fdp->fd_ofileflags[fd];
 1315                 fdpunlock(fdp);
 1316         }
 1317 }
 1318 
 1319 /*
 1320  * Get file structures.
 1321  */
 1322 int
 1323 sysctl_file(int *name, u_int namelen, char *where, size_t *sizep,
 1324     struct proc *p)
 1325 {
 1326         struct kinfo_file *kf;
 1327         struct filedesc *fdp;
 1328         struct file *fp;
 1329         struct process *pr;
 1330         size_t buflen, elem_size, elem_count, outsize;
 1331         char *dp = where;
 1332         int arg, i, error = 0, needed = 0, matched;
 1333         u_int op;
 1334         int show_pointers;
 1335 
 1336         if (namelen > 4)
 1337                 return (ENOTDIR);
 1338         if (namelen < 4 || name[2] > sizeof(*kf))
 1339                 return (EINVAL);
 1340 
 1341         buflen = where != NULL ? *sizep : 0;
 1342         op = name[0];
 1343         arg = name[1];
 1344         elem_size = name[2];
 1345         elem_count = name[3];
 1346         outsize = MIN(sizeof(*kf), elem_size);
 1347 
 1348         if (elem_size < 1)
 1349                 return (EINVAL);
 1350 
 1351         show_pointers = suser(curproc) == 0;
 1352 
 1353         kf = malloc(sizeof(*kf), M_TEMP, M_WAITOK);
 1354 
 1355 #define FILLIT2(fp, fdp, i, vp, pr, so) do {                            \
 1356         if (buflen >= elem_size && elem_count > 0) {                    \
 1357                 fill_file(kf, fp, fdp, i, vp, pr, p, so, show_pointers);\
 1358                 error = copyout(kf, dp, outsize);                       \
 1359                 if (error)                                              \
 1360                         break;                                          \
 1361                 dp += elem_size;                                        \
 1362                 buflen -= elem_size;                                    \
 1363                 elem_count--;                                           \
 1364         }                                                               \
 1365         needed += elem_size;                                            \
 1366 } while (0)
 1367 #define FILLIT(fp, fdp, i, vp, pr) \
 1368         FILLIT2(fp, fdp, i, vp, pr, NULL)
 1369 #define FILLSO(so) \
 1370         FILLIT2(NULL, NULL, 0, NULL, NULL, so)
 1371 
 1372         switch (op) {
 1373         case KERN_FILE_BYFILE:
 1374                 /* use the inp-tables to pick up closed connections, too */
 1375                 if (arg == DTYPE_SOCKET) {
 1376                         struct inpcb *inp;
 1377 
 1378                         NET_LOCK();
 1379                         mtx_enter(&tcbtable.inpt_mtx);
 1380                         TAILQ_FOREACH(inp, &tcbtable.inpt_queue, inp_queue)
 1381                                 FILLSO(inp->inp_socket);
 1382                         mtx_leave(&tcbtable.inpt_mtx);
 1383                         mtx_enter(&udbtable.inpt_mtx);
 1384                         TAILQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue)
 1385                                 FILLSO(inp->inp_socket);
 1386                         mtx_leave(&udbtable.inpt_mtx);
 1387                         mtx_enter(&rawcbtable.inpt_mtx);
 1388                         TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue)
 1389                                 FILLSO(inp->inp_socket);
 1390                         mtx_leave(&rawcbtable.inpt_mtx);
 1391 #ifdef INET6
 1392                         mtx_enter(&rawin6pcbtable.inpt_mtx);
 1393                         TAILQ_FOREACH(inp, &rawin6pcbtable.inpt_queue,
 1394                             inp_queue)
 1395                                 FILLSO(inp->inp_socket);
 1396                         mtx_leave(&rawin6pcbtable.inpt_mtx);
 1397 #endif
 1398                         NET_UNLOCK();
 1399                 }
 1400                 fp = NULL;
 1401                 while ((fp = fd_iterfile(fp, p)) != NULL) {
 1402                         if ((arg == 0 || fp->f_type == arg)) {
 1403                                 int af, skip = 0;
 1404                                 if (arg == DTYPE_SOCKET && fp->f_type == arg) {
 1405                                         af = ((struct socket *)fp->f_data)->
 1406                                             so_proto->pr_domain->dom_family;
 1407                                         if (af == AF_INET || af == AF_INET6)
 1408                                                 skip = 1;
 1409                                 }
 1410                                 if (!skip)
 1411                                         FILLIT(fp, NULL, 0, NULL, NULL);
 1412                         }
 1413                 }
 1414                 break;
 1415         case KERN_FILE_BYPID:
 1416                 /* A arg of -1 indicates all processes */
 1417                 if (arg < -1) {
 1418                         error = EINVAL;
 1419                         break;
 1420                 }
 1421                 matched = 0;
 1422                 LIST_FOREACH(pr, &allprocess, ps_list) {
 1423                         /*
 1424                          * skip system, exiting, embryonic and undead
 1425                          * processes
 1426                          */
 1427                         if (pr->ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING))
 1428                                 continue;
 1429                         if (arg > 0 && pr->ps_pid != (pid_t)arg) {
 1430                                 /* not the pid we are looking for */
 1431                                 continue;
 1432                         }
 1433                         matched = 1;
 1434                         fdp = pr->ps_fd;
 1435                         if (pr->ps_textvp)
 1436                                 FILLIT(NULL, NULL, KERN_FILE_TEXT, pr->ps_textvp, pr);
 1437                         if (fdp->fd_cdir)
 1438                                 FILLIT(NULL, NULL, KERN_FILE_CDIR, fdp->fd_cdir, pr);
 1439                         if (fdp->fd_rdir)
 1440                                 FILLIT(NULL, NULL, KERN_FILE_RDIR, fdp->fd_rdir, pr);
 1441                         if (pr->ps_tracevp)
 1442                                 FILLIT(NULL, NULL, KERN_FILE_TRACE, pr->ps_tracevp, pr);
 1443                         for (i = 0; i < fdp->fd_nfiles; i++) {
 1444                                 if ((fp = fd_getfile(fdp, i)) == NULL)
 1445                                         continue;
 1446                                 FILLIT(fp, fdp, i, NULL, pr);
 1447                                 FRELE(fp, p);
 1448                         }
 1449                 }
 1450                 if (!matched)
 1451                         error = ESRCH;
 1452                 break;
 1453         case KERN_FILE_BYUID:
 1454                 LIST_FOREACH(pr, &allprocess, ps_list) {
 1455                         /*
 1456                          * skip system, exiting, embryonic and undead
 1457                          * processes
 1458                          */
 1459                         if (pr->ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING))
 1460                                 continue;
 1461                         if (arg >= 0 && pr->ps_ucred->cr_uid != (uid_t)arg) {
 1462                                 /* not the uid we are looking for */
 1463                                 continue;
 1464                         }
 1465                         fdp = pr->ps_fd;
 1466                         if (fdp->fd_cdir)
 1467                                 FILLIT(NULL, NULL, KERN_FILE_CDIR, fdp->fd_cdir, pr);
 1468                         if (fdp->fd_rdir)
 1469                                 FILLIT(NULL, NULL, KERN_FILE_RDIR, fdp->fd_rdir, pr);
 1470                         if (pr->ps_tracevp)
 1471                                 FILLIT(NULL, NULL, KERN_FILE_TRACE, pr->ps_tracevp, pr);
 1472                         for (i = 0; i < fdp->fd_nfiles; i++) {
 1473                                 if ((fp = fd_getfile(fdp, i)) == NULL)
 1474                                         continue;
 1475                                 FILLIT(fp, fdp, i, NULL, pr);
 1476                                 FRELE(fp, p);
 1477                         }
 1478                 }
 1479                 break;
 1480         default:
 1481                 error = EINVAL;
 1482                 break;
 1483         }
 1484         free(kf, M_TEMP, sizeof(*kf));
 1485 
 1486         if (!error) {
 1487                 if (where == NULL)
 1488                         needed += KERN_FILESLOP * elem_size;
 1489                 else if (*sizep < needed)
 1490                         error = ENOMEM;
 1491                 *sizep = needed;
 1492         }
 1493 
 1494         return (error);
 1495 }
 1496 
 1497 /*
 1498  * try over estimating by 5 procs
 1499  */
 1500 #define KERN_PROCSLOP   5
 1501 
 1502 int
 1503 sysctl_doproc(int *name, u_int namelen, char *where, size_t *sizep)
 1504 {
 1505         struct kinfo_proc *kproc = NULL;
 1506         struct proc *p;
 1507         struct process *pr;
 1508         char *dp;
 1509         int arg, buflen, doingzomb, elem_size, elem_count;
 1510         int error, needed, op;
 1511         int dothreads = 0;
 1512         int show_pointers;
 1513 
 1514         dp = where;
 1515         buflen = where != NULL ? *sizep : 0;
 1516         needed = error = 0;
 1517 
 1518         if (namelen != 4 || name[2] <= 0 || name[3] < 0 ||
 1519             name[2] > sizeof(*kproc))
 1520                 return (EINVAL);
 1521         op = name[0];
 1522         arg = name[1];
 1523         elem_size = name[2];
 1524         elem_count = name[3];
 1525 
 1526         dothreads = op & KERN_PROC_SHOW_THREADS;
 1527         op &= ~KERN_PROC_SHOW_THREADS;
 1528 
 1529         show_pointers = suser(curproc) == 0;
 1530 
 1531         if (where != NULL)
 1532                 kproc = malloc(sizeof(*kproc), M_TEMP, M_WAITOK);
 1533 
 1534         pr = LIST_FIRST(&allprocess);
 1535         doingzomb = 0;
 1536 again:
 1537         for (; pr != NULL; pr = LIST_NEXT(pr, ps_list)) {
 1538                 /* XXX skip processes in the middle of being zapped */
 1539                 if (pr->ps_pgrp == NULL)
 1540                         continue;
 1541 
 1542                 /*
 1543                  * Skip embryonic processes.
 1544                  */
 1545                 if (pr->ps_flags & PS_EMBRYO)
 1546                         continue;
 1547 
 1548                 /*
 1549                  * TODO - make more efficient (see notes below).
 1550                  */
 1551                 switch (op) {
 1552 
 1553                 case KERN_PROC_PID:
 1554                         /* could do this with just a lookup */
 1555                         if (pr->ps_pid != (pid_t)arg)
 1556                                 continue;
 1557                         break;
 1558 
 1559                 case KERN_PROC_PGRP:
 1560                         /* could do this by traversing pgrp */
 1561                         if (pr->ps_pgrp->pg_id != (pid_t)arg)
 1562                                 continue;
 1563                         break;
 1564 
 1565                 case KERN_PROC_SESSION:
 1566                         if (pr->ps_session->s_leader == NULL ||
 1567                             pr->ps_session->s_leader->ps_pid != (pid_t)arg)
 1568                                 continue;
 1569                         break;
 1570 
 1571                 case KERN_PROC_TTY:
 1572                         if ((pr->ps_flags & PS_CONTROLT) == 0 ||
 1573                             pr->ps_session->s_ttyp == NULL ||
 1574                             pr->ps_session->s_ttyp->t_dev != (dev_t)arg)
 1575                                 continue;
 1576                         break;
 1577 
 1578                 case KERN_PROC_UID:
 1579                         if (pr->ps_ucred->cr_uid != (uid_t)arg)
 1580                                 continue;
 1581                         break;
 1582 
 1583                 case KERN_PROC_RUID:
 1584                         if (pr->ps_ucred->cr_ruid != (uid_t)arg)
 1585                                 continue;
 1586                         break;
 1587 
 1588                 case KERN_PROC_ALL:
 1589                         if (pr->ps_flags & PS_SYSTEM)
 1590                                 continue;
 1591                         break;
 1592 
 1593                 case KERN_PROC_KTHREAD:
 1594                         /* no filtering */
 1595                         break;
 1596 
 1597                 default:
 1598                         error = EINVAL;
 1599                         goto err;
 1600                 }
 1601 
 1602                 if (buflen >= elem_size && elem_count > 0) {
 1603                         fill_kproc(pr, kproc, NULL, show_pointers);
 1604                         error = copyout(kproc, dp, elem_size);
 1605                         if (error)
 1606                                 goto err;
 1607                         dp += elem_size;
 1608                         buflen -= elem_size;
 1609                         elem_count--;
 1610                 }
 1611                 needed += elem_size;
 1612 
 1613                 /* Skip per-thread entries if not required by op */
 1614                 if (!dothreads)
 1615                         continue;
 1616 
 1617                 TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) {
 1618                         if (buflen >= elem_size && elem_count > 0) {
 1619                                 fill_kproc(pr, kproc, p, show_pointers);
 1620                                 error = copyout(kproc, dp, elem_size);
 1621                                 if (error)
 1622                                         goto err;
 1623                                 dp += elem_size;
 1624                                 buflen -= elem_size;
 1625                                 elem_count--;
 1626                         }
 1627                         needed += elem_size;
 1628                 }
 1629         }
 1630         if (doingzomb == 0) {
 1631                 pr = LIST_FIRST(&zombprocess);
 1632                 doingzomb++;
 1633                 goto again;
 1634         }
 1635         if (where != NULL) {
 1636                 *sizep = dp - where;
 1637                 if (needed > *sizep) {
 1638                         error = ENOMEM;
 1639                         goto err;
 1640                 }
 1641         } else {
 1642                 needed += KERN_PROCSLOP * elem_size;
 1643                 *sizep = needed;
 1644         }
 1645 err:
 1646         if (kproc)
 1647                 free(kproc, M_TEMP, sizeof(*kproc));
 1648         return (error);
 1649 }
 1650 
 1651 /*
 1652  * Fill in a kproc structure for the specified process.
 1653  */
 1654 void
 1655 fill_kproc(struct process *pr, struct kinfo_proc *ki, struct proc *p,
 1656     int show_pointers)
 1657 {
 1658         struct session *s = pr->ps_session;
 1659         struct tty *tp;
 1660         struct vmspace *vm = pr->ps_vmspace;
 1661         struct timespec booted, st, ut, utc;
 1662         int isthread;
 1663 
 1664         isthread = p != NULL;
 1665         if (!isthread)
 1666                 p = pr->ps_mainproc;            /* XXX */
 1667 
 1668         FILL_KPROC(ki, strlcpy, p, pr, pr->ps_ucred, pr->ps_pgrp,
 1669             p, pr, s, vm, pr->ps_limit, pr->ps_sigacts, isthread,
 1670             show_pointers);
 1671 
 1672         /* stuff that's too painful to generalize into the macros */
 1673         if (pr->ps_pptr)
 1674                 ki->p_ppid = pr->ps_ppid;
 1675         if (s->s_leader)
 1676                 ki->p_sid = s->s_leader->ps_pid;
 1677 
 1678         if ((pr->ps_flags & PS_CONTROLT) && (tp = s->s_ttyp)) {
 1679                 ki->p_tdev = tp->t_dev;
 1680                 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : -1;
 1681                 if (show_pointers)
 1682                         ki->p_tsess = PTRTOINT64(tp->t_session);
 1683         } else {
 1684                 ki->p_tdev = NODEV;
 1685                 ki->p_tpgid = -1;
 1686         }
 1687 
 1688         /* fixups that can only be done in the kernel */
 1689         if ((pr->ps_flags & PS_ZOMBIE) == 0) {
 1690                 if ((pr->ps_flags & PS_EMBRYO) == 0 && vm != NULL)
 1691                         ki->p_vm_rssize = vm_resident_count(vm);
 1692                 calctsru(isthread ? &p->p_tu : &pr->ps_tu, &ut, &st, NULL);
 1693                 ki->p_uutime_sec = ut.tv_sec;
 1694                 ki->p_uutime_usec = ut.tv_nsec/1000;
 1695                 ki->p_ustime_sec = st.tv_sec;
 1696                 ki->p_ustime_usec = st.tv_nsec/1000;
 1697 
 1698                 /* Convert starting uptime to a starting UTC time. */
 1699                 nanoboottime(&booted);
 1700                 timespecadd(&booted, &pr->ps_start, &utc);
 1701                 ki->p_ustart_sec = utc.tv_sec;
 1702                 ki->p_ustart_usec = utc.tv_nsec / 1000;
 1703 
 1704 #ifdef MULTIPROCESSOR
 1705                 if (p->p_cpu != NULL)
 1706                         ki->p_cpuid = CPU_INFO_UNIT(p->p_cpu);
 1707 #endif
 1708         }
 1709 
 1710         /* get %cpu and schedule state: just one thread or sum of all? */
 1711         if (isthread) {
 1712                 ki->p_pctcpu = p->p_pctcpu;
 1713                 ki->p_stat   = p->p_stat;
 1714         } else {
 1715                 ki->p_pctcpu = 0;
 1716                 ki->p_stat = (pr->ps_flags & PS_ZOMBIE) ? SDEAD : SIDL;
 1717                 TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) {
 1718                         ki->p_pctcpu += p->p_pctcpu;
 1719                         /* find best state: ONPROC > RUN > STOP > SLEEP > .. */
 1720                         if (p->p_stat == SONPROC || ki->p_stat == SONPROC)
 1721                                 ki->p_stat = SONPROC;
 1722                         else if (p->p_stat == SRUN || ki->p_stat == SRUN)
 1723                                 ki->p_stat = SRUN;
 1724                         else if (p->p_stat == SSTOP || ki->p_stat == SSTOP)
 1725                                 ki->p_stat = SSTOP;
 1726                         else if (p->p_stat == SSLEEP)
 1727                                 ki->p_stat = SSLEEP;
 1728                 }
 1729         }
 1730 }
 1731 
 1732 int
 1733 sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp,
 1734     struct proc *cp)
 1735 {
 1736         struct process *vpr;
 1737         pid_t pid;
 1738         struct ps_strings pss;
 1739         struct iovec iov;
 1740         struct uio uio;
 1741         int error, cnt, op;
 1742         size_t limit;
 1743         char **rargv, **vargv;          /* reader vs. victim */
 1744         char *rarg, *varg, *buf;
 1745         struct vmspace *vm;
 1746         vaddr_t ps_strings;
 1747 
 1748         if (namelen > 2)
 1749                 return (ENOTDIR);
 1750         if (namelen < 2)
 1751                 return (EINVAL);
 1752 
 1753         pid = name[0];
 1754         op = name[1];
 1755 
 1756         switch (op) {
 1757         case KERN_PROC_ARGV:
 1758         case KERN_PROC_NARGV:
 1759         case KERN_PROC_ENV:
 1760         case KERN_PROC_NENV:
 1761                 break;
 1762         default:
 1763                 return (EOPNOTSUPP);
 1764         }
 1765 
 1766         if ((vpr = prfind(pid)) == NULL)
 1767                 return (ESRCH);
 1768 
 1769         if (oldp == NULL) {
 1770                 if (op == KERN_PROC_NARGV || op == KERN_PROC_NENV)
 1771                         *oldlenp = sizeof(int);
 1772                 else
 1773                         *oldlenp = ARG_MAX;     /* XXX XXX XXX */
 1774                 return (0);
 1775         }
 1776 
 1777         /* Either system process or exiting/zombie */
 1778         if (vpr->ps_flags & (PS_SYSTEM | PS_EXITING))
 1779                 return (EINVAL);
 1780 
 1781         /* Execing - danger. */
 1782         if ((vpr->ps_flags & PS_INEXEC))
 1783                 return (EBUSY);
 1784 
 1785         /* Only owner or root can get env */
 1786         if ((op == KERN_PROC_NENV || op == KERN_PROC_ENV) &&
 1787             (vpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid &&
 1788             (error = suser(cp)) != 0))
 1789                 return (error);
 1790 
 1791         ps_strings = vpr->ps_strings;
 1792         vm = vpr->ps_vmspace;
 1793         uvmspace_addref(vm);
 1794         vpr = NULL;
 1795 
 1796         buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
 1797 
 1798         iov.iov_base = &pss;
 1799         iov.iov_len = sizeof(pss);
 1800         uio.uio_iov = &iov;
 1801         uio.uio_iovcnt = 1;
 1802         uio.uio_offset = (off_t)ps_strings;
 1803         uio.uio_resid = sizeof(pss);
 1804         uio.uio_segflg = UIO_SYSSPACE;
 1805         uio.uio_rw = UIO_READ;
 1806         uio.uio_procp = cp;
 1807 
 1808         if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0)
 1809                 goto out;
 1810 
 1811         if (op == KERN_PROC_NARGV) {
 1812                 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr);
 1813                 goto out;
 1814         }
 1815         if (op == KERN_PROC_NENV) {
 1816                 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr);
 1817                 goto out;
 1818         }
 1819 
 1820         if (op == KERN_PROC_ARGV) {
 1821                 cnt = pss.ps_nargvstr;
 1822                 vargv = pss.ps_argvstr;
 1823         } else {
 1824                 cnt = pss.ps_nenvstr;
 1825                 vargv = pss.ps_envstr;
 1826         }
 1827 
 1828         /* -1 to have space for a terminating NUL */
 1829         limit = *oldlenp - 1;
 1830         *oldlenp = 0;
 1831 
 1832         rargv = oldp;
 1833 
 1834         /*
 1835          * *oldlenp - number of bytes copied out into readers buffer.
 1836          * limit - maximal number of bytes allowed into readers buffer.
 1837          * rarg - pointer into readers buffer where next arg will be stored.
 1838          * rargv - pointer into readers buffer where the next rarg pointer
 1839          *  will be stored.
 1840          * vargv - pointer into victim address space where the next argument
 1841          *  will be read.
 1842          */
 1843 
 1844         /* space for cnt pointers and a NULL */
 1845         rarg = (char *)(rargv + cnt + 1);
 1846         *oldlenp += (cnt + 1) * sizeof(char **);
 1847 
 1848         while (cnt > 0 && *oldlenp < limit) {
 1849                 size_t len, vstrlen;
 1850 
 1851                 /* Write to readers argv */
 1852                 if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0)
 1853                         goto out;
 1854 
 1855                 /* read the victim argv */
 1856                 iov.iov_base = &varg;
 1857                 iov.iov_len = sizeof(varg);
 1858                 uio.uio_iov = &iov;
 1859                 uio.uio_iovcnt = 1;
 1860                 uio.uio_offset = (off_t)(vaddr_t)vargv;
 1861                 uio.uio_resid = sizeof(varg);
 1862                 uio.uio_segflg = UIO_SYSSPACE;
 1863                 uio.uio_rw = UIO_READ;
 1864                 uio.uio_procp = cp;
 1865                 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0)
 1866                         goto out;
 1867 
 1868                 if (varg == NULL)
 1869                         break;
 1870 
 1871                 /*
 1872                  * read the victim arg. We must jump through hoops to avoid
 1873                  * crossing a page boundary too much and returning an error.
 1874                  */
 1875 more:
 1876                 len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK);
 1877                 /* leave space for the terminating NUL */
 1878                 iov.iov_base = buf;
 1879                 iov.iov_len = len;
 1880                 uio.uio_iov = &iov;
 1881                 uio.uio_iovcnt = 1;
 1882                 uio.uio_offset = (off_t)(vaddr_t)varg;
 1883                 uio.uio_resid = len;
 1884                 uio.uio_segflg = UIO_SYSSPACE;
 1885                 uio.uio_rw = UIO_READ;
 1886                 uio.uio_procp = cp;
 1887                 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0)
 1888                         goto out;
 1889 
 1890                 for (vstrlen = 0; vstrlen < len; vstrlen++) {
 1891                         if (buf[vstrlen] == '\0')
 1892                                 break;
 1893                 }
 1894 
 1895                 /* Don't overflow readers buffer. */
 1896                 if (*oldlenp + vstrlen + 1 >= limit) {
 1897                         error = ENOMEM;
 1898                         goto out;
 1899                 }
 1900 
 1901                 if ((error = copyout(buf, rarg, vstrlen)) != 0)
 1902                         goto out;
 1903 
 1904                 *oldlenp += vstrlen;
 1905                 rarg += vstrlen;
 1906 
 1907                 /* The string didn't end in this page? */
 1908                 if (vstrlen == len) {
 1909                         varg += vstrlen;
 1910                         goto more;
 1911                 }
 1912 
 1913                 /* End of string. Terminate it with a NUL */
 1914                 buf[0] = '\0';
 1915                 if ((error = copyout(buf, rarg, 1)) != 0)
 1916                         goto out;
 1917                 *oldlenp += 1;
 1918                 rarg += 1;
 1919 
 1920                 vargv++;
 1921                 rargv++;
 1922                 cnt--;
 1923         }
 1924 
 1925         if (*oldlenp >= limit) {
 1926                 error = ENOMEM;
 1927                 goto out;
 1928         }
 1929 
 1930         /* Write the terminating null */
 1931         rarg = NULL;
 1932         error = copyout(&rarg, rargv, sizeof(rarg));
 1933 
 1934 out:
 1935         uvmspace_free(vm);
 1936         free(buf, M_TEMP, PAGE_SIZE);
 1937         return (error);
 1938 }
 1939 
 1940 int
 1941 sysctl_proc_cwd(int *name, u_int namelen, void *oldp, size_t *oldlenp,
 1942     struct proc *cp)
 1943 {
 1944         struct process *findpr;
 1945         struct vnode *vp;
 1946         pid_t pid;
 1947         int error;
 1948         size_t lenused, len;
 1949         char *path, *bp, *bend;
 1950 
 1951         if (namelen > 1)
 1952                 return (ENOTDIR);
 1953         if (namelen < 1)
 1954                 return (EINVAL);
 1955 
 1956         pid = name[0];
 1957         if ((findpr = prfind(pid)) == NULL)
 1958                 return (ESRCH);
 1959 
 1960         if (oldp == NULL) {
 1961                 *oldlenp = MAXPATHLEN * 4;
 1962                 return (0);
 1963         }
 1964 
 1965         /* Either system process or exiting/zombie */
 1966         if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING))
 1967                 return (EINVAL);
 1968 
 1969         /* Only owner or root can get cwd */
 1970         if (findpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid &&
 1971             (error = suser(cp)) != 0)
 1972                 return (error);
 1973 
 1974         len = *oldlenp;
 1975         if (len > MAXPATHLEN * 4)
 1976                 len = MAXPATHLEN * 4;
 1977         else if (len < 2)
 1978                 return (ERANGE);
 1979         *oldlenp = 0;
 1980 
 1981         /* snag a reference to the vnode before we can sleep */
 1982         vp = findpr->ps_fd->fd_cdir;
 1983         vref(vp);
 1984 
 1985         path = malloc(len, M_TEMP, M_WAITOK);
 1986 
 1987         bp = &path[len];
 1988         bend = bp;
 1989         *(--bp) = '\0';
 1990 
 1991         /* Same as sys__getcwd */
 1992         error = vfs_getcwd_common(vp, NULL,
 1993             &bp, path, len / 2, GETCWD_CHECK_ACCESS, cp);
 1994         if (error == 0) {
 1995                 *oldlenp = lenused = bend - bp;
 1996                 error = copyout(bp, oldp, lenused);
 1997         }
 1998 
 1999         vrele(vp);
 2000         free(path, M_TEMP, len);
 2001 
 2002         return (error);
 2003 }
 2004 
 2005 int
 2006 sysctl_proc_nobroadcastkill(int *name, u_int namelen, void *newp, size_t newlen,
 2007     void *oldp, size_t *oldlenp, struct proc *cp)
 2008 {
 2009         struct process *findpr;
 2010         pid_t pid;
 2011         int error, flag;
 2012 
 2013         if (namelen > 1)
 2014                 return (ENOTDIR);
 2015         if (namelen < 1)
 2016                 return (EINVAL);
 2017 
 2018         pid = name[0];
 2019         if ((findpr = prfind(pid)) == NULL)
 2020                 return (ESRCH);
 2021 
 2022         /* Either system process or exiting/zombie */
 2023         if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING))
 2024                 return (EINVAL);
 2025 
 2026         /* Only root can change PS_NOBROADCASTKILL */
 2027         if (newp != NULL && (error = suser(cp)) != 0)
 2028                 return (error);
 2029 
 2030         /* get the PS_NOBROADCASTKILL flag */
 2031         flag = findpr->ps_flags & PS_NOBROADCASTKILL ? 1 : 0;
 2032 
 2033         error = sysctl_int(oldp, oldlenp, newp, newlen, &flag);
 2034         if (error == 0 && newp) {
 2035                 if (flag)
 2036                         atomic_setbits_int(&findpr->ps_flags,
 2037                             PS_NOBROADCASTKILL);
 2038                 else
 2039                         atomic_clearbits_int(&findpr->ps_flags,
 2040                             PS_NOBROADCASTKILL);
 2041         }
 2042 
 2043         return (error);
 2044 }
 2045 
 2046 /* Arbitrary but reasonable limit for one iteration. */
 2047 #define VMMAP_MAXLEN    MAXPHYS
 2048 
 2049 int
 2050 sysctl_proc_vmmap(int *name, u_int namelen, void *oldp, size_t *oldlenp,
 2051     struct proc *cp)
 2052 {
 2053         struct process *findpr;
 2054         pid_t pid;
 2055         int error;
 2056         size_t oldlen, len;
 2057         struct kinfo_vmentry *kve, *ukve;
 2058         u_long *ustart, start;
 2059 
 2060         if (namelen > 1)
 2061                 return (ENOTDIR);
 2062         if (namelen < 1)
 2063                 return (EINVAL);
 2064 
 2065         /* Provide max buffer length as hint. */
 2066         if (oldp == NULL) {
 2067                 if (oldlenp == NULL)
 2068                         return (EINVAL);
 2069                 else {
 2070                         *oldlenp = VMMAP_MAXLEN;
 2071                         return (0);
 2072                 }
 2073         }
 2074 
 2075         pid = name[0];
 2076         if (pid == cp->p_p->ps_pid) {
 2077                 /* Self process mapping. */
 2078                 findpr = cp->p_p;
 2079         } else if (pid > 0) {
 2080                 if ((findpr = prfind(pid)) == NULL)
 2081                         return (ESRCH);
 2082 
 2083                 /* Either system process or exiting/zombie */
 2084                 if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING))
 2085                         return (EINVAL);
 2086 
 2087 #if 1
 2088                 /* XXX Allow only root for now */
 2089                 if ((error = suser(cp)) != 0)
 2090                         return (error);
 2091 #else
 2092                 /* Only owner or root can get vmmap */
 2093                 if (findpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid &&
 2094                     (error = suser(cp)) != 0)
 2095                         return (error);
 2096 #endif
 2097         } else {
 2098                 /* Only root can get kernel_map */
 2099                 if ((error = suser(cp)) != 0)
 2100                         return (error);
 2101                 findpr = NULL;
 2102         }
 2103 
 2104         /* Check the given size. */
 2105         oldlen = *oldlenp;
 2106         if (oldlen == 0 || oldlen % sizeof(*kve) != 0)
 2107                 return (EINVAL);
 2108 
 2109         /* Deny huge allocation. */
 2110         if (oldlen > VMMAP_MAXLEN)
 2111                 return (EINVAL);
 2112 
 2113         /*
 2114          * Iterate from the given address passed as the first element's
 2115          * kve_start via oldp.
 2116          */
 2117         ukve = (struct kinfo_vmentry *)oldp;
 2118         ustart = &ukve->kve_start;
 2119         error = copyin(ustart, &start, sizeof(start));
 2120         if (error != 0)
 2121                 return (error);
 2122 
 2123         /* Allocate wired memory to not block. */
 2124         kve = malloc(oldlen, M_TEMP, M_WAITOK);
 2125 
 2126         /* Set the base address and read entries. */
 2127         kve[0].kve_start = start;
 2128         len = oldlen;
 2129         error = fill_vmmap(findpr, kve, &len);
 2130         if (error != 0 && error != ENOMEM)
 2131                 goto done;
 2132         if (len == 0)
 2133                 goto done;
 2134 
 2135         KASSERT(len <= oldlen);
 2136         KASSERT((len % sizeof(struct kinfo_vmentry)) == 0);
 2137 
 2138         error = copyout(kve, oldp, len);
 2139 
 2140 done:
 2141         *oldlenp = len;
 2142 
 2143         free(kve, M_TEMP, oldlen);
 2144 
 2145         return (error);
 2146 }
 2147 #endif
 2148 
 2149 /*
 2150  * Initialize disknames/diskstats for export by sysctl. If update is set,
 2151  * then we simply update the disk statistics information.
 2152  */
 2153 int
 2154 sysctl_diskinit(int update, struct proc *p)
 2155 {
 2156         struct diskstats *sdk;
 2157         struct disk *dk;
 2158         const char *duid;
 2159         int error, changed = 0;
 2160 
 2161         KERNEL_ASSERT_LOCKED();
 2162 
 2163         if ((error = rw_enter(&sysctl_disklock, RW_WRITE|RW_INTR)) != 0)
 2164                 return error;
 2165 
 2166         /* Run in a loop, disks may change while malloc sleeps. */
 2167         while (disk_change) {
 2168                 int tlen;
 2169 
 2170                 disk_change = 0;
 2171 
 2172                 tlen = 0;
 2173                 TAILQ_FOREACH(dk, &disklist, dk_link) {
 2174                         if (dk->dk_name)
 2175                                 tlen += strlen(dk->dk_name);
 2176                         tlen += 18;     /* label uid + separators */
 2177                 }
 2178                 tlen++;
 2179 
 2180                 /*
 2181                  * The sysctl_disklock ensures that no other process can
 2182                  * allocate disknames and diskstats while our malloc sleeps.
 2183                  */
 2184                 free(disknames, M_SYSCTL, disknameslen);
 2185                 free(diskstats, M_SYSCTL, diskstatslen);
 2186                 diskstats = NULL;
 2187                 disknames = NULL;
 2188                 diskstats = mallocarray(disk_count, sizeof(struct diskstats),
 2189                     M_SYSCTL, M_WAITOK|M_ZERO);
 2190                 diskstatslen = disk_count * sizeof(struct diskstats);
 2191                 disknames = malloc(tlen, M_SYSCTL, M_WAITOK|M_ZERO);
 2192                 disknameslen = tlen;
 2193                 disknames[0] = '\0';
 2194                 changed = 1;
 2195         }
 2196 
 2197         if (changed) {
 2198                 int l;
 2199 
 2200                 l = 0;
 2201                 sdk = diskstats;
 2202                 TAILQ_FOREACH(dk, &disklist, dk_link) {
 2203                         duid = NULL;
 2204                         if (dk->dk_label && !duid_iszero(dk->dk_label->d_uid))
 2205                                 duid = duid_format(dk->dk_label->d_uid);
 2206                         snprintf(disknames + l, disknameslen - l, "%s:%s,",
 2207                             dk->dk_name ? dk->dk_name : "",
 2208                             duid ? duid : "");
 2209                         l += strlen(disknames + l);
 2210                         strlcpy(sdk->ds_name, dk->dk_name,
 2211                             sizeof(sdk->ds_name));
 2212                         mtx_enter(&dk->dk_mtx);
 2213                         sdk->ds_busy = dk->dk_busy;
 2214                         sdk->ds_rxfer = dk->dk_rxfer;
 2215                         sdk->ds_wxfer = dk->dk_wxfer;
 2216                         sdk->ds_seek = dk->dk_seek;
 2217                         sdk->ds_rbytes = dk->dk_rbytes;
 2218                         sdk->ds_wbytes = dk->dk_wbytes;
 2219                         sdk->ds_attachtime = dk->dk_attachtime;
 2220                         sdk->ds_timestamp = dk->dk_timestamp;
 2221                         sdk->ds_time = dk->dk_time;
 2222                         mtx_leave(&dk->dk_mtx);
 2223                         sdk++;
 2224                 }
 2225 
 2226                 /* Eliminate trailing comma */
 2227                 if (l != 0)
 2228                         disknames[l - 1] = '\0';
 2229         } else if (update) {
 2230                 /* Just update, number of drives hasn't changed */
 2231                 sdk = diskstats;
 2232                 TAILQ_FOREACH(dk, &disklist, dk_link) {
 2233                         strlcpy(sdk->ds_name, dk->dk_name,
 2234                             sizeof(sdk->ds_name));
 2235                         mtx_enter(&dk->dk_mtx);
 2236                         sdk->ds_busy = dk->dk_busy;
 2237                         sdk->ds_rxfer = dk->dk_rxfer;
 2238                         sdk->ds_wxfer = dk->dk_wxfer;
 2239                         sdk->ds_seek = dk->dk_seek;
 2240                         sdk->ds_rbytes = dk->dk_rbytes;
 2241                         sdk->ds_wbytes = dk->dk_wbytes;
 2242                         sdk->ds_attachtime = dk->dk_attachtime;
 2243                         sdk->ds_timestamp = dk->dk_timestamp;
 2244                         sdk->ds_time = dk->dk_time;
 2245                         mtx_leave(&dk->dk_mtx);
 2246                         sdk++;
 2247                 }
 2248         }
 2249         rw_exit_write(&sysctl_disklock);
 2250         return 0;
 2251 }
 2252 
 2253 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
 2254 int
 2255 sysctl_sysvipc(int *name, u_int namelen, void *where, size_t *sizep)
 2256 {
 2257 #ifdef SYSVSEM
 2258         struct sem_sysctl_info *semsi;
 2259 #endif
 2260 #ifdef SYSVSHM
 2261         struct shm_sysctl_info *shmsi;
 2262 #endif
 2263         size_t infosize, dssize, tsize, buflen, bufsiz;
 2264         int i, nds, error, ret;
 2265         void *buf;
 2266 
 2267         if (namelen != 1)
 2268                 return (EINVAL);
 2269 
 2270         buflen = *sizep;
 2271 
 2272         switch (*name) {
 2273         case KERN_SYSVIPC_MSG_INFO:
 2274 #ifdef SYSVMSG
 2275                 return (sysctl_sysvmsg(name, namelen, where, sizep));
 2276 #else
 2277                 return (EOPNOTSUPP);
 2278 #endif
 2279         case KERN_SYSVIPC_SEM_INFO:
 2280 #ifdef SYSVSEM
 2281                 infosize = sizeof(semsi->seminfo);
 2282                 nds = seminfo.semmni;
 2283                 dssize = sizeof(semsi->semids[0]);
 2284                 break;
 2285 #else
 2286                 return (EOPNOTSUPP);
 2287 #endif
 2288         case KERN_SYSVIPC_SHM_INFO:
 2289 #ifdef SYSVSHM
 2290                 infosize = sizeof(shmsi->shminfo);
 2291                 nds = shminfo.shmmni;
 2292                 dssize = sizeof(shmsi->shmids[0]);
 2293                 break;
 2294 #else
 2295                 return (EOPNOTSUPP);
 2296 #endif
 2297         default:
 2298                 return (EINVAL);
 2299         }
 2300         tsize = infosize + (nds * dssize);
 2301 
 2302         /* Return just the total size required. */
 2303         if (where == NULL) {
 2304                 *sizep = tsize;
 2305                 return (0);
 2306         }
 2307 
 2308         /* Not enough room for even the info struct. */
 2309         if (buflen < infosize) {
 2310                 *sizep = 0;
 2311                 return (ENOMEM);
 2312         }
 2313         bufsiz = min(tsize, buflen);
 2314         buf = malloc(bufsiz, M_TEMP, M_WAITOK|M_ZERO);
 2315 
 2316         switch (*name) {
 2317 #ifdef SYSVSEM
 2318         case KERN_SYSVIPC_SEM_INFO:
 2319                 semsi = (struct sem_sysctl_info *)buf;
 2320                 semsi->seminfo = seminfo;
 2321                 break;
 2322 #endif
 2323 #ifdef SYSVSHM
 2324         case KERN_SYSVIPC_SHM_INFO:
 2325                 shmsi = (struct shm_sysctl_info *)buf;
 2326                 shmsi->shminfo = shminfo;
 2327                 break;
 2328 #endif
 2329         }
 2330         buflen -= infosize;
 2331 
 2332         ret = 0;
 2333         if (buflen > 0) {
 2334                 /* Fill in the IPC data structures.  */
 2335                 for (i = 0; i < nds; i++) {
 2336                         if (buflen < dssize) {
 2337                                 ret = ENOMEM;
 2338                                 break;
 2339                         }
 2340                         switch (*name) {
 2341 #ifdef SYSVSEM
 2342                         case KERN_SYSVIPC_SEM_INFO:
 2343                                 if (sema[i] != NULL)
 2344                                         memcpy(&semsi->semids[i], sema[i],
 2345                                             dssize);
 2346                                 else
 2347                                         memset(&semsi->semids[i], 0, dssize);
 2348                                 break;
 2349 #endif
 2350 #ifdef SYSVSHM
 2351                         case KERN_SYSVIPC_SHM_INFO:
 2352                                 if (shmsegs[i] != NULL)
 2353                                         memcpy(&shmsi->shmids[i], shmsegs[i],
 2354                                             dssize);
 2355                                 else
 2356                                         memset(&shmsi->shmids[i], 0, dssize);
 2357                                 break;
 2358 #endif
 2359                         }
 2360                         buflen -= dssize;
 2361                 }
 2362         }
 2363         *sizep -= buflen;
 2364         error = copyout(buf, where, *sizep);
 2365         free(buf, M_TEMP, bufsiz);
 2366         /* If copyout succeeded, use return code set earlier. */
 2367         return (error ? error : ret);
 2368 }
 2369 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */
 2370 
 2371 #ifndef SMALL_KERNEL
 2372 
 2373 int
 2374 sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp)
 2375 {
 2376         return (evcount_sysctl(name, namelen, oldp, oldlenp, NULL, 0));
 2377 }
 2378 
 2379 
 2380 int
 2381 sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp,
 2382     void *newp, size_t newlen)
 2383 {
 2384         struct ksensor *ks;
 2385         struct sensor *us;
 2386         struct ksensordev *ksd;
 2387         struct sensordev *usd;
 2388         int dev, numt, ret;
 2389         enum sensor_type type;
 2390 
 2391         if (namelen != 1 && namelen != 3)
 2392                 return (ENOTDIR);
 2393 
 2394         dev = name[0];
 2395         if (namelen == 1) {
 2396                 ret = sensordev_get(dev, &ksd);
 2397                 if (ret)
 2398                         return (ret);
 2399 
 2400                 /* Grab a copy, to clear the kernel pointers */
 2401                 usd = malloc(sizeof(*usd), M_TEMP, M_WAITOK|M_ZERO);
 2402                 usd->num = ksd->num;
 2403                 strlcpy(usd->xname, ksd->xname, sizeof(usd->xname));
 2404                 memcpy(usd->maxnumt, ksd->maxnumt, sizeof(usd->maxnumt));
 2405                 usd->sensors_count = ksd->sensors_count;
 2406 
 2407                 ret = sysctl_rdstruct(oldp, oldlenp, newp, usd,
 2408                     sizeof(struct sensordev));
 2409 
 2410                 free(usd, M_TEMP, sizeof(*usd));
 2411                 return (ret);
 2412         }
 2413 
 2414         type = name[1];
 2415         numt = name[2];
 2416 
 2417         ret = sensor_find(dev, type, numt, &ks);
 2418         if (ret)
 2419                 return (ret);
 2420 
 2421         /* Grab a copy, to clear the kernel pointers */
 2422         us = malloc(sizeof(*us), M_TEMP, M_WAITOK|M_ZERO);
 2423         memcpy(us->desc, ks->desc, sizeof(us->desc));
 2424         us->tv = ks->tv;
 2425         us->value = ks->value;
 2426         us->type = ks->type;
 2427         us->status = ks->status;
 2428         us->numt = ks->numt;
 2429         us->flags = ks->flags;
 2430 
 2431         ret = sysctl_rdstruct(oldp, oldlenp, newp, us,
 2432             sizeof(struct sensor));
 2433         free(us, M_TEMP, sizeof(*us));
 2434         return (ret);
 2435 }
 2436 #endif  /* SMALL_KERNEL */
 2437 
 2438 int
 2439 sysctl_cptime2(int *name, u_int namelen, void *oldp, size_t *oldlenp,
 2440     void *newp, size_t newlen)
 2441 {
 2442         CPU_INFO_ITERATOR cii;
 2443         struct cpu_info *ci;
 2444         int found = 0;
 2445 
 2446         if (namelen != 1)
 2447                 return (ENOTDIR);
 2448 
 2449         CPU_INFO_FOREACH(cii, ci) {
 2450                 if (name[0] == CPU_INFO_UNIT(ci)) {
 2451                         found = 1;
 2452                         break;
 2453                 }
 2454         }
 2455         if (!found)
 2456                 return (ENOENT);
 2457 
 2458         return (sysctl_rdstruct(oldp, oldlenp, newp,
 2459             &ci->ci_schedstate.spc_cp_time,
 2460             sizeof(ci->ci_schedstate.spc_cp_time)));
 2461 }
 2462 
 2463 #if NAUDIO > 0
 2464 int
 2465 sysctl_audio(int *name, u_int namelen, void *oldp, size_t *oldlenp,
 2466     void *newp, size_t newlen)
 2467 {
 2468         if (namelen != 1)
 2469                 return (ENOTDIR);
 2470 
 2471         if (name[0] != KERN_AUDIO_RECORD)
 2472                 return (ENOENT);
 2473 
 2474         return (sysctl_int(oldp, oldlenp, newp, newlen, &audio_record_enable));
 2475 }
 2476 #endif
 2477 
 2478 #if NVIDEO > 0
 2479 int
 2480 sysctl_video(int *name, u_int namelen, void *oldp, size_t *oldlenp,
 2481     void *newp, size_t newlen)
 2482 {
 2483         if (namelen != 1)
 2484                 return (ENOTDIR);
 2485 
 2486         if (name[0] != KERN_VIDEO_RECORD)
 2487                 return (ENOENT);
 2488 
 2489         return (sysctl_int(oldp, oldlenp, newp, newlen, &video_record_enable));
 2490 }
 2491 #endif
 2492 
 2493 int
 2494 sysctl_cpustats(int *name, u_int namelen, void *oldp, size_t *oldlenp,
 2495     void *newp, size_t newlen)
 2496 {
 2497         CPU_INFO_ITERATOR cii;
 2498         struct cpustats cs;
 2499         struct cpu_info *ci;
 2500         int found = 0;
 2501 
 2502         if (namelen != 1)
 2503                 return (ENOTDIR);
 2504 
 2505         CPU_INFO_FOREACH(cii, ci) {
 2506                 if (name[0] == CPU_INFO_UNIT(ci)) {
 2507                         found = 1;
 2508                         break;
 2509                 }
 2510         }
 2511         if (!found)
 2512                 return (ENOENT);
 2513 
 2514         memset(&cs, 0, sizeof cs);
 2515         memcpy(&cs.cs_time, &ci->ci_schedstate.spc_cp_time, sizeof(cs.cs_time));
 2516         cs.cs_flags = 0;
 2517         if (cpu_is_online(ci))
 2518                 cs.cs_flags |= CPUSTATS_ONLINE;
 2519 
 2520         return (sysctl_rdstruct(oldp, oldlenp, newp, &cs, sizeof(cs)));
 2521 }
 2522 
 2523 int
 2524 sysctl_utc_offset(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
 2525 {
 2526         struct timespec adjusted, now;
 2527         int adjustment_seconds, error, new_offset_minutes, old_offset_minutes;
 2528 
 2529         old_offset_minutes = utc_offset / 60;   /* seconds -> minutes */
 2530         new_offset_minutes = old_offset_minutes;
 2531         error = sysctl_securelevel_int(oldp, oldlenp, newp, newlen,
 2532              &new_offset_minutes);
 2533         if (error)
 2534                 return error;
 2535         if (new_offset_minutes < -24 * 60 || new_offset_minutes > 24 * 60)
 2536                 return EINVAL;
 2537         if (new_offset_minutes == old_offset_minutes)
 2538                 return 0;
 2539 
 2540         utc_offset = new_offset_minutes * 60;   /* minutes -> seconds */
 2541         adjustment_seconds = (new_offset_minutes - old_offset_minutes) * 60;
 2542 
 2543         nanotime(&now);
 2544         adjusted = now;
 2545         adjusted.tv_sec -= adjustment_seconds;
 2546         tc_setrealtimeclock(&adjusted);
 2547         resettodr();
 2548 
 2549         return 0;
 2550 }

Cache object: 57717a699902804bb186128633783cd2


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