1df8bae1dSRodney W. Grimes /*- 2df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1989, 1993 3df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 4df8bae1dSRodney W. Grimes * 5df8bae1dSRodney W. Grimes * This code is derived from software contributed to Berkeley by 6df8bae1dSRodney W. Grimes * Mike Karels at Berkeley Software Design, Inc. 7df8bae1dSRodney W. Grimes * 8df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 9df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 10df8bae1dSRodney W. Grimes * are met: 11df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 12df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 13df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 14df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 15df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 16df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 17df8bae1dSRodney W. Grimes * must display the following acknowledgement: 18df8bae1dSRodney W. Grimes * This product includes software developed by the University of 19df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 20df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 21df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 22df8bae1dSRodney W. Grimes * without specific prior written permission. 23df8bae1dSRodney W. Grimes * 24df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34df8bae1dSRodney W. Grimes * SUCH DAMAGE. 35df8bae1dSRodney W. Grimes * 36df8bae1dSRodney W. Grimes * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 37deae269aSPoul-Henning Kamp * $Id: kern_sysctl.c,v 1.38 1995/11/12 19:51:51 phk Exp $ 38df8bae1dSRodney W. Grimes */ 39df8bae1dSRodney W. Grimes 40df8bae1dSRodney W. Grimes /* 41df8bae1dSRodney W. Grimes * sysctl system call. 42df8bae1dSRodney W. Grimes */ 43df8bae1dSRodney W. Grimes 44df8bae1dSRodney W. Grimes #include <sys/param.h> 45df8bae1dSRodney W. Grimes #include <sys/systm.h> 46d2d3e875SBruce Evans #include <sys/sysproto.h> 47df8bae1dSRodney W. Grimes #include <sys/kernel.h> 48df8bae1dSRodney W. Grimes #include <sys/malloc.h> 49df8bae1dSRodney W. Grimes #include <sys/proc.h> 50df8bae1dSRodney W. Grimes #include <sys/file.h> 51df8bae1dSRodney W. Grimes #include <sys/vnode.h> 52df8bae1dSRodney W. Grimes #include <sys/unistd.h> 53df8bae1dSRodney W. Grimes #include <sys/buf.h> 54df8bae1dSRodney W. Grimes #include <sys/ioctl.h> 55df8bae1dSRodney W. Grimes #include <sys/tty.h> 565bb4f738SGarrett Wollman #include <sys/conf.h> 57df8bae1dSRodney W. Grimes #include <vm/vm.h> 58df8bae1dSRodney W. Grimes #include <sys/sysctl.h> 593a34a5c3SPoul-Henning Kamp #include <sys/user.h> 60df8bae1dSRodney W. Grimes 61787d58f2SPoul-Henning Kamp extern struct linker_set sysctl_; 62787d58f2SPoul-Henning Kamp 63b396cd83SPoul-Henning Kamp /* BEGIN_MIB */ 64787d58f2SPoul-Henning Kamp SYSCTL_NODE(, 0, sysctl, CTLFLAG_RW, 0, 65787d58f2SPoul-Henning Kamp "Sysctl internal magic"); 662e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_KERN, kern, CTLFLAG_RW, 0, 672e210993SPoul-Henning Kamp "High kernel, proc, limits &c"); 682e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_VM, vm, CTLFLAG_RW, 0, 692e210993SPoul-Henning Kamp "Virtual memory"); 702e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_FS, fs, CTLFLAG_RW, 0, 712e210993SPoul-Henning Kamp "File system"); 722e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_NET, net, CTLFLAG_RW, 0, 732e210993SPoul-Henning Kamp "Network, (see socket.h)"); 742e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_DEBUG, debug, CTLFLAG_RW, 0, 752e210993SPoul-Henning Kamp "Debugging"); 762e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_HW, hw, CTLFLAG_RW, 0, 772e210993SPoul-Henning Kamp "hardware"); 782e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_MACHDEP, machdep, CTLFLAG_RW, 0, 792e210993SPoul-Henning Kamp "machine dependent"); 802e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW, 0, 812e210993SPoul-Henning Kamp "user-level"); 82b396cd83SPoul-Henning Kamp 832e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD, osrelease, 0, ""); 84b396cd83SPoul-Henning Kamp 852e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD, 0, BSD, ""); 86b396cd83SPoul-Henning Kamp 872e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD, version, 0, ""); 88b396cd83SPoul-Henning Kamp 892e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD, ostype, 0, ""); 90b396cd83SPoul-Henning Kamp 91b396cd83SPoul-Henning Kamp extern int osreldate; 922e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD, &osreldate, 0, ""); 93b396cd83SPoul-Henning Kamp 942e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXVNODES, maxvnodes, CTLFLAG_RD, &desiredvnodes, 0, ""); 95b396cd83SPoul-Henning Kamp 962e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXPROC, maxproc, CTLFLAG_RD, &maxproc, 0, ""); 97b396cd83SPoul-Henning Kamp 98b396cd83SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXPROCPERUID, maxprocperuid, 993a34a5c3SPoul-Henning Kamp CTLFLAG_RD, &maxprocperuid, 0, ""); 100b396cd83SPoul-Henning Kamp 101b396cd83SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXFILESPERPROC, maxfilesperproc, 1023a34a5c3SPoul-Henning Kamp CTLFLAG_RD, &maxfilesperproc, 0, ""); 103b396cd83SPoul-Henning Kamp 1042e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_ARGMAX, argmax, CTLFLAG_RD, 0, ARG_MAX, ""); 105b396cd83SPoul-Henning Kamp 1062e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD, 0, _POSIX_VERSION, ""); 107b396cd83SPoul-Henning Kamp 1082e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RD, 0, NGROUPS_MAX, ""); 109b396cd83SPoul-Henning Kamp 1102e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control, CTLFLAG_RD, 0, 1, ""); 111b396cd83SPoul-Henning Kamp 1122e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXFILES, maxfiles, CTLFLAG_RW, &maxfiles, 0, ""); 113b396cd83SPoul-Henning Kamp 114b396cd83SPoul-Henning Kamp #ifdef _POSIX_SAVED_IDS 1152e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 1, ""); 116b396cd83SPoul-Henning Kamp #else 1172e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 0, ""); 118b396cd83SPoul-Henning Kamp #endif 119b396cd83SPoul-Henning Kamp 120b396cd83SPoul-Henning Kamp char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */ 121b396cd83SPoul-Henning Kamp 122b396cd83SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, 1233a34a5c3SPoul-Henning Kamp CTLFLAG_RW, kernelname, sizeof kernelname, ""); 124b396cd83SPoul-Henning Kamp 125b396cd83SPoul-Henning Kamp SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime, 1263a34a5c3SPoul-Henning Kamp CTLFLAG_RW, &boottime, timeval, ""); 127b396cd83SPoul-Henning Kamp 1282e210993SPoul-Henning Kamp SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 129b396cd83SPoul-Henning Kamp 130787d58f2SPoul-Henning Kamp SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, ""); 131b396cd83SPoul-Henning Kamp 1322e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD, 0, 1, ""); 133b396cd83SPoul-Henning Kamp 1342e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD, 0, BYTE_ORDER, ""); 135b396cd83SPoul-Henning Kamp 1362e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_PAGESIZE, pagesize, CTLFLAG_RD, 0, PAGE_SIZE, ""); 137b396cd83SPoul-Henning Kamp 138b396cd83SPoul-Henning Kamp /* END_MIB */ 139b396cd83SPoul-Henning Kamp 140b396cd83SPoul-Henning Kamp extern int vfs_update_wakeup; 141b396cd83SPoul-Henning Kamp extern int vfs_update_interval; 142b396cd83SPoul-Henning Kamp static int 1433a34a5c3SPoul-Henning Kamp sysctl_kern_updateinterval SYSCTL_HANDLER_ARGS 144b396cd83SPoul-Henning Kamp { 1453a34a5c3SPoul-Henning Kamp int error = sysctl_handle_int(oidp, 146ae0eb976SPoul-Henning Kamp oidp->oid_arg1, oidp->oid_arg2, req); 1473a34a5c3SPoul-Henning Kamp if (!error) 148b396cd83SPoul-Henning Kamp wakeup(&vfs_update_wakeup); 1493a34a5c3SPoul-Henning Kamp return error; 150b396cd83SPoul-Henning Kamp } 151b396cd83SPoul-Henning Kamp 1522e210993SPoul-Henning Kamp SYSCTL_PROC(_kern, KERN_UPDATEINTERVAL, update, CTLTYPE_INT|CTLFLAG_RW, 1533a34a5c3SPoul-Henning Kamp &vfs_update_interval, 0, sysctl_kern_updateinterval, ""); 154b396cd83SPoul-Henning Kamp 1552e210993SPoul-Henning Kamp 1562e210993SPoul-Henning Kamp char hostname[MAXHOSTNAMELEN]; 1572e210993SPoul-Henning Kamp int hostnamelen; 1582e210993SPoul-Henning Kamp static int 1592e210993SPoul-Henning Kamp sysctl_kern_hostname SYSCTL_HANDLER_ARGS 1602e210993SPoul-Henning Kamp { 1612e210993SPoul-Henning Kamp int error = sysctl_handle_string(oidp, 162ae0eb976SPoul-Henning Kamp oidp->oid_arg1, oidp->oid_arg2, req); 163ae0eb976SPoul-Henning Kamp if (req->newptr && (error == 0 || error == ENOMEM)) 164ae0eb976SPoul-Henning Kamp hostnamelen = req->newlen; 1652e210993SPoul-Henning Kamp return error; 1662e210993SPoul-Henning Kamp } 1672e210993SPoul-Henning Kamp 1682e210993SPoul-Henning Kamp SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname, CTLTYPE_STRING|CTLFLAG_RW, 1692e210993SPoul-Henning Kamp &hostname, sizeof(hostname), sysctl_kern_hostname, ""); 1702e210993SPoul-Henning Kamp 171787d58f2SPoul-Henning Kamp static int 1723c8e79ddSBruce Evans sysctl_order_cmp(const void *a, const void *b) 173787d58f2SPoul-Henning Kamp { 1743c8e79ddSBruce Evans const struct sysctl_oid **pa, **pb; 1753c8e79ddSBruce Evans 1763c8e79ddSBruce Evans pa = (const struct sysctl_oid **)a; 1773c8e79ddSBruce Evans pb = (const struct sysctl_oid **)b; 1783c8e79ddSBruce Evans if (*pa == NULL) 1793c8e79ddSBruce Evans return (1); 1803c8e79ddSBruce Evans if (*pb == NULL) 1813c8e79ddSBruce Evans return (-1); 182787d58f2SPoul-Henning Kamp return ((*pa)->oid_number - (*pb)->oid_number); 183787d58f2SPoul-Henning Kamp } 184787d58f2SPoul-Henning Kamp 185787d58f2SPoul-Henning Kamp static void 186787d58f2SPoul-Henning Kamp sysctl_order(void *arg) 187787d58f2SPoul-Henning Kamp { 188b8da2396SPoul-Henning Kamp int j; 189787d58f2SPoul-Henning Kamp struct linker_set *l = (struct linker_set *) arg; 190787d58f2SPoul-Henning Kamp struct sysctl_oid **oidpp; 191787d58f2SPoul-Henning Kamp 192787d58f2SPoul-Henning Kamp j = l->ls_length; 193787d58f2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 194787d58f2SPoul-Henning Kamp for (; j--; oidpp++) { 195787d58f2SPoul-Henning Kamp if (!*oidpp) 196787d58f2SPoul-Henning Kamp continue; 197787d58f2SPoul-Henning Kamp if ((*oidpp)->oid_arg1 == arg) { 198787d58f2SPoul-Henning Kamp *oidpp = 0; 199787d58f2SPoul-Henning Kamp continue; 200787d58f2SPoul-Henning Kamp } 201787d58f2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) 202787d58f2SPoul-Henning Kamp if (!(*oidpp)->oid_handler) 203787d58f2SPoul-Henning Kamp sysctl_order((*oidpp)->oid_arg1); 204787d58f2SPoul-Henning Kamp } 205787d58f2SPoul-Henning Kamp qsort(l->ls_items, l->ls_length, sizeof l->ls_items[0], 206787d58f2SPoul-Henning Kamp sysctl_order_cmp); 207787d58f2SPoul-Henning Kamp } 208787d58f2SPoul-Henning Kamp 209787d58f2SPoul-Henning Kamp SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_order, &sysctl_); 210787d58f2SPoul-Henning Kamp 211787d58f2SPoul-Henning Kamp static void 212787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node(struct linker_set *l, int i) 213787d58f2SPoul-Henning Kamp { 214787d58f2SPoul-Henning Kamp int j, k; 215787d58f2SPoul-Henning Kamp struct sysctl_oid **oidpp; 216787d58f2SPoul-Henning Kamp 217787d58f2SPoul-Henning Kamp j = l->ls_length; 218787d58f2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 219787d58f2SPoul-Henning Kamp for (; j--; oidpp++) { 220787d58f2SPoul-Henning Kamp 221787d58f2SPoul-Henning Kamp if (!*oidpp) 222787d58f2SPoul-Henning Kamp continue; 223787d58f2SPoul-Henning Kamp 224787d58f2SPoul-Henning Kamp for (k=0; k<i; k++) 225787d58f2SPoul-Henning Kamp printf(" "); 226787d58f2SPoul-Henning Kamp 227787d58f2SPoul-Henning Kamp if ((*oidpp)->oid_number > 100) { 228b8da2396SPoul-Henning Kamp printf("Junk! %p # %d %s k %x a1 %p a2 %x h %p\n", 229787d58f2SPoul-Henning Kamp *oidpp, 230787d58f2SPoul-Henning Kamp (*oidpp)->oid_number, (*oidpp)->oid_name, 231787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind, (*oidpp)->oid_arg1, 232787d58f2SPoul-Henning Kamp (*oidpp)->oid_arg2, (*oidpp)->oid_handler); 233787d58f2SPoul-Henning Kamp continue; 234787d58f2SPoul-Henning Kamp } 235787d58f2SPoul-Henning Kamp printf("%d %s ", (*oidpp)->oid_number, (*oidpp)->oid_name); 236787d58f2SPoul-Henning Kamp 237787d58f2SPoul-Henning Kamp printf("%c%c", 238787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind & CTLFLAG_RD ? 'R':' ', 239787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind & CTLFLAG_WR ? 'W':' '); 240787d58f2SPoul-Henning Kamp 241787d58f2SPoul-Henning Kamp switch ((*oidpp)->oid_kind & CTLTYPE) { 242787d58f2SPoul-Henning Kamp case CTLTYPE_NODE: 243787d58f2SPoul-Henning Kamp if ((*oidpp)->oid_handler) { 244787d58f2SPoul-Henning Kamp printf(" Node(proc)\n"); 245787d58f2SPoul-Henning Kamp } else { 246787d58f2SPoul-Henning Kamp printf(" Node\n"); 247787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node( 248787d58f2SPoul-Henning Kamp (*oidpp)->oid_arg1, i+2); 249787d58f2SPoul-Henning Kamp } 250787d58f2SPoul-Henning Kamp break; 251787d58f2SPoul-Henning Kamp case CTLTYPE_INT: printf(" Int\n"); break; 252787d58f2SPoul-Henning Kamp case CTLTYPE_STRING: printf(" String\n"); break; 253787d58f2SPoul-Henning Kamp case CTLTYPE_QUAD: printf(" Quad\n"); break; 254787d58f2SPoul-Henning Kamp case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break; 255787d58f2SPoul-Henning Kamp default: printf("\n"); 256787d58f2SPoul-Henning Kamp } 257787d58f2SPoul-Henning Kamp 258787d58f2SPoul-Henning Kamp } 259787d58f2SPoul-Henning Kamp } 260787d58f2SPoul-Henning Kamp 261787d58f2SPoul-Henning Kamp 262787d58f2SPoul-Henning Kamp static int 263787d58f2SPoul-Henning Kamp sysctl_sysctl_debug SYSCTL_HANDLER_ARGS 264787d58f2SPoul-Henning Kamp { 265787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node(&sysctl_, 0); 266787d58f2SPoul-Henning Kamp return ENOENT; 267787d58f2SPoul-Henning Kamp } 268787d58f2SPoul-Henning Kamp 269787d58f2SPoul-Henning Kamp SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD, 270787d58f2SPoul-Henning Kamp 0, 0, sysctl_sysctl_debug, ""); 2712e210993SPoul-Henning Kamp 2722e210993SPoul-Henning Kamp char domainname[MAXHOSTNAMELEN]; 2732e210993SPoul-Henning Kamp int domainnamelen; 2742e210993SPoul-Henning Kamp static int 2752e210993SPoul-Henning Kamp sysctl_kern_domainname SYSCTL_HANDLER_ARGS 2762e210993SPoul-Henning Kamp { 2772e210993SPoul-Henning Kamp int error = sysctl_handle_string(oidp, 278ae0eb976SPoul-Henning Kamp oidp->oid_arg1, oidp->oid_arg2, req); 279ae0eb976SPoul-Henning Kamp if (req->newptr && (error == 0 || error == ENOMEM)) 280ae0eb976SPoul-Henning Kamp domainnamelen = req->newlen; 2812e210993SPoul-Henning Kamp return error; 2822e210993SPoul-Henning Kamp } 2832e210993SPoul-Henning Kamp 2842e210993SPoul-Henning Kamp SYSCTL_PROC(_kern, KERN_DOMAINNAME, domainname, CTLTYPE_STRING|CTLFLAG_RW, 2852e210993SPoul-Henning Kamp &domainname, sizeof(domainname), sysctl_kern_domainname, ""); 2862e210993SPoul-Henning Kamp 2872e210993SPoul-Henning Kamp long hostid; 2882e210993SPoul-Henning Kamp /* Some trouble here, if sizeof (int) != sizeof (long) */ 2892e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_HOSTID, hostid, CTLFLAG_RW, &hostid, 0, ""); 2902e210993SPoul-Henning Kamp 291ae0eb976SPoul-Henning Kamp /* 292ae0eb976SPoul-Henning Kamp * Handle an integer, signed or unsigned. 293ae0eb976SPoul-Henning Kamp * Two cases: 294ae0eb976SPoul-Henning Kamp * a variable: point arg1 at it. 295ae0eb976SPoul-Henning Kamp * a constant: pass it in arg2. 296ae0eb976SPoul-Henning Kamp */ 297ae0eb976SPoul-Henning Kamp 2983a34a5c3SPoul-Henning Kamp int 2993a34a5c3SPoul-Henning Kamp sysctl_handle_int SYSCTL_HANDLER_ARGS 300b396cd83SPoul-Henning Kamp { 301ae0eb976SPoul-Henning Kamp int error = 0; 302b396cd83SPoul-Henning Kamp 303ae0eb976SPoul-Henning Kamp if (arg1) 304ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, sizeof(int)); 305ae0eb976SPoul-Henning Kamp else if (arg2) 306ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, &arg2, sizeof(int)); 307b396cd83SPoul-Henning Kamp 308ae0eb976SPoul-Henning Kamp if (error || !req->newptr) 309ae0eb976SPoul-Henning Kamp return (error); 310b396cd83SPoul-Henning Kamp 311ae0eb976SPoul-Henning Kamp if (!arg1) 312ae0eb976SPoul-Henning Kamp error = EPERM; 313ae0eb976SPoul-Henning Kamp else 314ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, sizeof(int)); 315ae0eb976SPoul-Henning Kamp return (error); 316b396cd83SPoul-Henning Kamp } 317b396cd83SPoul-Henning Kamp 318ae0eb976SPoul-Henning Kamp /* 319ae0eb976SPoul-Henning Kamp * Handle our generic '\0' terminated 'C' string. 320ae0eb976SPoul-Henning Kamp * Two cases: 321ae0eb976SPoul-Henning Kamp * a variable string: point arg1 at it, arg2 is max length. 322ae0eb976SPoul-Henning Kamp * a constant string: point arg1 at it, arg2 is zero. 323ae0eb976SPoul-Henning Kamp */ 324ae0eb976SPoul-Henning Kamp 3253a34a5c3SPoul-Henning Kamp int 3263a34a5c3SPoul-Henning Kamp sysctl_handle_string SYSCTL_HANDLER_ARGS 327b396cd83SPoul-Henning Kamp { 328ae0eb976SPoul-Henning Kamp int error=0; 329b396cd83SPoul-Henning Kamp 330ae0eb976SPoul-Henning Kamp if (arg2) 331ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, arg2); 332ae0eb976SPoul-Henning Kamp else 333ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, strlen((char *)arg1)+1); 334b396cd83SPoul-Henning Kamp 335deae269aSPoul-Henning Kamp if (error || !req->newptr || !arg2) 336ae0eb976SPoul-Henning Kamp return (error); 337ae0eb976SPoul-Henning Kamp 338ae0eb976SPoul-Henning Kamp if ((req->newlen - req->newidx) > arg2) { 339ae0eb976SPoul-Henning Kamp error = E2BIG; 340ae0eb976SPoul-Henning Kamp } else { 341ae0eb976SPoul-Henning Kamp arg2 = (req->newlen - req->newidx); 342ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, arg2); 343ae0eb976SPoul-Henning Kamp ((char *)arg1)[arg2] = '\0'; 344b396cd83SPoul-Henning Kamp } 345b396cd83SPoul-Henning Kamp 3462e210993SPoul-Henning Kamp return (error); 347b396cd83SPoul-Henning Kamp } 348b396cd83SPoul-Henning Kamp 349ae0eb976SPoul-Henning Kamp /* 350ae0eb976SPoul-Henning Kamp * Handle any kind of opaque data. 351ae0eb976SPoul-Henning Kamp * arg1 points to it, arg2 is the size. 352ae0eb976SPoul-Henning Kamp */ 353ae0eb976SPoul-Henning Kamp 3543a34a5c3SPoul-Henning Kamp int 3553a34a5c3SPoul-Henning Kamp sysctl_handle_opaque SYSCTL_HANDLER_ARGS 356b396cd83SPoul-Henning Kamp { 357ae0eb976SPoul-Henning Kamp int error; 358b396cd83SPoul-Henning Kamp 359ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, arg2); 360b396cd83SPoul-Henning Kamp 361ae0eb976SPoul-Henning Kamp if (error || !req->newptr) 362ae0eb976SPoul-Henning Kamp return (error); 363ae0eb976SPoul-Henning Kamp 364ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, arg2); 365ae0eb976SPoul-Henning Kamp 366ae0eb976SPoul-Henning Kamp return (error); 367b396cd83SPoul-Henning Kamp } 368ae0eb976SPoul-Henning Kamp 369deae269aSPoul-Henning Kamp /* 370deae269aSPoul-Henning Kamp * Transfer functions to/from kernel space. 371deae269aSPoul-Henning Kamp * XXX: rather untested at this point 372deae269aSPoul-Henning Kamp */ 373deae269aSPoul-Henning Kamp static int 374ae0eb976SPoul-Henning Kamp sysctl_old_kernel(struct sysctl_req *req, void *p, int l) 375ae0eb976SPoul-Henning Kamp { 376deae269aSPoul-Henning Kamp int i = 0; 377deae269aSPoul-Henning Kamp 378deae269aSPoul-Henning Kamp if (req->oldptr) { 379deae269aSPoul-Henning Kamp i = min(req->oldlen - req->oldidx, l); 380deae269aSPoul-Henning Kamp if (i > 0) 381ae0eb976SPoul-Henning Kamp bcopy(p, req->oldptr + req->oldidx, i); 382ae0eb976SPoul-Henning Kamp } 383deae269aSPoul-Henning Kamp req->oldidx += l; 384ae0eb976SPoul-Henning Kamp if (i != l) 385ae0eb976SPoul-Henning Kamp return (ENOMEM); 3862e210993SPoul-Henning Kamp return (0); 387ae0eb976SPoul-Henning Kamp 388ae0eb976SPoul-Henning Kamp } 389ae0eb976SPoul-Henning Kamp 390deae269aSPoul-Henning Kamp static int 391ae0eb976SPoul-Henning Kamp sysctl_new_kernel(struct sysctl_req *req, void *p, int l) 392ae0eb976SPoul-Henning Kamp { 393deae269aSPoul-Henning Kamp int i; 394deae269aSPoul-Henning Kamp if (!req->newptr) 395deae269aSPoul-Henning Kamp return 0; 396deae269aSPoul-Henning Kamp if (req->newlen - req->newidx < l) 397ae0eb976SPoul-Henning Kamp return (EINVAL); 398ae0eb976SPoul-Henning Kamp bcopy(req->newptr + req->newidx, p, l); 399ae0eb976SPoul-Henning Kamp req->newidx += l; 400ae0eb976SPoul-Henning Kamp return (0); 401ae0eb976SPoul-Henning Kamp } 402ae0eb976SPoul-Henning Kamp 403deae269aSPoul-Henning Kamp /* 404deae269aSPoul-Henning Kamp * Transfer function to/from user space. 405deae269aSPoul-Henning Kamp */ 406deae269aSPoul-Henning Kamp static int 407ae0eb976SPoul-Henning Kamp sysctl_old_user(struct sysctl_req *req, void *p, int l) 408ae0eb976SPoul-Henning Kamp { 409deae269aSPoul-Henning Kamp int error = 0, i = 0; 410ae0eb976SPoul-Henning Kamp 411deae269aSPoul-Henning Kamp if (req->oldptr) { 412deae269aSPoul-Henning Kamp i = min(req->oldlen - req->oldidx, l); 413deae269aSPoul-Henning Kamp if (i > 0) 414ae0eb976SPoul-Henning Kamp error = copyout(p, req->oldptr + req->oldidx, i); 415deae269aSPoul-Henning Kamp } 416deae269aSPoul-Henning Kamp req->oldidx += l; 417ae0eb976SPoul-Henning Kamp if (error) 418ae0eb976SPoul-Henning Kamp return (error); 419deae269aSPoul-Henning Kamp if (req->oldptr && i < l) 420ae0eb976SPoul-Henning Kamp return (ENOMEM); 421deae269aSPoul-Henning Kamp return (0); 422ae0eb976SPoul-Henning Kamp } 423ae0eb976SPoul-Henning Kamp 424deae269aSPoul-Henning Kamp static int 425ae0eb976SPoul-Henning Kamp sysctl_new_user(struct sysctl_req *req, void *p, int l) 426ae0eb976SPoul-Henning Kamp { 427deae269aSPoul-Henning Kamp int error, i; 428deae269aSPoul-Henning Kamp 429deae269aSPoul-Henning Kamp if (!req->newptr) 430deae269aSPoul-Henning Kamp return 0; 431deae269aSPoul-Henning Kamp if (req->newlen - req->newidx < l) 432ae0eb976SPoul-Henning Kamp return (EINVAL); 433ae0eb976SPoul-Henning Kamp error = copyin(req->newptr + req->newidx, p, l); 434ae0eb976SPoul-Henning Kamp req->newidx += l; 435ae0eb976SPoul-Henning Kamp return (error); 436b396cd83SPoul-Henning Kamp } 437b396cd83SPoul-Henning Kamp 4383a34a5c3SPoul-Henning Kamp #ifdef DEBUG 4393a34a5c3SPoul-Henning Kamp static sysctlfn debug_sysctl; 4403a34a5c3SPoul-Henning Kamp #endif 441b396cd83SPoul-Henning Kamp 442df8bae1dSRodney W. Grimes /* 443df8bae1dSRodney W. Grimes * Locking and stats 444df8bae1dSRodney W. Grimes */ 445df8bae1dSRodney W. Grimes static struct sysctl_lock { 446df8bae1dSRodney W. Grimes int sl_lock; 447df8bae1dSRodney W. Grimes int sl_want; 448df8bae1dSRodney W. Grimes int sl_locked; 449df8bae1dSRodney W. Grimes } memlock; 450df8bae1dSRodney W. Grimes 4512e210993SPoul-Henning Kamp 4522e210993SPoul-Henning Kamp 4532e210993SPoul-Henning Kamp /* 4542e210993SPoul-Henning Kamp * Traverse our tree, and find the right node, execute whatever it points 4552e210993SPoul-Henning Kamp * at, and return the resulting error code. 4562e210993SPoul-Henning Kamp * We work entirely in kernel-space at this time. 4572e210993SPoul-Henning Kamp */ 4582e210993SPoul-Henning Kamp 4592e210993SPoul-Henning Kamp 4602e210993SPoul-Henning Kamp int 4612e210993SPoul-Henning Kamp sysctl_root SYSCTL_HANDLER_ARGS 4622e210993SPoul-Henning Kamp { 4632e210993SPoul-Henning Kamp int *name = (int *) arg1; 4642e210993SPoul-Henning Kamp int namelen = arg2; 4652e210993SPoul-Henning Kamp int indx, i, j; 4662e210993SPoul-Henning Kamp struct sysctl_oid **oidpp; 4672e210993SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 4682e210993SPoul-Henning Kamp 4692e210993SPoul-Henning Kamp j = lsp->ls_length; 4702e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 4712e210993SPoul-Henning Kamp 4722e210993SPoul-Henning Kamp indx = 0; 4732e210993SPoul-Henning Kamp while (j-- && indx < CTL_MAXNAME) { 474787d58f2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number == name[indx])) { 4752e210993SPoul-Henning Kamp indx++; 4762e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 4772e210993SPoul-Henning Kamp if ((*oidpp)->oid_handler) 4782e210993SPoul-Henning Kamp goto found; 4792e210993SPoul-Henning Kamp if (indx == namelen) 4802e210993SPoul-Henning Kamp return ENOENT; 4812e210993SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 4822e210993SPoul-Henning Kamp j = lsp->ls_length; 4832e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 4842e210993SPoul-Henning Kamp } else { 4852e210993SPoul-Henning Kamp if (indx != namelen) 4862e210993SPoul-Henning Kamp return EISDIR; 4872e210993SPoul-Henning Kamp goto found; 4882e210993SPoul-Henning Kamp } 4892e210993SPoul-Henning Kamp } else { 4902e210993SPoul-Henning Kamp oidpp++; 4912e210993SPoul-Henning Kamp } 4922e210993SPoul-Henning Kamp } 493deae269aSPoul-Henning Kamp return ENOENT; 4942e210993SPoul-Henning Kamp found: 4952e210993SPoul-Henning Kamp 4962e210993SPoul-Henning Kamp /* If writing isn't allowed */ 497ae0eb976SPoul-Henning Kamp if (req->newptr && !((*oidpp)->oid_kind & CTLFLAG_WR)) 4982e210993SPoul-Henning Kamp return (EPERM); 4992e210993SPoul-Henning Kamp 5002e210993SPoul-Henning Kamp if (!(*oidpp)->oid_handler) 5012e210993SPoul-Henning Kamp return EINVAL; 5022e210993SPoul-Henning Kamp 5032e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 5042e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 5052e210993SPoul-Henning Kamp name + indx, namelen - indx, 506ae0eb976SPoul-Henning Kamp req); 5072e210993SPoul-Henning Kamp } else { 5082e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 5092e210993SPoul-Henning Kamp (*oidpp)->oid_arg1, (*oidpp)->oid_arg2, 510ae0eb976SPoul-Henning Kamp req); 5112e210993SPoul-Henning Kamp } 5122e210993SPoul-Henning Kamp return (i); 5132e210993SPoul-Henning Kamp } 5142e210993SPoul-Henning Kamp 515d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 516b8da2396SPoul-Henning Kamp struct sysctl_args { 517b8da2396SPoul-Henning Kamp int *name; 518b8da2396SPoul-Henning Kamp u_int namelen; 519b8da2396SPoul-Henning Kamp void *old; 520b8da2396SPoul-Henning Kamp size_t *oldlenp; 521b8da2396SPoul-Henning Kamp void *new; 522b8da2396SPoul-Henning Kamp size_t newlen; 523b8da2396SPoul-Henning Kamp }; 524d2d3e875SBruce Evans #endif 525b8da2396SPoul-Henning Kamp 526df8bae1dSRodney W. Grimes int 527df8bae1dSRodney W. Grimes __sysctl(p, uap, retval) 528df8bae1dSRodney W. Grimes struct proc *p; 529df8bae1dSRodney W. Grimes register struct sysctl_args *uap; 530df8bae1dSRodney W. Grimes int *retval; 531df8bae1dSRodney W. Grimes { 532deae269aSPoul-Henning Kamp int error, i, j, name[CTL_MAXNAME]; 533b396cd83SPoul-Henning Kamp 534df8bae1dSRodney W. Grimes if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 535df8bae1dSRodney W. Grimes return (EINVAL); 536b396cd83SPoul-Henning Kamp 537797f2d22SPoul-Henning Kamp error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 538797f2d22SPoul-Henning Kamp if (error) 539df8bae1dSRodney W. Grimes return (error); 540df8bae1dSRodney W. Grimes 541deae269aSPoul-Henning Kamp error = userland_sysctl(p, name, uap->namelen, 542b8da2396SPoul-Henning Kamp uap->old, uap->oldlenp, 0, 543deae269aSPoul-Henning Kamp uap->new, uap->newlen, &j); 544deae269aSPoul-Henning Kamp if (error && error != ENOMEM) 545deae269aSPoul-Henning Kamp return (error); 546deae269aSPoul-Henning Kamp if (uap->oldlenp) { 547deae269aSPoul-Henning Kamp i = copyout(&j, uap->oldlenp, sizeof(j)); 548deae269aSPoul-Henning Kamp if (i) 549deae269aSPoul-Henning Kamp return (i); 550deae269aSPoul-Henning Kamp } 551deae269aSPoul-Henning Kamp return (error); 552b8da2396SPoul-Henning Kamp } 553b8da2396SPoul-Henning Kamp 5546ff1bbebSPoul-Henning Kamp static sysctlfn kern_sysctl; 5556ff1bbebSPoul-Henning Kamp 556b8da2396SPoul-Henning Kamp /* 557b8da2396SPoul-Henning Kamp * This is used from various compatibility syscalls too. That's why name 558b8da2396SPoul-Henning Kamp * must be in kernel space. 559b8da2396SPoul-Henning Kamp */ 560b8da2396SPoul-Henning Kamp int 561b8da2396SPoul-Henning Kamp userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen, int *retval) 562b8da2396SPoul-Henning Kamp { 563ae0eb976SPoul-Henning Kamp int error = 0, dolock = 1, i, oldlen = 0; 564ae0eb976SPoul-Henning Kamp u_int savelen = 0; 565b8da2396SPoul-Henning Kamp sysctlfn *fn; 566ae0eb976SPoul-Henning Kamp struct sysctl_req req; 567ae0eb976SPoul-Henning Kamp 568ae0eb976SPoul-Henning Kamp bzero(&req, sizeof req); 569b8da2396SPoul-Henning Kamp 570b8da2396SPoul-Henning Kamp if (new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 571b396cd83SPoul-Henning Kamp return (error); 572b396cd83SPoul-Henning Kamp 573b8da2396SPoul-Henning Kamp if (oldlenp) { 574b8da2396SPoul-Henning Kamp if (inkernel) { 575ae0eb976SPoul-Henning Kamp req.oldlen = *oldlenp; 576b8da2396SPoul-Henning Kamp } else { 577deae269aSPoul-Henning Kamp error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp)); 578b8da2396SPoul-Henning Kamp if (error) 579b8da2396SPoul-Henning Kamp return (error); 580b8da2396SPoul-Henning Kamp } 581b8da2396SPoul-Henning Kamp } 582b8da2396SPoul-Henning Kamp 583ae0eb976SPoul-Henning Kamp if (old) { 584ae0eb976SPoul-Henning Kamp if (!useracc(old, req.oldlen, B_WRITE)) 585ae0eb976SPoul-Henning Kamp return (EFAULT); 586ae0eb976SPoul-Henning Kamp req.oldptr= old; 587ae0eb976SPoul-Henning Kamp } 5882e210993SPoul-Henning Kamp 589b8da2396SPoul-Henning Kamp if (newlen) { 590ae0eb976SPoul-Henning Kamp if (!useracc(new, req.newlen, B_READ)) 591ae0eb976SPoul-Henning Kamp return (EFAULT); 592ae0eb976SPoul-Henning Kamp req.newlen = newlen; 593ae0eb976SPoul-Henning Kamp req.newptr = new; 594b396cd83SPoul-Henning Kamp } 595b396cd83SPoul-Henning Kamp 596ae0eb976SPoul-Henning Kamp req.oldfunc = sysctl_old_user; 597ae0eb976SPoul-Henning Kamp req.newfunc = sysctl_new_user; 598ae0eb976SPoul-Henning Kamp 599ae0eb976SPoul-Henning Kamp error = sysctl_root(0, name, namelen, &req); 600b396cd83SPoul-Henning Kamp 601deae269aSPoul-Henning Kamp /* 602deae269aSPoul-Henning Kamp if (error && error != ENOMEM) 603deae269aSPoul-Henning Kamp return (error); 604deae269aSPoul-Henning Kamp */ 605deae269aSPoul-Henning Kamp if (error == ENOENT) 606deae269aSPoul-Henning Kamp goto oldstuff; 607deae269aSPoul-Henning Kamp 608deae269aSPoul-Henning Kamp if (retval) { 609deae269aSPoul-Henning Kamp if (req.oldptr && req.oldidx > req.oldlen) 610ae0eb976SPoul-Henning Kamp *retval = req.oldlen; 611deae269aSPoul-Henning Kamp else 612deae269aSPoul-Henning Kamp *retval = req.oldidx; 613b8da2396SPoul-Henning Kamp } 6142e210993SPoul-Henning Kamp return (error); 615deae269aSPoul-Henning Kamp 616deae269aSPoul-Henning Kamp oldstuff: 617deae269aSPoul-Henning Kamp oldlen = req.oldlen; 618b396cd83SPoul-Henning Kamp 619df8bae1dSRodney W. Grimes switch (name[0]) { 620df8bae1dSRodney W. Grimes case CTL_KERN: 621df8bae1dSRodney W. Grimes fn = kern_sysctl; 622e9e2a852SAndrey A. Chernov if (name[1] != KERN_VNODE) /* XXX */ 623df8bae1dSRodney W. Grimes dolock = 0; 624df8bae1dSRodney W. Grimes break; 625df8bae1dSRodney W. Grimes case CTL_HW: 626df8bae1dSRodney W. Grimes fn = hw_sysctl; 627df8bae1dSRodney W. Grimes break; 628df8bae1dSRodney W. Grimes case CTL_VM: 629df8bae1dSRodney W. Grimes fn = vm_sysctl; 630df8bae1dSRodney W. Grimes break; 631df8bae1dSRodney W. Grimes case CTL_NET: 632df8bae1dSRodney W. Grimes fn = net_sysctl; 633df8bae1dSRodney W. Grimes break; 634df8bae1dSRodney W. Grimes case CTL_FS: 635df8bae1dSRodney W. Grimes fn = fs_sysctl; 636df8bae1dSRodney W. Grimes break; 637df8bae1dSRodney W. Grimes #ifdef DEBUG 638df8bae1dSRodney W. Grimes case CTL_DEBUG: 639df8bae1dSRodney W. Grimes fn = debug_sysctl; 640df8bae1dSRodney W. Grimes break; 641df8bae1dSRodney W. Grimes #endif 642df8bae1dSRodney W. Grimes default: 643df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 644df8bae1dSRodney W. Grimes } 645b8da2396SPoul-Henning Kamp if (old != NULL) { 646b8da2396SPoul-Henning Kamp if (!useracc(old, oldlen, B_WRITE)) 647df8bae1dSRodney W. Grimes return (EFAULT); 648df8bae1dSRodney W. Grimes while (memlock.sl_lock) { 649df8bae1dSRodney W. Grimes memlock.sl_want = 1; 65082478919SDavid Greenman (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 651df8bae1dSRodney W. Grimes memlock.sl_locked++; 652df8bae1dSRodney W. Grimes } 653df8bae1dSRodney W. Grimes memlock.sl_lock = 1; 654df8bae1dSRodney W. Grimes if (dolock) 655b8da2396SPoul-Henning Kamp vslock(old, oldlen); 656df8bae1dSRodney W. Grimes savelen = oldlen; 657df8bae1dSRodney W. Grimes } 658b396cd83SPoul-Henning Kamp 659b396cd83SPoul-Henning Kamp 660b8da2396SPoul-Henning Kamp error = (*fn)(name + 1, namelen - 1, old, &oldlen, 661b8da2396SPoul-Henning Kamp new, newlen, p); 6622e210993SPoul-Henning Kamp 6632e210993SPoul-Henning Kamp 664b8da2396SPoul-Henning Kamp if (old != NULL) { 665df8bae1dSRodney W. Grimes if (dolock) 666b8da2396SPoul-Henning Kamp vsunlock(old, savelen, B_WRITE); 667df8bae1dSRodney W. Grimes memlock.sl_lock = 0; 668df8bae1dSRodney W. Grimes if (memlock.sl_want) { 669df8bae1dSRodney W. Grimes memlock.sl_want = 0; 670df8bae1dSRodney W. Grimes wakeup((caddr_t)&memlock); 671df8bae1dSRodney W. Grimes } 672df8bae1dSRodney W. Grimes } 673787d58f2SPoul-Henning Kamp #if 0 674787d58f2SPoul-Henning Kamp if (error) { 675787d58f2SPoul-Henning Kamp printf("SYSCTL_ERROR: "); 676b8da2396SPoul-Henning Kamp for(i=0;i<namelen;i++) 677787d58f2SPoul-Henning Kamp printf("%d ", name[i]); 678787d58f2SPoul-Henning Kamp printf("= %d\n", error); 679787d58f2SPoul-Henning Kamp } 680787d58f2SPoul-Henning Kamp #endif 681df8bae1dSRodney W. Grimes if (error) 682df8bae1dSRodney W. Grimes return (error); 683b8da2396SPoul-Henning Kamp if (retval) 684df8bae1dSRodney W. Grimes *retval = oldlen; 685b8da2396SPoul-Henning Kamp return (error); 686df8bae1dSRodney W. Grimes } 687df8bae1dSRodney W. Grimes 688df8bae1dSRodney W. Grimes /* 689df8bae1dSRodney W. Grimes * Attributes stored in the kernel. 690df8bae1dSRodney W. Grimes */ 6916ae6a09bSGarrett Wollman int securelevel = -1; 692df8bae1dSRodney W. Grimes 693df8bae1dSRodney W. Grimes /* 694df8bae1dSRodney W. Grimes * kernel related system variables. 695df8bae1dSRodney W. Grimes */ 6963c8e79ddSBruce Evans static int 697df8bae1dSRodney W. Grimes kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 698df8bae1dSRodney W. Grimes int *name; 699df8bae1dSRodney W. Grimes u_int namelen; 700df8bae1dSRodney W. Grimes void *oldp; 701df8bae1dSRodney W. Grimes size_t *oldlenp; 702df8bae1dSRodney W. Grimes void *newp; 703df8bae1dSRodney W. Grimes size_t newlen; 704df8bae1dSRodney W. Grimes struct proc *p; 705df8bae1dSRodney W. Grimes { 7062e210993SPoul-Henning Kamp int error, level; 7075bb4f738SGarrett Wollman dev_t ndumpdev; 708df8bae1dSRodney W. Grimes 709df8bae1dSRodney W. Grimes /* all sysctl names at this level are terminal */ 7103f31c649SGarrett Wollman if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF 7113f31c649SGarrett Wollman || name[0] == KERN_NTP_PLL)) 712df8bae1dSRodney W. Grimes return (ENOTDIR); /* overloaded */ 713df8bae1dSRodney W. Grimes 714df8bae1dSRodney W. Grimes switch (name[0]) { 715b396cd83SPoul-Henning Kamp 716df8bae1dSRodney W. Grimes case KERN_SECURELVL: 717df8bae1dSRodney W. Grimes level = securelevel; 718df8bae1dSRodney W. Grimes if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 719df8bae1dSRodney W. Grimes newp == NULL) 720df8bae1dSRodney W. Grimes return (error); 721df8bae1dSRodney W. Grimes if (level < securelevel && p->p_pid != 1) 722df8bae1dSRodney W. Grimes return (EPERM); 723df8bae1dSRodney W. Grimes securelevel = level; 724df8bae1dSRodney W. Grimes return (0); 725df8bae1dSRodney W. Grimes case KERN_VNODE: 726df8bae1dSRodney W. Grimes return (sysctl_vnode(oldp, oldlenp)); 727df8bae1dSRodney W. Grimes case KERN_PROC: 728df8bae1dSRodney W. Grimes return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 729df8bae1dSRodney W. Grimes case KERN_FILE: 730df8bae1dSRodney W. Grimes return (sysctl_file(oldp, oldlenp)); 731df8bae1dSRodney W. Grimes #ifdef GPROF 732df8bae1dSRodney W. Grimes case KERN_PROF: 733df8bae1dSRodney W. Grimes return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 734df8bae1dSRodney W. Grimes newp, newlen)); 735df8bae1dSRodney W. Grimes #endif 7363f31c649SGarrett Wollman case KERN_NTP_PLL: 7373f31c649SGarrett Wollman return (ntp_sysctl(name + 1, namelen - 1, oldp, oldlenp, 7383f31c649SGarrett Wollman newp, newlen, p)); 7395bb4f738SGarrett Wollman case KERN_DUMPDEV: 7405bb4f738SGarrett Wollman ndumpdev = dumpdev; 7415bb4f738SGarrett Wollman error = sysctl_struct(oldp, oldlenp, newp, newlen, &ndumpdev, 7425bb4f738SGarrett Wollman sizeof ndumpdev); 7435bb4f738SGarrett Wollman if (!error && ndumpdev != dumpdev) { 7445bb4f738SGarrett Wollman error = setdumpdev(ndumpdev); 7455bb4f738SGarrett Wollman } 7465bb4f738SGarrett Wollman return error; 747df8bae1dSRodney W. Grimes default: 748df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 749df8bae1dSRodney W. Grimes } 750df8bae1dSRodney W. Grimes /* NOTREACHED */ 751df8bae1dSRodney W. Grimes } 752df8bae1dSRodney W. Grimes 753df8bae1dSRodney W. Grimes /* 754df8bae1dSRodney W. Grimes * hardware related system variables. 755df8bae1dSRodney W. Grimes */ 75626f9a767SRodney W. Grimes int 757df8bae1dSRodney W. Grimes hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 758df8bae1dSRodney W. Grimes int *name; 759df8bae1dSRodney W. Grimes u_int namelen; 760df8bae1dSRodney W. Grimes void *oldp; 761df8bae1dSRodney W. Grimes size_t *oldlenp; 762df8bae1dSRodney W. Grimes void *newp; 763df8bae1dSRodney W. Grimes size_t newlen; 764df8bae1dSRodney W. Grimes struct proc *p; 765df8bae1dSRodney W. Grimes { 7668478cabaSGarrett Wollman /* almost all sysctl names at this level are terminal */ 7678478cabaSGarrett Wollman if (namelen != 1 && name[0] != HW_DEVCONF) 768df8bae1dSRodney W. Grimes return (ENOTDIR); /* overloaded */ 769df8bae1dSRodney W. Grimes 770df8bae1dSRodney W. Grimes switch (name[0]) { 771df8bae1dSRodney W. Grimes case HW_PHYSMEM: 772df8bae1dSRodney W. Grimes return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 773df8bae1dSRodney W. Grimes case HW_USERMEM: 774df8bae1dSRodney W. Grimes return (sysctl_rdint(oldp, oldlenp, newp, 775df8bae1dSRodney W. Grimes ctob(physmem - cnt.v_wire_count))); 7768478cabaSGarrett Wollman case HW_DEVCONF: 7778478cabaSGarrett Wollman return (dev_sysctl(name + 1, namelen - 1, oldp, oldlenp, 7788478cabaSGarrett Wollman newp, newlen, p)); 779df8bae1dSRodney W. Grimes default: 780df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 781df8bae1dSRodney W. Grimes } 782df8bae1dSRodney W. Grimes /* NOTREACHED */ 783df8bae1dSRodney W. Grimes } 784df8bae1dSRodney W. Grimes 785df8bae1dSRodney W. Grimes #ifdef DEBUG 786df8bae1dSRodney W. Grimes /* 787df8bae1dSRodney W. Grimes * Debugging related system variables. 788df8bae1dSRodney W. Grimes */ 789df8bae1dSRodney W. Grimes struct ctldebug debug0, debug1, debug2, debug3, debug4; 790df8bae1dSRodney W. Grimes struct ctldebug debug5, debug6, debug7, debug8, debug9; 791df8bae1dSRodney W. Grimes struct ctldebug debug10, debug11, debug12, debug13, debug14; 792df8bae1dSRodney W. Grimes struct ctldebug debug15, debug16, debug17, debug18, debug19; 793df8bae1dSRodney W. Grimes static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 794df8bae1dSRodney W. Grimes &debug0, &debug1, &debug2, &debug3, &debug4, 795df8bae1dSRodney W. Grimes &debug5, &debug6, &debug7, &debug8, &debug9, 796df8bae1dSRodney W. Grimes &debug10, &debug11, &debug12, &debug13, &debug14, 797df8bae1dSRodney W. Grimes &debug15, &debug16, &debug17, &debug18, &debug19, 798df8bae1dSRodney W. Grimes }; 7996124ac44SBruce Evans static int 800df8bae1dSRodney W. Grimes debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 801df8bae1dSRodney W. Grimes int *name; 802df8bae1dSRodney W. Grimes u_int namelen; 803df8bae1dSRodney W. Grimes void *oldp; 804df8bae1dSRodney W. Grimes size_t *oldlenp; 805df8bae1dSRodney W. Grimes void *newp; 806df8bae1dSRodney W. Grimes size_t newlen; 807df8bae1dSRodney W. Grimes struct proc *p; 808df8bae1dSRodney W. Grimes { 809df8bae1dSRodney W. Grimes struct ctldebug *cdp; 810df8bae1dSRodney W. Grimes 811df8bae1dSRodney W. Grimes /* all sysctl names at this level are name and field */ 812df8bae1dSRodney W. Grimes if (namelen != 2) 813df8bae1dSRodney W. Grimes return (ENOTDIR); /* overloaded */ 814df8bae1dSRodney W. Grimes cdp = debugvars[name[0]]; 815df8bae1dSRodney W. Grimes if (cdp->debugname == 0) 816df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 817df8bae1dSRodney W. Grimes switch (name[1]) { 818df8bae1dSRodney W. Grimes case CTL_DEBUG_NAME: 819df8bae1dSRodney W. Grimes return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 820df8bae1dSRodney W. Grimes case CTL_DEBUG_VALUE: 821df8bae1dSRodney W. Grimes return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 822df8bae1dSRodney W. Grimes default: 823df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 824df8bae1dSRodney W. Grimes } 825df8bae1dSRodney W. Grimes /* NOTREACHED */ 826df8bae1dSRodney W. Grimes } 827df8bae1dSRodney W. Grimes #endif /* DEBUG */ 828df8bae1dSRodney W. Grimes 829df8bae1dSRodney W. Grimes /* 830df8bae1dSRodney W. Grimes * Validate parameters and get old / set new parameters 831df8bae1dSRodney W. Grimes * for an integer-valued sysctl function. 832df8bae1dSRodney W. Grimes */ 83326f9a767SRodney W. Grimes int 834df8bae1dSRodney W. Grimes sysctl_int(oldp, oldlenp, newp, newlen, valp) 835df8bae1dSRodney W. Grimes void *oldp; 836df8bae1dSRodney W. Grimes size_t *oldlenp; 837df8bae1dSRodney W. Grimes void *newp; 838df8bae1dSRodney W. Grimes size_t newlen; 839df8bae1dSRodney W. Grimes int *valp; 840df8bae1dSRodney W. Grimes { 841df8bae1dSRodney W. Grimes int error = 0; 842df8bae1dSRodney W. Grimes 843df8bae1dSRodney W. Grimes if (oldp && *oldlenp < sizeof(int)) 844df8bae1dSRodney W. Grimes return (ENOMEM); 845df8bae1dSRodney W. Grimes if (newp && newlen != sizeof(int)) 846df8bae1dSRodney W. Grimes return (EINVAL); 847df8bae1dSRodney W. Grimes *oldlenp = sizeof(int); 848df8bae1dSRodney W. Grimes if (oldp) 849df8bae1dSRodney W. Grimes error = copyout(valp, oldp, sizeof(int)); 850df8bae1dSRodney W. Grimes if (error == 0 && newp) 851df8bae1dSRodney W. Grimes error = copyin(newp, valp, sizeof(int)); 852df8bae1dSRodney W. Grimes return (error); 853df8bae1dSRodney W. Grimes } 854df8bae1dSRodney W. Grimes 855df8bae1dSRodney W. Grimes /* 856df8bae1dSRodney W. Grimes * As above, but read-only. 857df8bae1dSRodney W. Grimes */ 85826f9a767SRodney W. Grimes int 859df8bae1dSRodney W. Grimes sysctl_rdint(oldp, oldlenp, newp, val) 860df8bae1dSRodney W. Grimes void *oldp; 861df8bae1dSRodney W. Grimes size_t *oldlenp; 862df8bae1dSRodney W. Grimes void *newp; 863df8bae1dSRodney W. Grimes int val; 864df8bae1dSRodney W. Grimes { 865df8bae1dSRodney W. Grimes int error = 0; 866df8bae1dSRodney W. Grimes 867df8bae1dSRodney W. Grimes if (oldp && *oldlenp < sizeof(int)) 868df8bae1dSRodney W. Grimes return (ENOMEM); 869df8bae1dSRodney W. Grimes if (newp) 870df8bae1dSRodney W. Grimes return (EPERM); 871df8bae1dSRodney W. Grimes *oldlenp = sizeof(int); 872df8bae1dSRodney W. Grimes if (oldp) 873df8bae1dSRodney W. Grimes error = copyout((caddr_t)&val, oldp, sizeof(int)); 874df8bae1dSRodney W. Grimes return (error); 875df8bae1dSRodney W. Grimes } 876df8bae1dSRodney W. Grimes 877df8bae1dSRodney W. Grimes /* 878df8bae1dSRodney W. Grimes * Validate parameters and get old / set new parameters 879df8bae1dSRodney W. Grimes * for a string-valued sysctl function. 880df8bae1dSRodney W. Grimes */ 88126f9a767SRodney W. Grimes int 882df8bae1dSRodney W. Grimes sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 883df8bae1dSRodney W. Grimes void *oldp; 884df8bae1dSRodney W. Grimes size_t *oldlenp; 885df8bae1dSRodney W. Grimes void *newp; 886df8bae1dSRodney W. Grimes size_t newlen; 887df8bae1dSRodney W. Grimes char *str; 888df8bae1dSRodney W. Grimes int maxlen; 889df8bae1dSRodney W. Grimes { 890e1453736SMike Pritchard int len, error = 0, rval = 0; 891df8bae1dSRodney W. Grimes 892df8bae1dSRodney W. Grimes len = strlen(str) + 1; 893e1453736SMike Pritchard if (oldp && *oldlenp < len) { 894f81fcd41SGuido van Rooij len = *oldlenp; 895e1453736SMike Pritchard rval = ENOMEM; 896e1453736SMike Pritchard } 897df8bae1dSRodney W. Grimes if (newp && newlen >= maxlen) 898df8bae1dSRodney W. Grimes return (EINVAL); 899df8bae1dSRodney W. Grimes if (oldp) { 900df8bae1dSRodney W. Grimes *oldlenp = len; 901df8bae1dSRodney W. Grimes error = copyout(str, oldp, len); 902e1453736SMike Pritchard if (error) 903e1453736SMike Pritchard rval = error; 904df8bae1dSRodney W. Grimes } 905e1453736SMike Pritchard if ((error == 0 || error == ENOMEM) && newp) { 906df8bae1dSRodney W. Grimes error = copyin(newp, str, newlen); 907e1453736SMike Pritchard if (error) 908e1453736SMike Pritchard rval = error; 909df8bae1dSRodney W. Grimes str[newlen] = 0; 910df8bae1dSRodney W. Grimes } 911e1453736SMike Pritchard return (rval); 912df8bae1dSRodney W. Grimes } 913df8bae1dSRodney W. Grimes 914df8bae1dSRodney W. Grimes /* 915df8bae1dSRodney W. Grimes * As above, but read-only. 916df8bae1dSRodney W. Grimes */ 91726f9a767SRodney W. Grimes int 918df8bae1dSRodney W. Grimes sysctl_rdstring(oldp, oldlenp, newp, str) 919df8bae1dSRodney W. Grimes void *oldp; 920df8bae1dSRodney W. Grimes size_t *oldlenp; 921df8bae1dSRodney W. Grimes void *newp; 922df8bae1dSRodney W. Grimes char *str; 923df8bae1dSRodney W. Grimes { 924e1453736SMike Pritchard int len, error = 0, rval = 0; 925df8bae1dSRodney W. Grimes 926df8bae1dSRodney W. Grimes len = strlen(str) + 1; 927e1453736SMike Pritchard if (oldp && *oldlenp < len) { 928e1453736SMike Pritchard len = *oldlenp; 929e1453736SMike Pritchard rval = ENOMEM; 930e1453736SMike Pritchard } 931df8bae1dSRodney W. Grimes if (newp) 932df8bae1dSRodney W. Grimes return (EPERM); 933df8bae1dSRodney W. Grimes *oldlenp = len; 934df8bae1dSRodney W. Grimes if (oldp) 935df8bae1dSRodney W. Grimes error = copyout(str, oldp, len); 936e1453736SMike Pritchard if (error) 937e1453736SMike Pritchard rval = error; 938e1453736SMike Pritchard return (rval); 939df8bae1dSRodney W. Grimes } 940df8bae1dSRodney W. Grimes 941df8bae1dSRodney W. Grimes /* 942df8bae1dSRodney W. Grimes * Validate parameters and get old / set new parameters 943df8bae1dSRodney W. Grimes * for a structure oriented sysctl function. 944df8bae1dSRodney W. Grimes */ 94526f9a767SRodney W. Grimes int 946df8bae1dSRodney W. Grimes sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 947df8bae1dSRodney W. Grimes void *oldp; 948df8bae1dSRodney W. Grimes size_t *oldlenp; 949df8bae1dSRodney W. Grimes void *newp; 950df8bae1dSRodney W. Grimes size_t newlen; 951df8bae1dSRodney W. Grimes void *sp; 952df8bae1dSRodney W. Grimes int len; 953df8bae1dSRodney W. Grimes { 954df8bae1dSRodney W. Grimes int error = 0; 955df8bae1dSRodney W. Grimes 956df8bae1dSRodney W. Grimes if (oldp && *oldlenp < len) 957df8bae1dSRodney W. Grimes return (ENOMEM); 958df8bae1dSRodney W. Grimes if (newp && newlen > len) 959df8bae1dSRodney W. Grimes return (EINVAL); 960df8bae1dSRodney W. Grimes if (oldp) { 961df8bae1dSRodney W. Grimes *oldlenp = len; 962df8bae1dSRodney W. Grimes error = copyout(sp, oldp, len); 963df8bae1dSRodney W. Grimes } 964df8bae1dSRodney W. Grimes if (error == 0 && newp) 965df8bae1dSRodney W. Grimes error = copyin(newp, sp, len); 966df8bae1dSRodney W. Grimes return (error); 967df8bae1dSRodney W. Grimes } 968df8bae1dSRodney W. Grimes 969df8bae1dSRodney W. Grimes /* 970df8bae1dSRodney W. Grimes * Validate parameters and get old parameters 971df8bae1dSRodney W. Grimes * for a structure oriented sysctl function. 972df8bae1dSRodney W. Grimes */ 97326f9a767SRodney W. Grimes int 974df8bae1dSRodney W. Grimes sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 975df8bae1dSRodney W. Grimes void *oldp; 976df8bae1dSRodney W. Grimes size_t *oldlenp; 977df8bae1dSRodney W. Grimes void *newp, *sp; 978df8bae1dSRodney W. Grimes int len; 979df8bae1dSRodney W. Grimes { 980df8bae1dSRodney W. Grimes int error = 0; 981df8bae1dSRodney W. Grimes 982df8bae1dSRodney W. Grimes if (oldp && *oldlenp < len) 983df8bae1dSRodney W. Grimes return (ENOMEM); 984df8bae1dSRodney W. Grimes if (newp) 985df8bae1dSRodney W. Grimes return (EPERM); 986df8bae1dSRodney W. Grimes *oldlenp = len; 987df8bae1dSRodney W. Grimes if (oldp) 988df8bae1dSRodney W. Grimes error = copyout(sp, oldp, len); 989df8bae1dSRodney W. Grimes return (error); 990df8bae1dSRodney W. Grimes } 991df8bae1dSRodney W. Grimes 992df8bae1dSRodney W. Grimes /* 993df8bae1dSRodney W. Grimes * Get file structures. 994df8bae1dSRodney W. Grimes */ 99526f9a767SRodney W. Grimes int 996df8bae1dSRodney W. Grimes sysctl_file(where, sizep) 997df8bae1dSRodney W. Grimes char *where; 998df8bae1dSRodney W. Grimes size_t *sizep; 999df8bae1dSRodney W. Grimes { 1000df8bae1dSRodney W. Grimes int buflen, error; 1001df8bae1dSRodney W. Grimes struct file *fp; 1002df8bae1dSRodney W. Grimes char *start = where; 1003df8bae1dSRodney W. Grimes 1004df8bae1dSRodney W. Grimes buflen = *sizep; 1005df8bae1dSRodney W. Grimes if (where == NULL) { 1006df8bae1dSRodney W. Grimes /* 1007df8bae1dSRodney W. Grimes * overestimate by 10 files 1008df8bae1dSRodney W. Grimes */ 1009df8bae1dSRodney W. Grimes *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 1010df8bae1dSRodney W. Grimes return (0); 1011df8bae1dSRodney W. Grimes } 1012df8bae1dSRodney W. Grimes 1013df8bae1dSRodney W. Grimes /* 1014df8bae1dSRodney W. Grimes * first copyout filehead 1015df8bae1dSRodney W. Grimes */ 1016df8bae1dSRodney W. Grimes if (buflen < sizeof(filehead)) { 1017df8bae1dSRodney W. Grimes *sizep = 0; 1018df8bae1dSRodney W. Grimes return (0); 1019df8bae1dSRodney W. Grimes } 1020797f2d22SPoul-Henning Kamp error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 1021797f2d22SPoul-Henning Kamp if (error) 1022df8bae1dSRodney W. Grimes return (error); 1023df8bae1dSRodney W. Grimes buflen -= sizeof(filehead); 1024df8bae1dSRodney W. Grimes where += sizeof(filehead); 1025df8bae1dSRodney W. Grimes 1026df8bae1dSRodney W. Grimes /* 1027df8bae1dSRodney W. Grimes * followed by an array of file structures 1028df8bae1dSRodney W. Grimes */ 1029df8bae1dSRodney W. Grimes for (fp = filehead; fp != NULL; fp = fp->f_filef) { 1030df8bae1dSRodney W. Grimes if (buflen < sizeof(struct file)) { 1031df8bae1dSRodney W. Grimes *sizep = where - start; 1032df8bae1dSRodney W. Grimes return (ENOMEM); 1033df8bae1dSRodney W. Grimes } 1034797f2d22SPoul-Henning Kamp error = copyout((caddr_t)fp, where, sizeof (struct file)); 1035797f2d22SPoul-Henning Kamp if (error) 1036df8bae1dSRodney W. Grimes return (error); 1037df8bae1dSRodney W. Grimes buflen -= sizeof(struct file); 1038df8bae1dSRodney W. Grimes where += sizeof(struct file); 1039df8bae1dSRodney W. Grimes } 1040df8bae1dSRodney W. Grimes *sizep = where - start; 1041df8bae1dSRodney W. Grimes return (0); 1042df8bae1dSRodney W. Grimes } 1043df8bae1dSRodney W. Grimes 1044df8bae1dSRodney W. Grimes /* 1045df8bae1dSRodney W. Grimes * try over estimating by 5 procs 1046df8bae1dSRodney W. Grimes */ 1047df8bae1dSRodney W. Grimes #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 1048df8bae1dSRodney W. Grimes 104926f9a767SRodney W. Grimes int 1050df8bae1dSRodney W. Grimes sysctl_doproc(name, namelen, where, sizep) 1051df8bae1dSRodney W. Grimes int *name; 1052df8bae1dSRodney W. Grimes u_int namelen; 1053df8bae1dSRodney W. Grimes char *where; 1054df8bae1dSRodney W. Grimes size_t *sizep; 1055df8bae1dSRodney W. Grimes { 1056df8bae1dSRodney W. Grimes register struct proc *p; 1057df8bae1dSRodney W. Grimes register struct kinfo_proc *dp = (struct kinfo_proc *)where; 1058df8bae1dSRodney W. Grimes register int needed = 0; 1059df8bae1dSRodney W. Grimes int buflen = where != NULL ? *sizep : 0; 1060df8bae1dSRodney W. Grimes int doingzomb; 1061df8bae1dSRodney W. Grimes struct eproc eproc; 1062df8bae1dSRodney W. Grimes int error = 0; 1063df8bae1dSRodney W. Grimes 1064df8bae1dSRodney W. Grimes if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 1065df8bae1dSRodney W. Grimes return (EINVAL); 1066df8bae1dSRodney W. Grimes p = (struct proc *)allproc; 1067df8bae1dSRodney W. Grimes doingzomb = 0; 1068df8bae1dSRodney W. Grimes again: 1069df8bae1dSRodney W. Grimes for (; p != NULL; p = p->p_next) { 1070df8bae1dSRodney W. Grimes /* 1071df8bae1dSRodney W. Grimes * Skip embryonic processes. 1072df8bae1dSRodney W. Grimes */ 1073df8bae1dSRodney W. Grimes if (p->p_stat == SIDL) 1074df8bae1dSRodney W. Grimes continue; 1075df8bae1dSRodney W. Grimes /* 1076df8bae1dSRodney W. Grimes * TODO - make more efficient (see notes below). 1077df8bae1dSRodney W. Grimes * do by session. 1078df8bae1dSRodney W. Grimes */ 1079df8bae1dSRodney W. Grimes switch (name[0]) { 1080df8bae1dSRodney W. Grimes 1081df8bae1dSRodney W. Grimes case KERN_PROC_PID: 1082df8bae1dSRodney W. Grimes /* could do this with just a lookup */ 1083df8bae1dSRodney W. Grimes if (p->p_pid != (pid_t)name[1]) 1084df8bae1dSRodney W. Grimes continue; 1085df8bae1dSRodney W. Grimes break; 1086df8bae1dSRodney W. Grimes 1087df8bae1dSRodney W. Grimes case KERN_PROC_PGRP: 1088df8bae1dSRodney W. Grimes /* could do this by traversing pgrp */ 1089be6a1d14SDavid Greenman if (p->p_pgrp == NULL || p->p_pgrp->pg_id != (pid_t)name[1]) 1090df8bae1dSRodney W. Grimes continue; 1091df8bae1dSRodney W. Grimes break; 1092df8bae1dSRodney W. Grimes 1093df8bae1dSRodney W. Grimes case KERN_PROC_TTY: 1094df8bae1dSRodney W. Grimes if ((p->p_flag & P_CONTROLT) == 0 || 1095be6a1d14SDavid Greenman p->p_session == NULL || 1096df8bae1dSRodney W. Grimes p->p_session->s_ttyp == NULL || 1097df8bae1dSRodney W. Grimes p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 1098df8bae1dSRodney W. Grimes continue; 1099df8bae1dSRodney W. Grimes break; 1100df8bae1dSRodney W. Grimes 1101df8bae1dSRodney W. Grimes case KERN_PROC_UID: 1102be6a1d14SDavid Greenman if (p->p_ucred == NULL || p->p_ucred->cr_uid != (uid_t)name[1]) 1103df8bae1dSRodney W. Grimes continue; 1104df8bae1dSRodney W. Grimes break; 1105df8bae1dSRodney W. Grimes 1106df8bae1dSRodney W. Grimes case KERN_PROC_RUID: 1107be6a1d14SDavid Greenman if (p->p_ucred == NULL || p->p_cred->p_ruid != (uid_t)name[1]) 1108df8bae1dSRodney W. Grimes continue; 1109df8bae1dSRodney W. Grimes break; 1110df8bae1dSRodney W. Grimes } 1111df8bae1dSRodney W. Grimes if (buflen >= sizeof(struct kinfo_proc)) { 1112df8bae1dSRodney W. Grimes fill_eproc(p, &eproc); 1113797f2d22SPoul-Henning Kamp error = copyout((caddr_t)p, &dp->kp_proc, 1114797f2d22SPoul-Henning Kamp sizeof(struct proc)); 1115797f2d22SPoul-Henning Kamp if (error) 1116df8bae1dSRodney W. Grimes return (error); 1117797f2d22SPoul-Henning Kamp error = copyout((caddr_t)&eproc, &dp->kp_eproc, 1118797f2d22SPoul-Henning Kamp sizeof(eproc)); 1119797f2d22SPoul-Henning Kamp if (error) 1120df8bae1dSRodney W. Grimes return (error); 1121df8bae1dSRodney W. Grimes dp++; 1122df8bae1dSRodney W. Grimes buflen -= sizeof(struct kinfo_proc); 1123df8bae1dSRodney W. Grimes } 1124df8bae1dSRodney W. Grimes needed += sizeof(struct kinfo_proc); 1125df8bae1dSRodney W. Grimes } 1126df8bae1dSRodney W. Grimes if (doingzomb == 0) { 1127df8bae1dSRodney W. Grimes p = zombproc; 1128df8bae1dSRodney W. Grimes doingzomb++; 1129df8bae1dSRodney W. Grimes goto again; 1130df8bae1dSRodney W. Grimes } 1131df8bae1dSRodney W. Grimes if (where != NULL) { 1132df8bae1dSRodney W. Grimes *sizep = (caddr_t)dp - where; 1133df8bae1dSRodney W. Grimes if (needed > *sizep) 1134df8bae1dSRodney W. Grimes return (ENOMEM); 1135df8bae1dSRodney W. Grimes } else { 1136df8bae1dSRodney W. Grimes needed += KERN_PROCSLOP; 1137df8bae1dSRodney W. Grimes *sizep = needed; 1138df8bae1dSRodney W. Grimes } 1139df8bae1dSRodney W. Grimes return (0); 1140df8bae1dSRodney W. Grimes } 1141df8bae1dSRodney W. Grimes 1142df8bae1dSRodney W. Grimes /* 1143df8bae1dSRodney W. Grimes * Fill in an eproc structure for the specified process. 1144df8bae1dSRodney W. Grimes */ 1145df8bae1dSRodney W. Grimes void 1146df8bae1dSRodney W. Grimes fill_eproc(p, ep) 1147df8bae1dSRodney W. Grimes register struct proc *p; 1148df8bae1dSRodney W. Grimes register struct eproc *ep; 1149df8bae1dSRodney W. Grimes { 1150df8bae1dSRodney W. Grimes register struct tty *tp; 1151df8bae1dSRodney W. Grimes 1152be6a1d14SDavid Greenman bzero(ep, sizeof(*ep)); 1153be6a1d14SDavid Greenman 1154df8bae1dSRodney W. Grimes ep->e_paddr = p; 11551c8fc26cSDavid Greenman if (p->p_cred) { 1156df8bae1dSRodney W. Grimes ep->e_pcred = *p->p_cred; 1157be6a1d14SDavid Greenman if (p->p_ucred) 1158df8bae1dSRodney W. Grimes ep->e_ucred = *p->p_ucred; 11591c8fc26cSDavid Greenman } 11601c8fc26cSDavid Greenman if (p->p_stat != SIDL && p->p_stat != SZOMB && p->p_vmspace != NULL) { 1161df8bae1dSRodney W. Grimes register struct vmspace *vm = p->p_vmspace; 1162df8bae1dSRodney W. Grimes 1163df8bae1dSRodney W. Grimes #ifdef pmap_resident_count 1164df8bae1dSRodney W. Grimes ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/ 1165df8bae1dSRodney W. Grimes #else 1166df8bae1dSRodney W. Grimes ep->e_vm.vm_rssize = vm->vm_rssize; 1167df8bae1dSRodney W. Grimes #endif 1168df8bae1dSRodney W. Grimes ep->e_vm.vm_tsize = vm->vm_tsize; 1169df8bae1dSRodney W. Grimes ep->e_vm.vm_dsize = vm->vm_dsize; 1170df8bae1dSRodney W. Grimes ep->e_vm.vm_ssize = vm->vm_ssize; 1171df8bae1dSRodney W. Grimes #ifndef sparc 1172df8bae1dSRodney W. Grimes ep->e_vm.vm_pmap = vm->vm_pmap; 1173df8bae1dSRodney W. Grimes #endif 1174df8bae1dSRodney W. Grimes } 1175df8bae1dSRodney W. Grimes if (p->p_pptr) 1176df8bae1dSRodney W. Grimes ep->e_ppid = p->p_pptr->p_pid; 1177be6a1d14SDavid Greenman if (p->p_pgrp) { 1178be6a1d14SDavid Greenman ep->e_sess = p->p_pgrp->pg_session; 1179df8bae1dSRodney W. Grimes ep->e_pgid = p->p_pgrp->pg_id; 1180df8bae1dSRodney W. Grimes ep->e_jobc = p->p_pgrp->pg_jobc; 1181be6a1d14SDavid Greenman } 1182df8bae1dSRodney W. Grimes if ((p->p_flag & P_CONTROLT) && 1183be6a1d14SDavid Greenman (ep->e_sess != NULL) && 1184be6a1d14SDavid Greenman ((tp = ep->e_sess->s_ttyp) != NULL)) { 1185df8bae1dSRodney W. Grimes ep->e_tdev = tp->t_dev; 1186df8bae1dSRodney W. Grimes ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1187df8bae1dSRodney W. Grimes ep->e_tsess = tp->t_session; 1188df8bae1dSRodney W. Grimes } else 1189df8bae1dSRodney W. Grimes ep->e_tdev = NODEV; 1190be6a1d14SDavid Greenman if (ep->e_sess && ep->e_sess->s_ttyvp) 1191be6a1d14SDavid Greenman ep->e_flag = EPROC_CTTY; 1192df8bae1dSRodney W. Grimes if (SESS_LEADER(p)) 1193df8bae1dSRodney W. Grimes ep->e_flag |= EPROC_SLEADER; 1194be6a1d14SDavid Greenman if (p->p_wmesg) { 1195df8bae1dSRodney W. Grimes strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 1196be6a1d14SDavid Greenman ep->e_wmesg[WMESGLEN] = 0; 1197be6a1d14SDavid Greenman } 1198df8bae1dSRodney W. Grimes } 1199df8bae1dSRodney W. Grimes 1200df8bae1dSRodney W. Grimes #ifdef COMPAT_43 1201df8bae1dSRodney W. Grimes #include <sys/socket.h> 1202df8bae1dSRodney W. Grimes #define KINFO_PROC (0<<8) 1203df8bae1dSRodney W. Grimes #define KINFO_RT (1<<8) 1204df8bae1dSRodney W. Grimes #define KINFO_VNODE (2<<8) 1205df8bae1dSRodney W. Grimes #define KINFO_FILE (3<<8) 1206df8bae1dSRodney W. Grimes #define KINFO_METER (4<<8) 1207df8bae1dSRodney W. Grimes #define KINFO_LOADAVG (5<<8) 1208df8bae1dSRodney W. Grimes #define KINFO_CLOCKRATE (6<<8) 1209df8bae1dSRodney W. Grimes 12106ece4a51SPeter Wemm /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ 12116ece4a51SPeter Wemm #define KINFO_BSDI_SYSINFO (101<<8) 12126ece4a51SPeter Wemm 12136ece4a51SPeter Wemm /* 12146ece4a51SPeter Wemm * XXX this is bloat, but I hope it's better here than on the potentially 12156ece4a51SPeter Wemm * limited kernel stack... -Peter 12166ece4a51SPeter Wemm */ 12176ece4a51SPeter Wemm 12186ece4a51SPeter Wemm struct { 12196ece4a51SPeter Wemm int bsdi_machine; /* "i386" on BSD/386 */ 12206ece4a51SPeter Wemm /* ^^^ this is an offset to the string, relative to the struct start */ 12216ece4a51SPeter Wemm char *pad0; 12226ece4a51SPeter Wemm long pad1; 12236ece4a51SPeter Wemm long pad2; 12246ece4a51SPeter Wemm long pad3; 12256ece4a51SPeter Wemm u_long pad4; 12266ece4a51SPeter Wemm u_long pad5; 12276ece4a51SPeter Wemm u_long pad6; 12286ece4a51SPeter Wemm 12296ece4a51SPeter Wemm int bsdi_ostype; /* "BSD/386" on BSD/386 */ 12306ece4a51SPeter Wemm int bsdi_osrelease; /* "1.1" on BSD/386 */ 12316ece4a51SPeter Wemm long pad7; 12326ece4a51SPeter Wemm long pad8; 12336ece4a51SPeter Wemm char *pad9; 12346ece4a51SPeter Wemm 12356ece4a51SPeter Wemm long pad10; 12366ece4a51SPeter Wemm long pad11; 12376ece4a51SPeter Wemm int pad12; 12386ece4a51SPeter Wemm long pad13; 12396ece4a51SPeter Wemm quad_t pad14; 12406ece4a51SPeter Wemm long pad15; 12416ece4a51SPeter Wemm 12426ece4a51SPeter Wemm struct timeval pad16; 12436ece4a51SPeter Wemm /* we dont set this, because BSDI's uname used gethostname() instead */ 12446ece4a51SPeter Wemm int bsdi_hostname; /* hostname on BSD/386 */ 12456ece4a51SPeter Wemm 12466ece4a51SPeter Wemm /* the actual string data is appended here */ 12476ece4a51SPeter Wemm 12486ece4a51SPeter Wemm } bsdi_si; 12496ece4a51SPeter Wemm /* 12506ece4a51SPeter Wemm * this data is appended to the end of the bsdi_si structure during copyout. 12516ece4a51SPeter Wemm * The "char *" offsets are relative to the base of the bsdi_si struct. 12526ece4a51SPeter Wemm * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings 12536ece4a51SPeter Wemm * should not exceed the length of the buffer here... (or else!! :-) 12546ece4a51SPeter Wemm */ 12556ece4a51SPeter Wemm char bsdi_strings[80]; /* It had better be less than this! */ 12566ece4a51SPeter Wemm 1257d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1258df8bae1dSRodney W. Grimes struct getkerninfo_args { 1259df8bae1dSRodney W. Grimes int op; 1260df8bae1dSRodney W. Grimes char *where; 1261df8bae1dSRodney W. Grimes int *size; 1262df8bae1dSRodney W. Grimes int arg; 1263df8bae1dSRodney W. Grimes }; 1264d2d3e875SBruce Evans #endif 1265df8bae1dSRodney W. Grimes 126626f9a767SRodney W. Grimes int 1267df8bae1dSRodney W. Grimes ogetkerninfo(p, uap, retval) 1268df8bae1dSRodney W. Grimes struct proc *p; 1269df8bae1dSRodney W. Grimes register struct getkerninfo_args *uap; 1270df8bae1dSRodney W. Grimes int *retval; 1271df8bae1dSRodney W. Grimes { 1272b8da2396SPoul-Henning Kamp int error, name[6]; 1273df8bae1dSRodney W. Grimes u_int size; 1274df8bae1dSRodney W. Grimes 1275df8bae1dSRodney W. Grimes switch (uap->op & 0xff00) { 1276df8bae1dSRodney W. Grimes 1277df8bae1dSRodney W. Grimes case KINFO_RT: 1278b8da2396SPoul-Henning Kamp name[0] = CTL_NET; 1279b8da2396SPoul-Henning Kamp name[1] = PF_ROUTE; 1280b8da2396SPoul-Henning Kamp name[2] = 0; 1281b8da2396SPoul-Henning Kamp name[3] = (uap->op & 0xff0000) >> 16; 1282b8da2396SPoul-Henning Kamp name[4] = uap->op & 0xff; 1283b8da2396SPoul-Henning Kamp name[5] = uap->arg; 1284b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 6, uap->where, uap->size, 1285b8da2396SPoul-Henning Kamp 0, 0, 0, 0); 1286df8bae1dSRodney W. Grimes break; 1287df8bae1dSRodney W. Grimes 1288df8bae1dSRodney W. Grimes case KINFO_VNODE: 1289b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1290b8da2396SPoul-Henning Kamp name[1] = KERN_VNODE; 1291b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 1292b8da2396SPoul-Henning Kamp 0, 0, 0, 0); 1293df8bae1dSRodney W. Grimes break; 1294df8bae1dSRodney W. Grimes 1295df8bae1dSRodney W. Grimes case KINFO_PROC: 1296b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1297b8da2396SPoul-Henning Kamp name[1] = KERN_PROC; 1298b8da2396SPoul-Henning Kamp name[2] = uap->op & 0xff; 1299b8da2396SPoul-Henning Kamp name[3] = uap->arg; 1300b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 4, uap->where, uap->size, 1301b8da2396SPoul-Henning Kamp 0, 0, 0, 0); 1302df8bae1dSRodney W. Grimes break; 1303df8bae1dSRodney W. Grimes 1304df8bae1dSRodney W. Grimes case KINFO_FILE: 1305b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1306b8da2396SPoul-Henning Kamp name[1] = KERN_FILE; 1307b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 1308b8da2396SPoul-Henning Kamp 0, 0, 0, 0); 1309df8bae1dSRodney W. Grimes break; 1310df8bae1dSRodney W. Grimes 1311df8bae1dSRodney W. Grimes case KINFO_METER: 1312b8da2396SPoul-Henning Kamp name[0] = CTL_VM; 1313b8da2396SPoul-Henning Kamp name[1] = VM_METER; 1314b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 1315b8da2396SPoul-Henning Kamp 0, 0, 0, 0); 1316df8bae1dSRodney W. Grimes break; 1317df8bae1dSRodney W. Grimes 1318df8bae1dSRodney W. Grimes case KINFO_LOADAVG: 1319b8da2396SPoul-Henning Kamp name[0] = CTL_VM; 1320b8da2396SPoul-Henning Kamp name[1] = VM_LOADAVG; 1321b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 1322b8da2396SPoul-Henning Kamp 0, 0, 0, 0); 1323df8bae1dSRodney W. Grimes break; 1324df8bae1dSRodney W. Grimes 1325df8bae1dSRodney W. Grimes case KINFO_CLOCKRATE: 1326b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1327b8da2396SPoul-Henning Kamp name[1] = KERN_CLOCKRATE; 1328b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 1329b8da2396SPoul-Henning Kamp 0, 0, 0, 0); 1330df8bae1dSRodney W. Grimes break; 1331df8bae1dSRodney W. Grimes 13326ece4a51SPeter Wemm case KINFO_BSDI_SYSINFO: { 13336ece4a51SPeter Wemm /* 13346ece4a51SPeter Wemm * this is pretty crude, but it's just enough for uname() 13356ece4a51SPeter Wemm * from BSDI's 1.x libc to work. 13366ece4a51SPeter Wemm * 13376ece4a51SPeter Wemm * In particular, it doesn't return the same results when 13386ece4a51SPeter Wemm * the supplied buffer is too small. BSDI's version apparently 13396ece4a51SPeter Wemm * will return the amount copied, and set the *size to how 13406ece4a51SPeter Wemm * much was needed. The emulation framework here isn't capable 13416ece4a51SPeter Wemm * of that, so we just set both to the amount copied. 13426ece4a51SPeter Wemm * BSDI's 2.x product apparently fails with ENOMEM in this 13436ece4a51SPeter Wemm * scenario. 13446ece4a51SPeter Wemm */ 13456ece4a51SPeter Wemm 13466ece4a51SPeter Wemm u_int needed; 13476ece4a51SPeter Wemm u_int left; 13486ece4a51SPeter Wemm char *s; 13496ece4a51SPeter Wemm 13506ece4a51SPeter Wemm bzero((char *)&bsdi_si, sizeof(bsdi_si)); 13516ece4a51SPeter Wemm bzero(bsdi_strings, sizeof(bsdi_strings)); 13526ece4a51SPeter Wemm 13536ece4a51SPeter Wemm s = bsdi_strings; 13546ece4a51SPeter Wemm 13556ece4a51SPeter Wemm bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); 13566ece4a51SPeter Wemm strcpy(s, ostype); 13576ece4a51SPeter Wemm s += strlen(s) + 1; 13586ece4a51SPeter Wemm 13596ece4a51SPeter Wemm bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); 13606ece4a51SPeter Wemm strcpy(s, osrelease); 13616ece4a51SPeter Wemm s += strlen(s) + 1; 13626ece4a51SPeter Wemm 13636ece4a51SPeter Wemm bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); 13646ece4a51SPeter Wemm strcpy(s, machine); 13656ece4a51SPeter Wemm s += strlen(s) + 1; 13666ece4a51SPeter Wemm 13676ece4a51SPeter Wemm needed = sizeof(bsdi_si) + (s - bsdi_strings); 13686ece4a51SPeter Wemm 13696ece4a51SPeter Wemm if (uap->where == NULL) { 13706ece4a51SPeter Wemm /* process is asking how much buffer to supply.. */ 13716ece4a51SPeter Wemm size = needed; 13726ece4a51SPeter Wemm error = 0; 13736ece4a51SPeter Wemm break; 13746ece4a51SPeter Wemm } 13756ece4a51SPeter Wemm 13766ece4a51SPeter Wemm 13776ece4a51SPeter Wemm /* if too much buffer supplied, trim it down */ 13786ece4a51SPeter Wemm if (size > needed) 13796ece4a51SPeter Wemm size = needed; 13806ece4a51SPeter Wemm 13816ece4a51SPeter Wemm /* how much of the buffer is remaining */ 13826ece4a51SPeter Wemm left = size; 13836ece4a51SPeter Wemm 13846ece4a51SPeter Wemm if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) 13856ece4a51SPeter Wemm break; 13866ece4a51SPeter Wemm 13876ece4a51SPeter Wemm /* is there any point in continuing? */ 13886ece4a51SPeter Wemm if (left > sizeof(bsdi_si)) { 13896ece4a51SPeter Wemm left -= sizeof(bsdi_si); 13906ece4a51SPeter Wemm error = copyout(&bsdi_strings, 13916ece4a51SPeter Wemm uap->where + sizeof(bsdi_si), left); 13926ece4a51SPeter Wemm } 13936ece4a51SPeter Wemm break; 13946ece4a51SPeter Wemm } 13956ece4a51SPeter Wemm 1396df8bae1dSRodney W. Grimes default: 1397df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 1398df8bae1dSRodney W. Grimes } 1399df8bae1dSRodney W. Grimes if (error) 1400df8bae1dSRodney W. Grimes return (error); 1401df8bae1dSRodney W. Grimes *retval = size; 1402df8bae1dSRodney W. Grimes if (uap->size) 1403df8bae1dSRodney W. Grimes error = copyout((caddr_t)&size, (caddr_t)uap->size, 1404df8bae1dSRodney W. Grimes sizeof(size)); 1405df8bae1dSRodney W. Grimes return (error); 1406df8bae1dSRodney W. Grimes } 1407df8bae1dSRodney W. Grimes #endif /* COMPAT_43 */ 1408