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 37787d58f2SPoul-Henning Kamp * $Id: kern_sysctl.c,v 1.31 1995/11/06 16:18:52 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> 46df8bae1dSRodney W. Grimes #include <sys/kernel.h> 47df8bae1dSRodney W. Grimes #include <sys/malloc.h> 48df8bae1dSRodney W. Grimes #include <sys/proc.h> 49df8bae1dSRodney W. Grimes #include <sys/file.h> 50df8bae1dSRodney W. Grimes #include <sys/vnode.h> 51df8bae1dSRodney W. Grimes #include <sys/unistd.h> 52df8bae1dSRodney W. Grimes #include <sys/buf.h> 53df8bae1dSRodney W. Grimes #include <sys/ioctl.h> 54df8bae1dSRodney W. Grimes #include <sys/tty.h> 555bb4f738SGarrett Wollman #include <sys/conf.h> 56df8bae1dSRodney W. Grimes #include <vm/vm.h> 57df8bae1dSRodney W. Grimes #include <sys/sysctl.h> 583a34a5c3SPoul-Henning Kamp #include <sys/user.h> 59df8bae1dSRodney W. Grimes 60787d58f2SPoul-Henning Kamp extern struct linker_set sysctl_; 61787d58f2SPoul-Henning Kamp 62b396cd83SPoul-Henning Kamp /* BEGIN_MIB */ 63787d58f2SPoul-Henning Kamp SYSCTL_NODE(, 0, sysctl, CTLFLAG_RW, 0, 64787d58f2SPoul-Henning Kamp "Sysctl internal magic"); 652e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_KERN, kern, CTLFLAG_RW, 0, 662e210993SPoul-Henning Kamp "High kernel, proc, limits &c"); 672e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_VM, vm, CTLFLAG_RW, 0, 682e210993SPoul-Henning Kamp "Virtual memory"); 692e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_FS, fs, CTLFLAG_RW, 0, 702e210993SPoul-Henning Kamp "File system"); 712e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_NET, net, CTLFLAG_RW, 0, 722e210993SPoul-Henning Kamp "Network, (see socket.h)"); 732e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_DEBUG, debug, CTLFLAG_RW, 0, 742e210993SPoul-Henning Kamp "Debugging"); 752e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_HW, hw, CTLFLAG_RW, 0, 762e210993SPoul-Henning Kamp "hardware"); 772e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_MACHDEP, machdep, CTLFLAG_RW, 0, 782e210993SPoul-Henning Kamp "machine dependent"); 792e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW, 0, 802e210993SPoul-Henning Kamp "user-level"); 81b396cd83SPoul-Henning Kamp 822e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD, osrelease, 0, ""); 83b396cd83SPoul-Henning Kamp 842e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD, 0, BSD, ""); 85b396cd83SPoul-Henning Kamp 862e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD, version, 0, ""); 87b396cd83SPoul-Henning Kamp 882e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD, ostype, 0, ""); 89b396cd83SPoul-Henning Kamp 90b396cd83SPoul-Henning Kamp extern int osreldate; 912e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD, &osreldate, 0, ""); 92b396cd83SPoul-Henning Kamp 932e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXVNODES, maxvnodes, CTLFLAG_RD, &desiredvnodes, 0, ""); 94b396cd83SPoul-Henning Kamp 952e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXPROC, maxproc, CTLFLAG_RD, &maxproc, 0, ""); 96b396cd83SPoul-Henning Kamp 97b396cd83SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXPROCPERUID, maxprocperuid, 983a34a5c3SPoul-Henning Kamp CTLFLAG_RD, &maxprocperuid, 0, ""); 99b396cd83SPoul-Henning Kamp 100b396cd83SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXFILESPERPROC, maxfilesperproc, 1013a34a5c3SPoul-Henning Kamp CTLFLAG_RD, &maxfilesperproc, 0, ""); 102b396cd83SPoul-Henning Kamp 1032e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_ARGMAX, argmax, CTLFLAG_RD, 0, ARG_MAX, ""); 104b396cd83SPoul-Henning Kamp 1052e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD, 0, _POSIX_VERSION, ""); 106b396cd83SPoul-Henning Kamp 1072e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RD, 0, NGROUPS_MAX, ""); 108b396cd83SPoul-Henning Kamp 1092e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control, CTLFLAG_RD, 0, 1, ""); 110b396cd83SPoul-Henning Kamp 1112e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXFILES, maxfiles, CTLFLAG_RW, &maxfiles, 0, ""); 112b396cd83SPoul-Henning Kamp 113b396cd83SPoul-Henning Kamp #ifdef _POSIX_SAVED_IDS 1142e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 1, ""); 115b396cd83SPoul-Henning Kamp #else 1162e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 0, ""); 117b396cd83SPoul-Henning Kamp #endif 118b396cd83SPoul-Henning Kamp 119b396cd83SPoul-Henning Kamp char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */ 120b396cd83SPoul-Henning Kamp 121b396cd83SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, 1223a34a5c3SPoul-Henning Kamp CTLFLAG_RW, kernelname, sizeof kernelname, ""); 123b396cd83SPoul-Henning Kamp 124b396cd83SPoul-Henning Kamp SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime, 1253a34a5c3SPoul-Henning Kamp CTLFLAG_RW, &boottime, timeval, ""); 126b396cd83SPoul-Henning Kamp 1272e210993SPoul-Henning Kamp SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 128b396cd83SPoul-Henning Kamp 129787d58f2SPoul-Henning Kamp SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, ""); 130b396cd83SPoul-Henning Kamp 1312e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD, 0, 1, ""); 132b396cd83SPoul-Henning Kamp 1332e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD, 0, BYTE_ORDER, ""); 134b396cd83SPoul-Henning Kamp 1352e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_PAGESIZE, pagesize, CTLFLAG_RD, 0, PAGE_SIZE, ""); 136b396cd83SPoul-Henning Kamp 137b396cd83SPoul-Henning Kamp /* END_MIB */ 138b396cd83SPoul-Henning Kamp 139b396cd83SPoul-Henning Kamp extern int vfs_update_wakeup; 140b396cd83SPoul-Henning Kamp extern int vfs_update_interval; 141b396cd83SPoul-Henning Kamp static int 1423a34a5c3SPoul-Henning Kamp sysctl_kern_updateinterval SYSCTL_HANDLER_ARGS 143b396cd83SPoul-Henning Kamp { 1443a34a5c3SPoul-Henning Kamp int error = sysctl_handle_int(oidp, 1453a34a5c3SPoul-Henning Kamp oidp->oid_arg1, oidp->oid_arg2, 1463a34a5c3SPoul-Henning Kamp oldp, oldlenp, newp, newlen); 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, 1622e210993SPoul-Henning Kamp oidp->oid_arg1, oidp->oid_arg2, 1632e210993SPoul-Henning Kamp oldp, oldlenp, newp, newlen); 1642e210993SPoul-Henning Kamp if (newp && (error == 0 || error == ENOMEM)) 1652e210993SPoul-Henning Kamp hostnamelen = newlen; 1662e210993SPoul-Henning Kamp return error; 1672e210993SPoul-Henning Kamp } 1682e210993SPoul-Henning Kamp 1692e210993SPoul-Henning Kamp SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname, CTLTYPE_STRING|CTLFLAG_RW, 1702e210993SPoul-Henning Kamp &hostname, sizeof(hostname), sysctl_kern_hostname, ""); 1712e210993SPoul-Henning Kamp 172787d58f2SPoul-Henning Kamp static int 173787d58f2SPoul-Henning Kamp sysctl_order_cmp(void *a, void *b) 174787d58f2SPoul-Henning Kamp { 175787d58f2SPoul-Henning Kamp struct sysctl_oid **pa,**pb; 176787d58f2SPoul-Henning Kamp pa = (struct sysctl_oid**) a; 177787d58f2SPoul-Henning Kamp pb = (struct sysctl_oid**) b; 178787d58f2SPoul-Henning Kamp if (!*pa) return 1; 179787d58f2SPoul-Henning Kamp if (!*pb) return -1; 180787d58f2SPoul-Henning Kamp return ((*pa)->oid_number - (*pb)->oid_number); 181787d58f2SPoul-Henning Kamp } 182787d58f2SPoul-Henning Kamp 183787d58f2SPoul-Henning Kamp static void 184787d58f2SPoul-Henning Kamp sysctl_order(void *arg) 185787d58f2SPoul-Henning Kamp { 186787d58f2SPoul-Henning Kamp int j,k; 187787d58f2SPoul-Henning Kamp struct linker_set *l = (struct linker_set *) arg; 188787d58f2SPoul-Henning Kamp struct sysctl_oid **oidpp; 189787d58f2SPoul-Henning Kamp 190787d58f2SPoul-Henning Kamp j = l->ls_length; 191787d58f2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 192787d58f2SPoul-Henning Kamp for (; j--; oidpp++) { 193787d58f2SPoul-Henning Kamp if (!*oidpp) 194787d58f2SPoul-Henning Kamp continue; 195787d58f2SPoul-Henning Kamp if ((*oidpp)->oid_arg1 == arg) { 196787d58f2SPoul-Henning Kamp *oidpp = 0; 197787d58f2SPoul-Henning Kamp continue; 198787d58f2SPoul-Henning Kamp } 199787d58f2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) 200787d58f2SPoul-Henning Kamp if (!(*oidpp)->oid_handler) 201787d58f2SPoul-Henning Kamp sysctl_order((*oidpp)->oid_arg1); 202787d58f2SPoul-Henning Kamp } 203787d58f2SPoul-Henning Kamp qsort(l->ls_items, l->ls_length, sizeof l->ls_items[0], 204787d58f2SPoul-Henning Kamp sysctl_order_cmp); 205787d58f2SPoul-Henning Kamp } 206787d58f2SPoul-Henning Kamp 207787d58f2SPoul-Henning Kamp SYSINIT(sysctl,SI_SUB_KMEM,SI_ORDER_ANY,sysctl_order,&sysctl_); 208787d58f2SPoul-Henning Kamp 209787d58f2SPoul-Henning Kamp static void 210787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node(struct linker_set *l,int i) 211787d58f2SPoul-Henning Kamp { 212787d58f2SPoul-Henning Kamp int j,k; 213787d58f2SPoul-Henning Kamp struct sysctl_oid **oidpp; 214787d58f2SPoul-Henning Kamp 215787d58f2SPoul-Henning Kamp j = l->ls_length; 216787d58f2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 217787d58f2SPoul-Henning Kamp for (; j--; oidpp++) { 218787d58f2SPoul-Henning Kamp 219787d58f2SPoul-Henning Kamp if (!*oidpp) 220787d58f2SPoul-Henning Kamp continue; 221787d58f2SPoul-Henning Kamp 222787d58f2SPoul-Henning Kamp for (k=0; k<i; k++) 223787d58f2SPoul-Henning Kamp printf(" "); 224787d58f2SPoul-Henning Kamp 225787d58f2SPoul-Henning Kamp if ((*oidpp)->oid_number > 100) { 226787d58f2SPoul-Henning Kamp printf("Junk! %p nm %x # %x k %x a1 %x a2 %x h %x\n", 227787d58f2SPoul-Henning Kamp *oidpp, 228787d58f2SPoul-Henning Kamp (*oidpp)->oid_number, (*oidpp)->oid_name, 229787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind, (*oidpp)->oid_arg1, 230787d58f2SPoul-Henning Kamp (*oidpp)->oid_arg2, (*oidpp)->oid_handler); 231787d58f2SPoul-Henning Kamp continue; 232787d58f2SPoul-Henning Kamp } 233787d58f2SPoul-Henning Kamp printf("%d %s ", (*oidpp)->oid_number, (*oidpp)->oid_name); 234787d58f2SPoul-Henning Kamp 235787d58f2SPoul-Henning Kamp printf("%c%c", 236787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind & CTLFLAG_RD ? 'R':' ', 237787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind & CTLFLAG_WR ? 'W':' '); 238787d58f2SPoul-Henning Kamp 239787d58f2SPoul-Henning Kamp switch ((*oidpp)->oid_kind & CTLTYPE) { 240787d58f2SPoul-Henning Kamp case CTLTYPE_NODE: 241787d58f2SPoul-Henning Kamp if ((*oidpp)->oid_handler) { 242787d58f2SPoul-Henning Kamp printf(" Node(proc)\n"); 243787d58f2SPoul-Henning Kamp } else { 244787d58f2SPoul-Henning Kamp printf(" Node\n"); 245787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node( 246787d58f2SPoul-Henning Kamp (*oidpp)->oid_arg1,i+2); 247787d58f2SPoul-Henning Kamp } 248787d58f2SPoul-Henning Kamp break; 249787d58f2SPoul-Henning Kamp case CTLTYPE_INT: printf(" Int\n"); break; 250787d58f2SPoul-Henning Kamp case CTLTYPE_STRING: printf(" String\n"); break; 251787d58f2SPoul-Henning Kamp case CTLTYPE_QUAD: printf(" Quad\n"); break; 252787d58f2SPoul-Henning Kamp case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break; 253787d58f2SPoul-Henning Kamp default: printf("\n"); 254787d58f2SPoul-Henning Kamp } 255787d58f2SPoul-Henning Kamp 256787d58f2SPoul-Henning Kamp } 257787d58f2SPoul-Henning Kamp } 258787d58f2SPoul-Henning Kamp 259787d58f2SPoul-Henning Kamp 260787d58f2SPoul-Henning Kamp static int 261787d58f2SPoul-Henning Kamp sysctl_sysctl_debug SYSCTL_HANDLER_ARGS 262787d58f2SPoul-Henning Kamp { 263787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node(&sysctl_,0); 264787d58f2SPoul-Henning Kamp return ENOENT; 265787d58f2SPoul-Henning Kamp } 266787d58f2SPoul-Henning Kamp 267787d58f2SPoul-Henning Kamp SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD, 268787d58f2SPoul-Henning Kamp 0, 0, sysctl_sysctl_debug, ""); 2692e210993SPoul-Henning Kamp 2702e210993SPoul-Henning Kamp char domainname[MAXHOSTNAMELEN]; 2712e210993SPoul-Henning Kamp int domainnamelen; 2722e210993SPoul-Henning Kamp static int 2732e210993SPoul-Henning Kamp sysctl_kern_domainname SYSCTL_HANDLER_ARGS 2742e210993SPoul-Henning Kamp { 2752e210993SPoul-Henning Kamp int error = sysctl_handle_string(oidp, 2762e210993SPoul-Henning Kamp oidp->oid_arg1, oidp->oid_arg2, 2772e210993SPoul-Henning Kamp oldp, oldlenp, newp, newlen); 2782e210993SPoul-Henning Kamp if (newp && (error == 0 || error == ENOMEM)) 2792e210993SPoul-Henning Kamp domainnamelen = newlen; 2802e210993SPoul-Henning Kamp return error; 2812e210993SPoul-Henning Kamp } 2822e210993SPoul-Henning Kamp 2832e210993SPoul-Henning Kamp SYSCTL_PROC(_kern, KERN_DOMAINNAME, domainname, CTLTYPE_STRING|CTLFLAG_RW, 2842e210993SPoul-Henning Kamp &domainname, sizeof(domainname), sysctl_kern_domainname, ""); 2852e210993SPoul-Henning Kamp 2862e210993SPoul-Henning Kamp long hostid; 2872e210993SPoul-Henning Kamp /* Some trouble here, if sizeof (int) != sizeof (long) */ 2882e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_HOSTID, hostid, CTLFLAG_RW, &hostid, 0, ""); 2892e210993SPoul-Henning Kamp 2903a34a5c3SPoul-Henning Kamp int 2913a34a5c3SPoul-Henning Kamp sysctl_handle_int SYSCTL_HANDLER_ARGS 292b396cd83SPoul-Henning Kamp { 293b396cd83SPoul-Henning Kamp /* If there isn't sufficient space to return */ 294b396cd83SPoul-Henning Kamp if (oldp && *oldlenp < sizeof(int)) 295b396cd83SPoul-Henning Kamp return (ENOMEM); 296b396cd83SPoul-Henning Kamp 297b396cd83SPoul-Henning Kamp /* If it is a constant, don't write */ 2983a34a5c3SPoul-Henning Kamp if (newp && !arg1) 299b396cd83SPoul-Henning Kamp return (EPERM); 300b396cd83SPoul-Henning Kamp 301b396cd83SPoul-Henning Kamp /* If we get more than an int */ 302b396cd83SPoul-Henning Kamp if (newp && newlen != sizeof(int)) 303b396cd83SPoul-Henning Kamp return (EINVAL); 304b396cd83SPoul-Henning Kamp 305b396cd83SPoul-Henning Kamp *oldlenp = sizeof(int); 3063a34a5c3SPoul-Henning Kamp if (oldp && arg1 ) 3072e210993SPoul-Henning Kamp bcopy(arg1, oldp, sizeof(int)); 308b396cd83SPoul-Henning Kamp else if (oldp) 3092e210993SPoul-Henning Kamp bcopy(&arg2, oldp, sizeof(int)); 3102e210993SPoul-Henning Kamp if (newp) 3112e210993SPoul-Henning Kamp bcopy(newp, arg1, sizeof(int)); 3122e210993SPoul-Henning Kamp return (0); 313b396cd83SPoul-Henning Kamp } 314b396cd83SPoul-Henning Kamp 3153a34a5c3SPoul-Henning Kamp int 3163a34a5c3SPoul-Henning Kamp sysctl_handle_string SYSCTL_HANDLER_ARGS 317b396cd83SPoul-Henning Kamp { 3182e210993SPoul-Henning Kamp int len, error=0; 3193a34a5c3SPoul-Henning Kamp char *str = (char *)arg1; 320b396cd83SPoul-Henning Kamp 321b396cd83SPoul-Henning Kamp len = strlen(str) + 1; 322b396cd83SPoul-Henning Kamp 323b396cd83SPoul-Henning Kamp if (oldp && *oldlenp < len) { 324b396cd83SPoul-Henning Kamp len = *oldlenp; 3252e210993SPoul-Henning Kamp error=ENOMEM; 326b396cd83SPoul-Henning Kamp } 327b396cd83SPoul-Henning Kamp 3283a34a5c3SPoul-Henning Kamp if (newp && newlen >= arg2) 329b396cd83SPoul-Henning Kamp return (EINVAL); 330b396cd83SPoul-Henning Kamp 331b396cd83SPoul-Henning Kamp if (oldp) { 332b396cd83SPoul-Henning Kamp *oldlenp = len; 3332e210993SPoul-Henning Kamp bcopy(str, oldp, len); 334b396cd83SPoul-Henning Kamp } 3352e210993SPoul-Henning Kamp 3362e210993SPoul-Henning Kamp if (newp) { 3372e210993SPoul-Henning Kamp bcopy(newp, str, newlen); 338b396cd83SPoul-Henning Kamp str[newlen] = 0; 339b396cd83SPoul-Henning Kamp } 3402e210993SPoul-Henning Kamp return (error); 341b396cd83SPoul-Henning Kamp } 342b396cd83SPoul-Henning Kamp 3433a34a5c3SPoul-Henning Kamp int 3443a34a5c3SPoul-Henning Kamp sysctl_handle_opaque SYSCTL_HANDLER_ARGS 345b396cd83SPoul-Henning Kamp { 3462e210993SPoul-Henning Kamp if (oldp && *oldlenp < arg2) 347b396cd83SPoul-Henning Kamp return (ENOMEM); 348b396cd83SPoul-Henning Kamp 3493a34a5c3SPoul-Henning Kamp if (newp && newlen != arg2) 350b396cd83SPoul-Henning Kamp return (EINVAL); 351b396cd83SPoul-Henning Kamp 352b396cd83SPoul-Henning Kamp if (oldp) { 3533a34a5c3SPoul-Henning Kamp *oldlenp = arg2; 3542e210993SPoul-Henning Kamp bcopy(arg1, oldp, arg2); 355b396cd83SPoul-Henning Kamp } 3562e210993SPoul-Henning Kamp if (newp) 3572e210993SPoul-Henning Kamp bcopy(newp, arg1, arg2); 3582e210993SPoul-Henning Kamp return (0); 359b396cd83SPoul-Henning Kamp } 360b396cd83SPoul-Henning Kamp 3613a34a5c3SPoul-Henning Kamp #ifdef DEBUG 3623a34a5c3SPoul-Henning Kamp static sysctlfn debug_sysctl; 3633a34a5c3SPoul-Henning Kamp #endif 364b396cd83SPoul-Henning Kamp 365df8bae1dSRodney W. Grimes /* 366df8bae1dSRodney W. Grimes * Locking and stats 367df8bae1dSRodney W. Grimes */ 368df8bae1dSRodney W. Grimes static struct sysctl_lock { 369df8bae1dSRodney W. Grimes int sl_lock; 370df8bae1dSRodney W. Grimes int sl_want; 371df8bae1dSRodney W. Grimes int sl_locked; 372df8bae1dSRodney W. Grimes } memlock; 373df8bae1dSRodney W. Grimes 374df8bae1dSRodney W. Grimes struct sysctl_args { 375df8bae1dSRodney W. Grimes int *name; 376df8bae1dSRodney W. Grimes u_int namelen; 377df8bae1dSRodney W. Grimes void *old; 378df8bae1dSRodney W. Grimes size_t *oldlenp; 379df8bae1dSRodney W. Grimes void *new; 380df8bae1dSRodney W. Grimes size_t newlen; 381df8bae1dSRodney W. Grimes }; 382df8bae1dSRodney W. Grimes 3832e210993SPoul-Henning Kamp 3842e210993SPoul-Henning Kamp 3852e210993SPoul-Henning Kamp /* 3862e210993SPoul-Henning Kamp * Traverse our tree, and find the right node, execute whatever it points 3872e210993SPoul-Henning Kamp * at, and return the resulting error code. 3882e210993SPoul-Henning Kamp * We work entirely in kernel-space at this time. 3892e210993SPoul-Henning Kamp */ 3902e210993SPoul-Henning Kamp 3912e210993SPoul-Henning Kamp 3922e210993SPoul-Henning Kamp int 3932e210993SPoul-Henning Kamp sysctl_root SYSCTL_HANDLER_ARGS 3942e210993SPoul-Henning Kamp { 3952e210993SPoul-Henning Kamp int *name = (int *) arg1; 3962e210993SPoul-Henning Kamp int namelen = arg2; 3972e210993SPoul-Henning Kamp int indx, i, j; 3982e210993SPoul-Henning Kamp struct sysctl_oid **oidpp; 3992e210993SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 4002e210993SPoul-Henning Kamp 4012e210993SPoul-Henning Kamp j = lsp->ls_length; 4022e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 4032e210993SPoul-Henning Kamp 4042e210993SPoul-Henning Kamp indx = 0; 4052e210993SPoul-Henning Kamp while (j-- && indx < CTL_MAXNAME) { 406787d58f2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number == name[indx])) { 4072e210993SPoul-Henning Kamp indx++; 4082e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 4092e210993SPoul-Henning Kamp if ((*oidpp)->oid_handler) 4102e210993SPoul-Henning Kamp goto found; 4112e210993SPoul-Henning Kamp if (indx == namelen) 4122e210993SPoul-Henning Kamp return ENOENT; 4132e210993SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 4142e210993SPoul-Henning Kamp j = lsp->ls_length; 4152e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 4162e210993SPoul-Henning Kamp } else { 4172e210993SPoul-Henning Kamp if (indx != namelen) 4182e210993SPoul-Henning Kamp return EISDIR; 4192e210993SPoul-Henning Kamp goto found; 4202e210993SPoul-Henning Kamp } 4212e210993SPoul-Henning Kamp } else { 4222e210993SPoul-Henning Kamp oidpp++; 4232e210993SPoul-Henning Kamp } 4242e210993SPoul-Henning Kamp } 4252e210993SPoul-Henning Kamp return EJUSTRETURN; 4262e210993SPoul-Henning Kamp found: 4272e210993SPoul-Henning Kamp 4282e210993SPoul-Henning Kamp /* If writing isn't allowed */ 4292e210993SPoul-Henning Kamp if (newp && !((*oidpp)->oid_kind & CTLFLAG_WR)) 4302e210993SPoul-Henning Kamp return (EPERM); 4312e210993SPoul-Henning Kamp 4322e210993SPoul-Henning Kamp if (!(*oidpp)->oid_handler) 4332e210993SPoul-Henning Kamp return EINVAL; 4342e210993SPoul-Henning Kamp 4352e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 4362e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 4372e210993SPoul-Henning Kamp name + indx, namelen - indx, 4382e210993SPoul-Henning Kamp oldp, oldlenp, newp, newlen); 4392e210993SPoul-Henning Kamp } else { 4402e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 4412e210993SPoul-Henning Kamp (*oidpp)->oid_arg1, (*oidpp)->oid_arg2, 4422e210993SPoul-Henning Kamp oldp, oldlenp, newp, newlen); 4432e210993SPoul-Henning Kamp } 4442e210993SPoul-Henning Kamp return (i); 4452e210993SPoul-Henning Kamp } 4462e210993SPoul-Henning Kamp 447df8bae1dSRodney W. Grimes int 448df8bae1dSRodney W. Grimes __sysctl(p, uap, retval) 449df8bae1dSRodney W. Grimes struct proc *p; 450df8bae1dSRodney W. Grimes register struct sysctl_args *uap; 451df8bae1dSRodney W. Grimes int *retval; 452df8bae1dSRodney W. Grimes { 453b396cd83SPoul-Henning Kamp int error, dolock = 1, i; 45426f9a767SRodney W. Grimes u_int savelen = 0, oldlen = 0; 455df8bae1dSRodney W. Grimes sysctlfn *fn; 456df8bae1dSRodney W. Grimes int name[CTL_MAXNAME]; 4572e210993SPoul-Henning Kamp void *oldp = 0; 4582e210993SPoul-Henning Kamp void *newp = 0; 459df8bae1dSRodney W. Grimes 460df8bae1dSRodney W. Grimes if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 461df8bae1dSRodney W. Grimes return (error); 462b396cd83SPoul-Henning Kamp 463df8bae1dSRodney W. Grimes /* 464df8bae1dSRodney W. Grimes * all top-level sysctl names are non-terminal 465df8bae1dSRodney W. Grimes */ 466b396cd83SPoul-Henning Kamp 467df8bae1dSRodney W. Grimes if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 468df8bae1dSRodney W. Grimes return (EINVAL); 469b396cd83SPoul-Henning Kamp 470797f2d22SPoul-Henning Kamp error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 471797f2d22SPoul-Henning Kamp if (error) 472df8bae1dSRodney W. Grimes return (error); 473df8bae1dSRodney W. Grimes 474b396cd83SPoul-Henning Kamp if (uap->oldlenp && 475b396cd83SPoul-Henning Kamp (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) 476b396cd83SPoul-Henning Kamp return (error); 477b396cd83SPoul-Henning Kamp 4782e210993SPoul-Henning Kamp if (uap->old) 4792e210993SPoul-Henning Kamp oldp = malloc(oldlen, M_TEMP, M_WAITOK); 4802e210993SPoul-Henning Kamp 4812e210993SPoul-Henning Kamp if (uap->newlen) { 4822e210993SPoul-Henning Kamp newp = malloc(uap->newlen, M_TEMP, M_WAITOK); 4832e210993SPoul-Henning Kamp error = copyin(uap->new, newp, uap->newlen); 484b396cd83SPoul-Henning Kamp } 4852e210993SPoul-Henning Kamp if (error) { 4862e210993SPoul-Henning Kamp if (oldp) 4872e210993SPoul-Henning Kamp free(oldp, M_TEMP); 4882e210993SPoul-Henning Kamp if (newp) 4892e210993SPoul-Henning Kamp free(newp, M_TEMP); 4902e210993SPoul-Henning Kamp return error; 491b396cd83SPoul-Henning Kamp } 492b396cd83SPoul-Henning Kamp 4932e210993SPoul-Henning Kamp error = sysctl_root(0, name, uap->namelen, oldp, &oldlen, 4942e210993SPoul-Henning Kamp newp, uap->newlen); 495b396cd83SPoul-Henning Kamp 4962e210993SPoul-Henning Kamp if (!error || error == ENOMEM) { 4972e210993SPoul-Henning Kamp if (uap->oldlenp) { 4982e210993SPoul-Henning Kamp i = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); 499b396cd83SPoul-Henning Kamp if (i) 500b396cd83SPoul-Henning Kamp error = i; 5012e210993SPoul-Henning Kamp } 5022e210993SPoul-Henning Kamp if ((error == ENOMEM || !error ) && oldp) { 5032e210993SPoul-Henning Kamp i = copyout(oldp, uap->old, oldlen); 5042e210993SPoul-Henning Kamp if (i) 5052e210993SPoul-Henning Kamp error = i; 5062e210993SPoul-Henning Kamp free(oldp, M_TEMP); 5072e210993SPoul-Henning Kamp } 5082e210993SPoul-Henning Kamp if (newp) 5092e210993SPoul-Henning Kamp free(newp, M_TEMP); 5102e210993SPoul-Henning Kamp return (error); 5112e210993SPoul-Henning Kamp } 512b396cd83SPoul-Henning Kamp 5132e210993SPoul-Henning Kamp if (oldp) 5142e210993SPoul-Henning Kamp free(oldp, M_TEMP); 5152e210993SPoul-Henning Kamp if (newp) 5162e210993SPoul-Henning Kamp free(newp, M_TEMP); 5172e210993SPoul-Henning Kamp 518df8bae1dSRodney W. Grimes switch (name[0]) { 519df8bae1dSRodney W. Grimes case CTL_KERN: 520df8bae1dSRodney W. Grimes fn = kern_sysctl; 521e9e2a852SAndrey A. Chernov if (name[1] != KERN_VNODE) /* XXX */ 522df8bae1dSRodney W. Grimes dolock = 0; 523df8bae1dSRodney W. Grimes break; 524df8bae1dSRodney W. Grimes case CTL_HW: 525df8bae1dSRodney W. Grimes fn = hw_sysctl; 526df8bae1dSRodney W. Grimes break; 527df8bae1dSRodney W. Grimes case CTL_VM: 528df8bae1dSRodney W. Grimes fn = vm_sysctl; 529df8bae1dSRodney W. Grimes break; 530df8bae1dSRodney W. Grimes case CTL_NET: 531df8bae1dSRodney W. Grimes fn = net_sysctl; 532df8bae1dSRodney W. Grimes break; 533df8bae1dSRodney W. Grimes case CTL_FS: 534df8bae1dSRodney W. Grimes fn = fs_sysctl; 535df8bae1dSRodney W. Grimes break; 536df8bae1dSRodney W. Grimes case CTL_MACHDEP: 537df8bae1dSRodney W. Grimes fn = cpu_sysctl; 538df8bae1dSRodney W. Grimes break; 539df8bae1dSRodney W. Grimes #ifdef DEBUG 540df8bae1dSRodney W. Grimes case CTL_DEBUG: 541df8bae1dSRodney W. Grimes fn = debug_sysctl; 542df8bae1dSRodney W. Grimes break; 543df8bae1dSRodney W. Grimes #endif 544df8bae1dSRodney W. Grimes default: 545df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 546df8bae1dSRodney W. Grimes } 547df8bae1dSRodney W. Grimes if (uap->old != NULL) { 548df8bae1dSRodney W. Grimes if (!useracc(uap->old, oldlen, B_WRITE)) 549df8bae1dSRodney W. Grimes return (EFAULT); 550df8bae1dSRodney W. Grimes while (memlock.sl_lock) { 551df8bae1dSRodney W. Grimes memlock.sl_want = 1; 55282478919SDavid Greenman (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 553df8bae1dSRodney W. Grimes memlock.sl_locked++; 554df8bae1dSRodney W. Grimes } 555df8bae1dSRodney W. Grimes memlock.sl_lock = 1; 556df8bae1dSRodney W. Grimes if (dolock) 557df8bae1dSRodney W. Grimes vslock(uap->old, oldlen); 558df8bae1dSRodney W. Grimes savelen = oldlen; 559df8bae1dSRodney W. Grimes } 560b396cd83SPoul-Henning Kamp 561b396cd83SPoul-Henning Kamp 562df8bae1dSRodney W. Grimes error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, 563df8bae1dSRodney W. Grimes uap->new, uap->newlen, p); 5642e210993SPoul-Henning Kamp 5652e210993SPoul-Henning Kamp 566df8bae1dSRodney W. Grimes if (uap->old != NULL) { 567df8bae1dSRodney W. Grimes if (dolock) 568df8bae1dSRodney W. Grimes vsunlock(uap->old, savelen, B_WRITE); 569df8bae1dSRodney W. Grimes memlock.sl_lock = 0; 570df8bae1dSRodney W. Grimes if (memlock.sl_want) { 571df8bae1dSRodney W. Grimes memlock.sl_want = 0; 572df8bae1dSRodney W. Grimes wakeup((caddr_t)&memlock); 573df8bae1dSRodney W. Grimes } 574df8bae1dSRodney W. Grimes } 575787d58f2SPoul-Henning Kamp #if 0 576787d58f2SPoul-Henning Kamp if (error) { 577787d58f2SPoul-Henning Kamp printf("SYSCTL_ERROR: "); 578787d58f2SPoul-Henning Kamp for(i=0;i<uap->namelen;i++) 579787d58f2SPoul-Henning Kamp printf("%d ", name[i]); 580787d58f2SPoul-Henning Kamp printf("= %d\n", error); 581787d58f2SPoul-Henning Kamp } 582787d58f2SPoul-Henning Kamp #endif 583df8bae1dSRodney W. Grimes if (error) 584df8bae1dSRodney W. Grimes return (error); 585df8bae1dSRodney W. Grimes if (uap->oldlenp) 586df8bae1dSRodney W. Grimes error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); 587df8bae1dSRodney W. Grimes *retval = oldlen; 588df8bae1dSRodney W. Grimes return (0); 589df8bae1dSRodney W. Grimes } 590df8bae1dSRodney W. Grimes 591df8bae1dSRodney W. Grimes /* 592df8bae1dSRodney W. Grimes * Attributes stored in the kernel. 593df8bae1dSRodney W. Grimes */ 5946ae6a09bSGarrett Wollman int securelevel = -1; 595df8bae1dSRodney W. Grimes 596df8bae1dSRodney W. Grimes /* 597df8bae1dSRodney W. Grimes * kernel related system variables. 598df8bae1dSRodney W. Grimes */ 59926f9a767SRodney W. Grimes int 600df8bae1dSRodney W. Grimes kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 601df8bae1dSRodney W. Grimes int *name; 602df8bae1dSRodney W. Grimes u_int namelen; 603df8bae1dSRodney W. Grimes void *oldp; 604df8bae1dSRodney W. Grimes size_t *oldlenp; 605df8bae1dSRodney W. Grimes void *newp; 606df8bae1dSRodney W. Grimes size_t newlen; 607df8bae1dSRodney W. Grimes struct proc *p; 608df8bae1dSRodney W. Grimes { 6092e210993SPoul-Henning Kamp int error, level; 6105bb4f738SGarrett Wollman dev_t ndumpdev; 611df8bae1dSRodney W. Grimes 612df8bae1dSRodney W. Grimes /* all sysctl names at this level are terminal */ 6133f31c649SGarrett Wollman if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF 6143f31c649SGarrett Wollman || name[0] == KERN_NTP_PLL)) 615df8bae1dSRodney W. Grimes return (ENOTDIR); /* overloaded */ 616df8bae1dSRodney W. Grimes 617df8bae1dSRodney W. Grimes switch (name[0]) { 618b396cd83SPoul-Henning Kamp 619df8bae1dSRodney W. Grimes case KERN_SECURELVL: 620df8bae1dSRodney W. Grimes level = securelevel; 621df8bae1dSRodney W. Grimes if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 622df8bae1dSRodney W. Grimes newp == NULL) 623df8bae1dSRodney W. Grimes return (error); 624df8bae1dSRodney W. Grimes if (level < securelevel && p->p_pid != 1) 625df8bae1dSRodney W. Grimes return (EPERM); 626df8bae1dSRodney W. Grimes securelevel = level; 627df8bae1dSRodney W. Grimes return (0); 628df8bae1dSRodney W. Grimes case KERN_VNODE: 629df8bae1dSRodney W. Grimes return (sysctl_vnode(oldp, oldlenp)); 630df8bae1dSRodney W. Grimes case KERN_PROC: 631df8bae1dSRodney W. Grimes return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 632df8bae1dSRodney W. Grimes case KERN_FILE: 633df8bae1dSRodney W. Grimes return (sysctl_file(oldp, oldlenp)); 634df8bae1dSRodney W. Grimes #ifdef GPROF 635df8bae1dSRodney W. Grimes case KERN_PROF: 636df8bae1dSRodney W. Grimes return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 637df8bae1dSRodney W. Grimes newp, newlen)); 638df8bae1dSRodney W. Grimes #endif 6393f31c649SGarrett Wollman case KERN_NTP_PLL: 6403f31c649SGarrett Wollman return (ntp_sysctl(name + 1, namelen - 1, oldp, oldlenp, 6413f31c649SGarrett Wollman newp, newlen, p)); 6425bb4f738SGarrett Wollman case KERN_DUMPDEV: 6435bb4f738SGarrett Wollman ndumpdev = dumpdev; 6445bb4f738SGarrett Wollman error = sysctl_struct(oldp, oldlenp, newp, newlen, &ndumpdev, 6455bb4f738SGarrett Wollman sizeof ndumpdev); 6465bb4f738SGarrett Wollman if (!error && ndumpdev != dumpdev) { 6475bb4f738SGarrett Wollman error = setdumpdev(ndumpdev); 6485bb4f738SGarrett Wollman } 6495bb4f738SGarrett Wollman return error; 650df8bae1dSRodney W. Grimes default: 651df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 652df8bae1dSRodney W. Grimes } 653df8bae1dSRodney W. Grimes /* NOTREACHED */ 654df8bae1dSRodney W. Grimes } 655df8bae1dSRodney W. Grimes 656df8bae1dSRodney W. Grimes /* 657df8bae1dSRodney W. Grimes * hardware related system variables. 658df8bae1dSRodney W. Grimes */ 65926f9a767SRodney W. Grimes int 660df8bae1dSRodney W. Grimes hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 661df8bae1dSRodney W. Grimes int *name; 662df8bae1dSRodney W. Grimes u_int namelen; 663df8bae1dSRodney W. Grimes void *oldp; 664df8bae1dSRodney W. Grimes size_t *oldlenp; 665df8bae1dSRodney W. Grimes void *newp; 666df8bae1dSRodney W. Grimes size_t newlen; 667df8bae1dSRodney W. Grimes struct proc *p; 668df8bae1dSRodney W. Grimes { 6698478cabaSGarrett Wollman /* almost all sysctl names at this level are terminal */ 6708478cabaSGarrett Wollman if (namelen != 1 && name[0] != HW_DEVCONF) 671df8bae1dSRodney W. Grimes return (ENOTDIR); /* overloaded */ 672df8bae1dSRodney W. Grimes 673df8bae1dSRodney W. Grimes switch (name[0]) { 674df8bae1dSRodney W. Grimes case HW_PHYSMEM: 675df8bae1dSRodney W. Grimes return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 676df8bae1dSRodney W. Grimes case HW_USERMEM: 677df8bae1dSRodney W. Grimes return (sysctl_rdint(oldp, oldlenp, newp, 678df8bae1dSRodney W. Grimes ctob(physmem - cnt.v_wire_count))); 6798478cabaSGarrett Wollman case HW_DEVCONF: 6808478cabaSGarrett Wollman return (dev_sysctl(name + 1, namelen - 1, oldp, oldlenp, 6818478cabaSGarrett Wollman newp, newlen, p)); 682df8bae1dSRodney W. Grimes default: 683df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 684df8bae1dSRodney W. Grimes } 685df8bae1dSRodney W. Grimes /* NOTREACHED */ 686df8bae1dSRodney W. Grimes } 687df8bae1dSRodney W. Grimes 688df8bae1dSRodney W. Grimes #ifdef DEBUG 689df8bae1dSRodney W. Grimes /* 690df8bae1dSRodney W. Grimes * Debugging related system variables. 691df8bae1dSRodney W. Grimes */ 692df8bae1dSRodney W. Grimes struct ctldebug debug0, debug1, debug2, debug3, debug4; 693df8bae1dSRodney W. Grimes struct ctldebug debug5, debug6, debug7, debug8, debug9; 694df8bae1dSRodney W. Grimes struct ctldebug debug10, debug11, debug12, debug13, debug14; 695df8bae1dSRodney W. Grimes struct ctldebug debug15, debug16, debug17, debug18, debug19; 696df8bae1dSRodney W. Grimes static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 697df8bae1dSRodney W. Grimes &debug0, &debug1, &debug2, &debug3, &debug4, 698df8bae1dSRodney W. Grimes &debug5, &debug6, &debug7, &debug8, &debug9, 699df8bae1dSRodney W. Grimes &debug10, &debug11, &debug12, &debug13, &debug14, 700df8bae1dSRodney W. Grimes &debug15, &debug16, &debug17, &debug18, &debug19, 701df8bae1dSRodney W. Grimes }; 7026124ac44SBruce Evans static int 703df8bae1dSRodney W. Grimes debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 704df8bae1dSRodney W. Grimes int *name; 705df8bae1dSRodney W. Grimes u_int namelen; 706df8bae1dSRodney W. Grimes void *oldp; 707df8bae1dSRodney W. Grimes size_t *oldlenp; 708df8bae1dSRodney W. Grimes void *newp; 709df8bae1dSRodney W. Grimes size_t newlen; 710df8bae1dSRodney W. Grimes struct proc *p; 711df8bae1dSRodney W. Grimes { 712df8bae1dSRodney W. Grimes struct ctldebug *cdp; 713df8bae1dSRodney W. Grimes 714df8bae1dSRodney W. Grimes /* all sysctl names at this level are name and field */ 715df8bae1dSRodney W. Grimes if (namelen != 2) 716df8bae1dSRodney W. Grimes return (ENOTDIR); /* overloaded */ 717df8bae1dSRodney W. Grimes cdp = debugvars[name[0]]; 718df8bae1dSRodney W. Grimes if (cdp->debugname == 0) 719df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 720df8bae1dSRodney W. Grimes switch (name[1]) { 721df8bae1dSRodney W. Grimes case CTL_DEBUG_NAME: 722df8bae1dSRodney W. Grimes return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 723df8bae1dSRodney W. Grimes case CTL_DEBUG_VALUE: 724df8bae1dSRodney W. Grimes return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 725df8bae1dSRodney W. Grimes default: 726df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 727df8bae1dSRodney W. Grimes } 728df8bae1dSRodney W. Grimes /* NOTREACHED */ 729df8bae1dSRodney W. Grimes } 730df8bae1dSRodney W. Grimes #endif /* DEBUG */ 731df8bae1dSRodney W. Grimes 732df8bae1dSRodney W. Grimes /* 733df8bae1dSRodney W. Grimes * Validate parameters and get old / set new parameters 734df8bae1dSRodney W. Grimes * for an integer-valued sysctl function. 735df8bae1dSRodney W. Grimes */ 73626f9a767SRodney W. Grimes int 737df8bae1dSRodney W. Grimes sysctl_int(oldp, oldlenp, newp, newlen, valp) 738df8bae1dSRodney W. Grimes void *oldp; 739df8bae1dSRodney W. Grimes size_t *oldlenp; 740df8bae1dSRodney W. Grimes void *newp; 741df8bae1dSRodney W. Grimes size_t newlen; 742df8bae1dSRodney W. Grimes int *valp; 743df8bae1dSRodney W. Grimes { 744df8bae1dSRodney W. Grimes int error = 0; 745df8bae1dSRodney W. Grimes 746df8bae1dSRodney W. Grimes if (oldp && *oldlenp < sizeof(int)) 747df8bae1dSRodney W. Grimes return (ENOMEM); 748df8bae1dSRodney W. Grimes if (newp && newlen != sizeof(int)) 749df8bae1dSRodney W. Grimes return (EINVAL); 750df8bae1dSRodney W. Grimes *oldlenp = sizeof(int); 751df8bae1dSRodney W. Grimes if (oldp) 752df8bae1dSRodney W. Grimes error = copyout(valp, oldp, sizeof(int)); 753df8bae1dSRodney W. Grimes if (error == 0 && newp) 754df8bae1dSRodney W. Grimes error = copyin(newp, valp, sizeof(int)); 755df8bae1dSRodney W. Grimes return (error); 756df8bae1dSRodney W. Grimes } 757df8bae1dSRodney W. Grimes 758df8bae1dSRodney W. Grimes /* 759df8bae1dSRodney W. Grimes * As above, but read-only. 760df8bae1dSRodney W. Grimes */ 76126f9a767SRodney W. Grimes int 762df8bae1dSRodney W. Grimes sysctl_rdint(oldp, oldlenp, newp, val) 763df8bae1dSRodney W. Grimes void *oldp; 764df8bae1dSRodney W. Grimes size_t *oldlenp; 765df8bae1dSRodney W. Grimes void *newp; 766df8bae1dSRodney W. Grimes int val; 767df8bae1dSRodney W. Grimes { 768df8bae1dSRodney W. Grimes int error = 0; 769df8bae1dSRodney W. Grimes 770df8bae1dSRodney W. Grimes if (oldp && *oldlenp < sizeof(int)) 771df8bae1dSRodney W. Grimes return (ENOMEM); 772df8bae1dSRodney W. Grimes if (newp) 773df8bae1dSRodney W. Grimes return (EPERM); 774df8bae1dSRodney W. Grimes *oldlenp = sizeof(int); 775df8bae1dSRodney W. Grimes if (oldp) 776df8bae1dSRodney W. Grimes error = copyout((caddr_t)&val, oldp, sizeof(int)); 777df8bae1dSRodney W. Grimes return (error); 778df8bae1dSRodney W. Grimes } 779df8bae1dSRodney W. Grimes 780df8bae1dSRodney W. Grimes /* 781df8bae1dSRodney W. Grimes * Validate parameters and get old / set new parameters 782df8bae1dSRodney W. Grimes * for a string-valued sysctl function. 783df8bae1dSRodney W. Grimes */ 78426f9a767SRodney W. Grimes int 785df8bae1dSRodney W. Grimes sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 786df8bae1dSRodney W. Grimes void *oldp; 787df8bae1dSRodney W. Grimes size_t *oldlenp; 788df8bae1dSRodney W. Grimes void *newp; 789df8bae1dSRodney W. Grimes size_t newlen; 790df8bae1dSRodney W. Grimes char *str; 791df8bae1dSRodney W. Grimes int maxlen; 792df8bae1dSRodney W. Grimes { 793e1453736SMike Pritchard int len, error = 0, rval = 0; 794df8bae1dSRodney W. Grimes 795df8bae1dSRodney W. Grimes len = strlen(str) + 1; 796e1453736SMike Pritchard if (oldp && *oldlenp < len) { 797f81fcd41SGuido van Rooij len = *oldlenp; 798e1453736SMike Pritchard rval = ENOMEM; 799e1453736SMike Pritchard } 800df8bae1dSRodney W. Grimes if (newp && newlen >= maxlen) 801df8bae1dSRodney W. Grimes return (EINVAL); 802df8bae1dSRodney W. Grimes if (oldp) { 803df8bae1dSRodney W. Grimes *oldlenp = len; 804df8bae1dSRodney W. Grimes error = copyout(str, oldp, len); 805e1453736SMike Pritchard if (error) 806e1453736SMike Pritchard rval = error; 807df8bae1dSRodney W. Grimes } 808e1453736SMike Pritchard if ((error == 0 || error == ENOMEM) && newp) { 809df8bae1dSRodney W. Grimes error = copyin(newp, str, newlen); 810e1453736SMike Pritchard if (error) 811e1453736SMike Pritchard rval = error; 812df8bae1dSRodney W. Grimes str[newlen] = 0; 813df8bae1dSRodney W. Grimes } 814e1453736SMike Pritchard return (rval); 815df8bae1dSRodney W. Grimes } 816df8bae1dSRodney W. Grimes 817df8bae1dSRodney W. Grimes /* 818df8bae1dSRodney W. Grimes * As above, but read-only. 819df8bae1dSRodney W. Grimes */ 82026f9a767SRodney W. Grimes int 821df8bae1dSRodney W. Grimes sysctl_rdstring(oldp, oldlenp, newp, str) 822df8bae1dSRodney W. Grimes void *oldp; 823df8bae1dSRodney W. Grimes size_t *oldlenp; 824df8bae1dSRodney W. Grimes void *newp; 825df8bae1dSRodney W. Grimes char *str; 826df8bae1dSRodney W. Grimes { 827e1453736SMike Pritchard int len, error = 0, rval = 0; 828df8bae1dSRodney W. Grimes 829df8bae1dSRodney W. Grimes len = strlen(str) + 1; 830e1453736SMike Pritchard if (oldp && *oldlenp < len) { 831e1453736SMike Pritchard len = *oldlenp; 832e1453736SMike Pritchard rval = ENOMEM; 833e1453736SMike Pritchard } 834df8bae1dSRodney W. Grimes if (newp) 835df8bae1dSRodney W. Grimes return (EPERM); 836df8bae1dSRodney W. Grimes *oldlenp = len; 837df8bae1dSRodney W. Grimes if (oldp) 838df8bae1dSRodney W. Grimes error = copyout(str, oldp, len); 839e1453736SMike Pritchard if (error) 840e1453736SMike Pritchard rval = error; 841e1453736SMike Pritchard return (rval); 842df8bae1dSRodney W. Grimes } 843df8bae1dSRodney W. Grimes 844df8bae1dSRodney W. Grimes /* 845df8bae1dSRodney W. Grimes * Validate parameters and get old / set new parameters 846df8bae1dSRodney W. Grimes * for a structure oriented sysctl function. 847df8bae1dSRodney W. Grimes */ 84826f9a767SRodney W. Grimes int 849df8bae1dSRodney W. Grimes sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 850df8bae1dSRodney W. Grimes void *oldp; 851df8bae1dSRodney W. Grimes size_t *oldlenp; 852df8bae1dSRodney W. Grimes void *newp; 853df8bae1dSRodney W. Grimes size_t newlen; 854df8bae1dSRodney W. Grimes void *sp; 855df8bae1dSRodney W. Grimes int len; 856df8bae1dSRodney W. Grimes { 857df8bae1dSRodney W. Grimes int error = 0; 858df8bae1dSRodney W. Grimes 859df8bae1dSRodney W. Grimes if (oldp && *oldlenp < len) 860df8bae1dSRodney W. Grimes return (ENOMEM); 861df8bae1dSRodney W. Grimes if (newp && newlen > len) 862df8bae1dSRodney W. Grimes return (EINVAL); 863df8bae1dSRodney W. Grimes if (oldp) { 864df8bae1dSRodney W. Grimes *oldlenp = len; 865df8bae1dSRodney W. Grimes error = copyout(sp, oldp, len); 866df8bae1dSRodney W. Grimes } 867df8bae1dSRodney W. Grimes if (error == 0 && newp) 868df8bae1dSRodney W. Grimes error = copyin(newp, sp, len); 869df8bae1dSRodney W. Grimes return (error); 870df8bae1dSRodney W. Grimes } 871df8bae1dSRodney W. Grimes 872df8bae1dSRodney W. Grimes /* 873df8bae1dSRodney W. Grimes * Validate parameters and get old parameters 874df8bae1dSRodney W. Grimes * for a structure oriented sysctl function. 875df8bae1dSRodney W. Grimes */ 87626f9a767SRodney W. Grimes int 877df8bae1dSRodney W. Grimes sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 878df8bae1dSRodney W. Grimes void *oldp; 879df8bae1dSRodney W. Grimes size_t *oldlenp; 880df8bae1dSRodney W. Grimes void *newp, *sp; 881df8bae1dSRodney W. Grimes int len; 882df8bae1dSRodney W. Grimes { 883df8bae1dSRodney W. Grimes int error = 0; 884df8bae1dSRodney W. Grimes 885df8bae1dSRodney W. Grimes if (oldp && *oldlenp < len) 886df8bae1dSRodney W. Grimes return (ENOMEM); 887df8bae1dSRodney W. Grimes if (newp) 888df8bae1dSRodney W. Grimes return (EPERM); 889df8bae1dSRodney W. Grimes *oldlenp = len; 890df8bae1dSRodney W. Grimes if (oldp) 891df8bae1dSRodney W. Grimes error = copyout(sp, oldp, len); 892df8bae1dSRodney W. Grimes return (error); 893df8bae1dSRodney W. Grimes } 894df8bae1dSRodney W. Grimes 895df8bae1dSRodney W. Grimes /* 896df8bae1dSRodney W. Grimes * Get file structures. 897df8bae1dSRodney W. Grimes */ 89826f9a767SRodney W. Grimes int 899df8bae1dSRodney W. Grimes sysctl_file(where, sizep) 900df8bae1dSRodney W. Grimes char *where; 901df8bae1dSRodney W. Grimes size_t *sizep; 902df8bae1dSRodney W. Grimes { 903df8bae1dSRodney W. Grimes int buflen, error; 904df8bae1dSRodney W. Grimes struct file *fp; 905df8bae1dSRodney W. Grimes char *start = where; 906df8bae1dSRodney W. Grimes 907df8bae1dSRodney W. Grimes buflen = *sizep; 908df8bae1dSRodney W. Grimes if (where == NULL) { 909df8bae1dSRodney W. Grimes /* 910df8bae1dSRodney W. Grimes * overestimate by 10 files 911df8bae1dSRodney W. Grimes */ 912df8bae1dSRodney W. Grimes *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 913df8bae1dSRodney W. Grimes return (0); 914df8bae1dSRodney W. Grimes } 915df8bae1dSRodney W. Grimes 916df8bae1dSRodney W. Grimes /* 917df8bae1dSRodney W. Grimes * first copyout filehead 918df8bae1dSRodney W. Grimes */ 919df8bae1dSRodney W. Grimes if (buflen < sizeof(filehead)) { 920df8bae1dSRodney W. Grimes *sizep = 0; 921df8bae1dSRodney W. Grimes return (0); 922df8bae1dSRodney W. Grimes } 923797f2d22SPoul-Henning Kamp error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 924797f2d22SPoul-Henning Kamp if (error) 925df8bae1dSRodney W. Grimes return (error); 926df8bae1dSRodney W. Grimes buflen -= sizeof(filehead); 927df8bae1dSRodney W. Grimes where += sizeof(filehead); 928df8bae1dSRodney W. Grimes 929df8bae1dSRodney W. Grimes /* 930df8bae1dSRodney W. Grimes * followed by an array of file structures 931df8bae1dSRodney W. Grimes */ 932df8bae1dSRodney W. Grimes for (fp = filehead; fp != NULL; fp = fp->f_filef) { 933df8bae1dSRodney W. Grimes if (buflen < sizeof(struct file)) { 934df8bae1dSRodney W. Grimes *sizep = where - start; 935df8bae1dSRodney W. Grimes return (ENOMEM); 936df8bae1dSRodney W. Grimes } 937797f2d22SPoul-Henning Kamp error = copyout((caddr_t)fp, where, sizeof (struct file)); 938797f2d22SPoul-Henning Kamp if (error) 939df8bae1dSRodney W. Grimes return (error); 940df8bae1dSRodney W. Grimes buflen -= sizeof(struct file); 941df8bae1dSRodney W. Grimes where += sizeof(struct file); 942df8bae1dSRodney W. Grimes } 943df8bae1dSRodney W. Grimes *sizep = where - start; 944df8bae1dSRodney W. Grimes return (0); 945df8bae1dSRodney W. Grimes } 946df8bae1dSRodney W. Grimes 947df8bae1dSRodney W. Grimes /* 948df8bae1dSRodney W. Grimes * try over estimating by 5 procs 949df8bae1dSRodney W. Grimes */ 950df8bae1dSRodney W. Grimes #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 951df8bae1dSRodney W. Grimes 95226f9a767SRodney W. Grimes int 953df8bae1dSRodney W. Grimes sysctl_doproc(name, namelen, where, sizep) 954df8bae1dSRodney W. Grimes int *name; 955df8bae1dSRodney W. Grimes u_int namelen; 956df8bae1dSRodney W. Grimes char *where; 957df8bae1dSRodney W. Grimes size_t *sizep; 958df8bae1dSRodney W. Grimes { 959df8bae1dSRodney W. Grimes register struct proc *p; 960df8bae1dSRodney W. Grimes register struct kinfo_proc *dp = (struct kinfo_proc *)where; 961df8bae1dSRodney W. Grimes register int needed = 0; 962df8bae1dSRodney W. Grimes int buflen = where != NULL ? *sizep : 0; 963df8bae1dSRodney W. Grimes int doingzomb; 964df8bae1dSRodney W. Grimes struct eproc eproc; 965df8bae1dSRodney W. Grimes int error = 0; 966df8bae1dSRodney W. Grimes 967df8bae1dSRodney W. Grimes if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 968df8bae1dSRodney W. Grimes return (EINVAL); 969df8bae1dSRodney W. Grimes p = (struct proc *)allproc; 970df8bae1dSRodney W. Grimes doingzomb = 0; 971df8bae1dSRodney W. Grimes again: 972df8bae1dSRodney W. Grimes for (; p != NULL; p = p->p_next) { 973df8bae1dSRodney W. Grimes /* 974df8bae1dSRodney W. Grimes * Skip embryonic processes. 975df8bae1dSRodney W. Grimes */ 976df8bae1dSRodney W. Grimes if (p->p_stat == SIDL) 977df8bae1dSRodney W. Grimes continue; 978df8bae1dSRodney W. Grimes /* 979df8bae1dSRodney W. Grimes * TODO - make more efficient (see notes below). 980df8bae1dSRodney W. Grimes * do by session. 981df8bae1dSRodney W. Grimes */ 982df8bae1dSRodney W. Grimes switch (name[0]) { 983df8bae1dSRodney W. Grimes 984df8bae1dSRodney W. Grimes case KERN_PROC_PID: 985df8bae1dSRodney W. Grimes /* could do this with just a lookup */ 986df8bae1dSRodney W. Grimes if (p->p_pid != (pid_t)name[1]) 987df8bae1dSRodney W. Grimes continue; 988df8bae1dSRodney W. Grimes break; 989df8bae1dSRodney W. Grimes 990df8bae1dSRodney W. Grimes case KERN_PROC_PGRP: 991df8bae1dSRodney W. Grimes /* could do this by traversing pgrp */ 992be6a1d14SDavid Greenman if (p->p_pgrp == NULL || p->p_pgrp->pg_id != (pid_t)name[1]) 993df8bae1dSRodney W. Grimes continue; 994df8bae1dSRodney W. Grimes break; 995df8bae1dSRodney W. Grimes 996df8bae1dSRodney W. Grimes case KERN_PROC_TTY: 997df8bae1dSRodney W. Grimes if ((p->p_flag & P_CONTROLT) == 0 || 998be6a1d14SDavid Greenman p->p_session == NULL || 999df8bae1dSRodney W. Grimes p->p_session->s_ttyp == NULL || 1000df8bae1dSRodney W. Grimes p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 1001df8bae1dSRodney W. Grimes continue; 1002df8bae1dSRodney W. Grimes break; 1003df8bae1dSRodney W. Grimes 1004df8bae1dSRodney W. Grimes case KERN_PROC_UID: 1005be6a1d14SDavid Greenman if (p->p_ucred == NULL || p->p_ucred->cr_uid != (uid_t)name[1]) 1006df8bae1dSRodney W. Grimes continue; 1007df8bae1dSRodney W. Grimes break; 1008df8bae1dSRodney W. Grimes 1009df8bae1dSRodney W. Grimes case KERN_PROC_RUID: 1010be6a1d14SDavid Greenman if (p->p_ucred == NULL || p->p_cred->p_ruid != (uid_t)name[1]) 1011df8bae1dSRodney W. Grimes continue; 1012df8bae1dSRodney W. Grimes break; 1013df8bae1dSRodney W. Grimes } 1014df8bae1dSRodney W. Grimes if (buflen >= sizeof(struct kinfo_proc)) { 1015df8bae1dSRodney W. Grimes fill_eproc(p, &eproc); 1016797f2d22SPoul-Henning Kamp error = copyout((caddr_t)p, &dp->kp_proc, 1017797f2d22SPoul-Henning Kamp sizeof(struct proc)); 1018797f2d22SPoul-Henning Kamp if (error) 1019df8bae1dSRodney W. Grimes return (error); 1020797f2d22SPoul-Henning Kamp error = copyout((caddr_t)&eproc, &dp->kp_eproc, 1021797f2d22SPoul-Henning Kamp sizeof(eproc)); 1022797f2d22SPoul-Henning Kamp if (error) 1023df8bae1dSRodney W. Grimes return (error); 1024df8bae1dSRodney W. Grimes dp++; 1025df8bae1dSRodney W. Grimes buflen -= sizeof(struct kinfo_proc); 1026df8bae1dSRodney W. Grimes } 1027df8bae1dSRodney W. Grimes needed += sizeof(struct kinfo_proc); 1028df8bae1dSRodney W. Grimes } 1029df8bae1dSRodney W. Grimes if (doingzomb == 0) { 1030df8bae1dSRodney W. Grimes p = zombproc; 1031df8bae1dSRodney W. Grimes doingzomb++; 1032df8bae1dSRodney W. Grimes goto again; 1033df8bae1dSRodney W. Grimes } 1034df8bae1dSRodney W. Grimes if (where != NULL) { 1035df8bae1dSRodney W. Grimes *sizep = (caddr_t)dp - where; 1036df8bae1dSRodney W. Grimes if (needed > *sizep) 1037df8bae1dSRodney W. Grimes return (ENOMEM); 1038df8bae1dSRodney W. Grimes } else { 1039df8bae1dSRodney W. Grimes needed += KERN_PROCSLOP; 1040df8bae1dSRodney W. Grimes *sizep = needed; 1041df8bae1dSRodney W. Grimes } 1042df8bae1dSRodney W. Grimes return (0); 1043df8bae1dSRodney W. Grimes } 1044df8bae1dSRodney W. Grimes 1045df8bae1dSRodney W. Grimes /* 1046df8bae1dSRodney W. Grimes * Fill in an eproc structure for the specified process. 1047df8bae1dSRodney W. Grimes */ 1048df8bae1dSRodney W. Grimes void 1049df8bae1dSRodney W. Grimes fill_eproc(p, ep) 1050df8bae1dSRodney W. Grimes register struct proc *p; 1051df8bae1dSRodney W. Grimes register struct eproc *ep; 1052df8bae1dSRodney W. Grimes { 1053df8bae1dSRodney W. Grimes register struct tty *tp; 1054df8bae1dSRodney W. Grimes 1055be6a1d14SDavid Greenman bzero(ep, sizeof(*ep)); 1056be6a1d14SDavid Greenman 1057df8bae1dSRodney W. Grimes ep->e_paddr = p; 10581c8fc26cSDavid Greenman if (p->p_cred) { 1059df8bae1dSRodney W. Grimes ep->e_pcred = *p->p_cred; 1060be6a1d14SDavid Greenman if (p->p_ucred) 1061df8bae1dSRodney W. Grimes ep->e_ucred = *p->p_ucred; 10621c8fc26cSDavid Greenman } 10631c8fc26cSDavid Greenman if (p->p_stat != SIDL && p->p_stat != SZOMB && p->p_vmspace != NULL) { 1064df8bae1dSRodney W. Grimes register struct vmspace *vm = p->p_vmspace; 1065df8bae1dSRodney W. Grimes 1066df8bae1dSRodney W. Grimes #ifdef pmap_resident_count 1067df8bae1dSRodney W. Grimes ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/ 1068df8bae1dSRodney W. Grimes #else 1069df8bae1dSRodney W. Grimes ep->e_vm.vm_rssize = vm->vm_rssize; 1070df8bae1dSRodney W. Grimes #endif 1071df8bae1dSRodney W. Grimes ep->e_vm.vm_tsize = vm->vm_tsize; 1072df8bae1dSRodney W. Grimes ep->e_vm.vm_dsize = vm->vm_dsize; 1073df8bae1dSRodney W. Grimes ep->e_vm.vm_ssize = vm->vm_ssize; 1074df8bae1dSRodney W. Grimes #ifndef sparc 1075df8bae1dSRodney W. Grimes ep->e_vm.vm_pmap = vm->vm_pmap; 1076df8bae1dSRodney W. Grimes #endif 1077df8bae1dSRodney W. Grimes } 1078df8bae1dSRodney W. Grimes if (p->p_pptr) 1079df8bae1dSRodney W. Grimes ep->e_ppid = p->p_pptr->p_pid; 1080be6a1d14SDavid Greenman if (p->p_pgrp) { 1081be6a1d14SDavid Greenman ep->e_sess = p->p_pgrp->pg_session; 1082df8bae1dSRodney W. Grimes ep->e_pgid = p->p_pgrp->pg_id; 1083df8bae1dSRodney W. Grimes ep->e_jobc = p->p_pgrp->pg_jobc; 1084be6a1d14SDavid Greenman } 1085df8bae1dSRodney W. Grimes if ((p->p_flag & P_CONTROLT) && 1086be6a1d14SDavid Greenman (ep->e_sess != NULL) && 1087be6a1d14SDavid Greenman ((tp = ep->e_sess->s_ttyp) != NULL)) { 1088df8bae1dSRodney W. Grimes ep->e_tdev = tp->t_dev; 1089df8bae1dSRodney W. Grimes ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1090df8bae1dSRodney W. Grimes ep->e_tsess = tp->t_session; 1091df8bae1dSRodney W. Grimes } else 1092df8bae1dSRodney W. Grimes ep->e_tdev = NODEV; 1093be6a1d14SDavid Greenman if (ep->e_sess && ep->e_sess->s_ttyvp) 1094be6a1d14SDavid Greenman ep->e_flag = EPROC_CTTY; 1095df8bae1dSRodney W. Grimes if (SESS_LEADER(p)) 1096df8bae1dSRodney W. Grimes ep->e_flag |= EPROC_SLEADER; 1097be6a1d14SDavid Greenman if (p->p_wmesg) { 1098df8bae1dSRodney W. Grimes strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 1099be6a1d14SDavid Greenman ep->e_wmesg[WMESGLEN] = 0; 1100be6a1d14SDavid Greenman } 1101df8bae1dSRodney W. Grimes } 1102df8bae1dSRodney W. Grimes 1103df8bae1dSRodney W. Grimes #ifdef COMPAT_43 1104df8bae1dSRodney W. Grimes #include <sys/socket.h> 1105df8bae1dSRodney W. Grimes #define KINFO_PROC (0<<8) 1106df8bae1dSRodney W. Grimes #define KINFO_RT (1<<8) 1107df8bae1dSRodney W. Grimes #define KINFO_VNODE (2<<8) 1108df8bae1dSRodney W. Grimes #define KINFO_FILE (3<<8) 1109df8bae1dSRodney W. Grimes #define KINFO_METER (4<<8) 1110df8bae1dSRodney W. Grimes #define KINFO_LOADAVG (5<<8) 1111df8bae1dSRodney W. Grimes #define KINFO_CLOCKRATE (6<<8) 1112df8bae1dSRodney W. Grimes 11136ece4a51SPeter Wemm /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ 11146ece4a51SPeter Wemm #define KINFO_BSDI_SYSINFO (101<<8) 11156ece4a51SPeter Wemm 11166ece4a51SPeter Wemm /* 11176ece4a51SPeter Wemm * XXX this is bloat, but I hope it's better here than on the potentially 11186ece4a51SPeter Wemm * limited kernel stack... -Peter 11196ece4a51SPeter Wemm */ 11206ece4a51SPeter Wemm 11216ece4a51SPeter Wemm struct { 11226ece4a51SPeter Wemm int bsdi_machine; /* "i386" on BSD/386 */ 11236ece4a51SPeter Wemm /* ^^^ this is an offset to the string, relative to the struct start */ 11246ece4a51SPeter Wemm char *pad0; 11256ece4a51SPeter Wemm long pad1; 11266ece4a51SPeter Wemm long pad2; 11276ece4a51SPeter Wemm long pad3; 11286ece4a51SPeter Wemm u_long pad4; 11296ece4a51SPeter Wemm u_long pad5; 11306ece4a51SPeter Wemm u_long pad6; 11316ece4a51SPeter Wemm 11326ece4a51SPeter Wemm int bsdi_ostype; /* "BSD/386" on BSD/386 */ 11336ece4a51SPeter Wemm int bsdi_osrelease; /* "1.1" on BSD/386 */ 11346ece4a51SPeter Wemm long pad7; 11356ece4a51SPeter Wemm long pad8; 11366ece4a51SPeter Wemm char *pad9; 11376ece4a51SPeter Wemm 11386ece4a51SPeter Wemm long pad10; 11396ece4a51SPeter Wemm long pad11; 11406ece4a51SPeter Wemm int pad12; 11416ece4a51SPeter Wemm long pad13; 11426ece4a51SPeter Wemm quad_t pad14; 11436ece4a51SPeter Wemm long pad15; 11446ece4a51SPeter Wemm 11456ece4a51SPeter Wemm struct timeval pad16; 11466ece4a51SPeter Wemm /* we dont set this, because BSDI's uname used gethostname() instead */ 11476ece4a51SPeter Wemm int bsdi_hostname; /* hostname on BSD/386 */ 11486ece4a51SPeter Wemm 11496ece4a51SPeter Wemm /* the actual string data is appended here */ 11506ece4a51SPeter Wemm 11516ece4a51SPeter Wemm } bsdi_si; 11526ece4a51SPeter Wemm /* 11536ece4a51SPeter Wemm * this data is appended to the end of the bsdi_si structure during copyout. 11546ece4a51SPeter Wemm * The "char *" offsets are relative to the base of the bsdi_si struct. 11556ece4a51SPeter Wemm * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings 11566ece4a51SPeter Wemm * should not exceed the length of the buffer here... (or else!! :-) 11576ece4a51SPeter Wemm */ 11586ece4a51SPeter Wemm char bsdi_strings[80]; /* It had better be less than this! */ 11596ece4a51SPeter Wemm 1160df8bae1dSRodney W. Grimes struct getkerninfo_args { 1161df8bae1dSRodney W. Grimes int op; 1162df8bae1dSRodney W. Grimes char *where; 1163df8bae1dSRodney W. Grimes int *size; 1164df8bae1dSRodney W. Grimes int arg; 1165df8bae1dSRodney W. Grimes }; 1166df8bae1dSRodney W. Grimes 116726f9a767SRodney W. Grimes int 1168df8bae1dSRodney W. Grimes ogetkerninfo(p, uap, retval) 1169df8bae1dSRodney W. Grimes struct proc *p; 1170df8bae1dSRodney W. Grimes register struct getkerninfo_args *uap; 1171df8bae1dSRodney W. Grimes int *retval; 1172df8bae1dSRodney W. Grimes { 1173df8bae1dSRodney W. Grimes int error, name[5]; 1174df8bae1dSRodney W. Grimes u_int size; 1175df8bae1dSRodney W. Grimes 1176df8bae1dSRodney W. Grimes if (uap->size && 1177df8bae1dSRodney W. Grimes (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) 1178df8bae1dSRodney W. Grimes return (error); 1179df8bae1dSRodney W. Grimes 1180df8bae1dSRodney W. Grimes switch (uap->op & 0xff00) { 1181df8bae1dSRodney W. Grimes 1182df8bae1dSRodney W. Grimes case KINFO_RT: 1183df8bae1dSRodney W. Grimes name[0] = PF_ROUTE; 1184df8bae1dSRodney W. Grimes name[1] = 0; 1185df8bae1dSRodney W. Grimes name[2] = (uap->op & 0xff0000) >> 16; 1186df8bae1dSRodney W. Grimes name[3] = uap->op & 0xff; 1187df8bae1dSRodney W. Grimes name[4] = uap->arg; 1188df8bae1dSRodney W. Grimes error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); 1189df8bae1dSRodney W. Grimes break; 1190df8bae1dSRodney W. Grimes 1191df8bae1dSRodney W. Grimes case KINFO_VNODE: 1192df8bae1dSRodney W. Grimes name[0] = KERN_VNODE; 1193df8bae1dSRodney W. Grimes error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 1194df8bae1dSRodney W. Grimes break; 1195df8bae1dSRodney W. Grimes 1196df8bae1dSRodney W. Grimes case KINFO_PROC: 1197df8bae1dSRodney W. Grimes name[0] = KERN_PROC; 1198df8bae1dSRodney W. Grimes name[1] = uap->op & 0xff; 1199df8bae1dSRodney W. Grimes name[2] = uap->arg; 1200df8bae1dSRodney W. Grimes error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); 1201df8bae1dSRodney W. Grimes break; 1202df8bae1dSRodney W. Grimes 1203df8bae1dSRodney W. Grimes case KINFO_FILE: 1204df8bae1dSRodney W. Grimes name[0] = KERN_FILE; 1205df8bae1dSRodney W. Grimes error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 1206df8bae1dSRodney W. Grimes break; 1207df8bae1dSRodney W. Grimes 1208df8bae1dSRodney W. Grimes case KINFO_METER: 1209df8bae1dSRodney W. Grimes name[0] = VM_METER; 1210df8bae1dSRodney W. Grimes error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 1211df8bae1dSRodney W. Grimes break; 1212df8bae1dSRodney W. Grimes 1213df8bae1dSRodney W. Grimes case KINFO_LOADAVG: 1214df8bae1dSRodney W. Grimes name[0] = VM_LOADAVG; 1215df8bae1dSRodney W. Grimes error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 1216df8bae1dSRodney W. Grimes break; 1217df8bae1dSRodney W. Grimes 1218df8bae1dSRodney W. Grimes case KINFO_CLOCKRATE: 1219df8bae1dSRodney W. Grimes name[0] = KERN_CLOCKRATE; 1220df8bae1dSRodney W. Grimes error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 1221df8bae1dSRodney W. Grimes break; 1222df8bae1dSRodney W. Grimes 12236ece4a51SPeter Wemm case KINFO_BSDI_SYSINFO: { 12246ece4a51SPeter Wemm /* 12256ece4a51SPeter Wemm * this is pretty crude, but it's just enough for uname() 12266ece4a51SPeter Wemm * from BSDI's 1.x libc to work. 12276ece4a51SPeter Wemm * 12286ece4a51SPeter Wemm * In particular, it doesn't return the same results when 12296ece4a51SPeter Wemm * the supplied buffer is too small. BSDI's version apparently 12306ece4a51SPeter Wemm * will return the amount copied, and set the *size to how 12316ece4a51SPeter Wemm * much was needed. The emulation framework here isn't capable 12326ece4a51SPeter Wemm * of that, so we just set both to the amount copied. 12336ece4a51SPeter Wemm * BSDI's 2.x product apparently fails with ENOMEM in this 12346ece4a51SPeter Wemm * scenario. 12356ece4a51SPeter Wemm */ 12366ece4a51SPeter Wemm 12376ece4a51SPeter Wemm u_int needed; 12386ece4a51SPeter Wemm u_int left; 12396ece4a51SPeter Wemm char *s; 12406ece4a51SPeter Wemm 12416ece4a51SPeter Wemm bzero((char *)&bsdi_si, sizeof(bsdi_si)); 12426ece4a51SPeter Wemm bzero(bsdi_strings, sizeof(bsdi_strings)); 12436ece4a51SPeter Wemm 12446ece4a51SPeter Wemm s = bsdi_strings; 12456ece4a51SPeter Wemm 12466ece4a51SPeter Wemm bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); 12476ece4a51SPeter Wemm strcpy(s, ostype); 12486ece4a51SPeter Wemm s += strlen(s) + 1; 12496ece4a51SPeter Wemm 12506ece4a51SPeter Wemm bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); 12516ece4a51SPeter Wemm strcpy(s, osrelease); 12526ece4a51SPeter Wemm s += strlen(s) + 1; 12536ece4a51SPeter Wemm 12546ece4a51SPeter Wemm bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); 12556ece4a51SPeter Wemm strcpy(s, machine); 12566ece4a51SPeter Wemm s += strlen(s) + 1; 12576ece4a51SPeter Wemm 12586ece4a51SPeter Wemm needed = sizeof(bsdi_si) + (s - bsdi_strings); 12596ece4a51SPeter Wemm 12606ece4a51SPeter Wemm if (uap->where == NULL) { 12616ece4a51SPeter Wemm /* process is asking how much buffer to supply.. */ 12626ece4a51SPeter Wemm size = needed; 12636ece4a51SPeter Wemm error = 0; 12646ece4a51SPeter Wemm break; 12656ece4a51SPeter Wemm } 12666ece4a51SPeter Wemm 12676ece4a51SPeter Wemm 12686ece4a51SPeter Wemm /* if too much buffer supplied, trim it down */ 12696ece4a51SPeter Wemm if (size > needed) 12706ece4a51SPeter Wemm size = needed; 12716ece4a51SPeter Wemm 12726ece4a51SPeter Wemm /* how much of the buffer is remaining */ 12736ece4a51SPeter Wemm left = size; 12746ece4a51SPeter Wemm 12756ece4a51SPeter Wemm if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) 12766ece4a51SPeter Wemm break; 12776ece4a51SPeter Wemm 12786ece4a51SPeter Wemm /* is there any point in continuing? */ 12796ece4a51SPeter Wemm if (left > sizeof(bsdi_si)) { 12806ece4a51SPeter Wemm left -= sizeof(bsdi_si); 12816ece4a51SPeter Wemm error = copyout(&bsdi_strings, 12826ece4a51SPeter Wemm uap->where + sizeof(bsdi_si), left); 12836ece4a51SPeter Wemm } 12846ece4a51SPeter Wemm break; 12856ece4a51SPeter Wemm } 12866ece4a51SPeter Wemm 1287df8bae1dSRodney W. Grimes default: 1288df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 1289df8bae1dSRodney W. Grimes } 1290df8bae1dSRodney W. Grimes if (error) 1291df8bae1dSRodney W. Grimes return (error); 1292df8bae1dSRodney W. Grimes *retval = size; 1293df8bae1dSRodney W. Grimes if (uap->size) 1294df8bae1dSRodney W. Grimes error = copyout((caddr_t)&size, (caddr_t)uap->size, 1295df8bae1dSRodney W. Grimes sizeof(size)); 1296df8bae1dSRodney W. Grimes return (error); 1297df8bae1dSRodney W. Grimes } 1298df8bae1dSRodney W. Grimes #endif /* COMPAT_43 */ 1299