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 372e210993SPoul-Henning Kamp * $Id: kern_sysctl.c,v 1.30 1995/10/28 13:07:23 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 60b396cd83SPoul-Henning Kamp /* BEGIN_MIB */ 612e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_KERN, kern, CTLFLAG_RW, 0, 622e210993SPoul-Henning Kamp "High kernel, proc, limits &c"); 632e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_VM, vm, CTLFLAG_RW, 0, 642e210993SPoul-Henning Kamp "Virtual memory"); 652e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_FS, fs, CTLFLAG_RW, 0, 662e210993SPoul-Henning Kamp "File system"); 672e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_NET, net, CTLFLAG_RW, 0, 682e210993SPoul-Henning Kamp "Network, (see socket.h)"); 692e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_DEBUG, debug, CTLFLAG_RW, 0, 702e210993SPoul-Henning Kamp "Debugging"); 712e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_HW, hw, CTLFLAG_RW, 0, 722e210993SPoul-Henning Kamp "hardware"); 732e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_MACHDEP, machdep, CTLFLAG_RW, 0, 742e210993SPoul-Henning Kamp "machine dependent"); 752e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW, 0, 762e210993SPoul-Henning Kamp "user-level"); 77b396cd83SPoul-Henning Kamp 782e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD, osrelease, 0, ""); 79b396cd83SPoul-Henning Kamp 802e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD, 0, BSD, ""); 81b396cd83SPoul-Henning Kamp 822e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD, version, 0, ""); 83b396cd83SPoul-Henning Kamp 842e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD, ostype, 0, ""); 85b396cd83SPoul-Henning Kamp 86b396cd83SPoul-Henning Kamp extern int osreldate; 872e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD, &osreldate, 0, ""); 88b396cd83SPoul-Henning Kamp 892e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXVNODES, maxvnodes, CTLFLAG_RD, &desiredvnodes, 0, ""); 90b396cd83SPoul-Henning Kamp 912e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXPROC, maxproc, CTLFLAG_RD, &maxproc, 0, ""); 92b396cd83SPoul-Henning Kamp 93b396cd83SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXPROCPERUID, maxprocperuid, 943a34a5c3SPoul-Henning Kamp CTLFLAG_RD, &maxprocperuid, 0, ""); 95b396cd83SPoul-Henning Kamp 96b396cd83SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXFILESPERPROC, maxfilesperproc, 973a34a5c3SPoul-Henning Kamp CTLFLAG_RD, &maxfilesperproc, 0, ""); 98b396cd83SPoul-Henning Kamp 992e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_ARGMAX, argmax, CTLFLAG_RD, 0, ARG_MAX, ""); 100b396cd83SPoul-Henning Kamp 1012e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD, 0, _POSIX_VERSION, ""); 102b396cd83SPoul-Henning Kamp 1032e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RD, 0, NGROUPS_MAX, ""); 104b396cd83SPoul-Henning Kamp 1052e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control, CTLFLAG_RD, 0, 1, ""); 106b396cd83SPoul-Henning Kamp 1072e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXFILES, maxfiles, CTLFLAG_RW, &maxfiles, 0, ""); 108b396cd83SPoul-Henning Kamp 109b396cd83SPoul-Henning Kamp #ifdef _POSIX_SAVED_IDS 1102e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 1, ""); 111b396cd83SPoul-Henning Kamp #else 1122e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 0, ""); 113b396cd83SPoul-Henning Kamp #endif 114b396cd83SPoul-Henning Kamp 115b396cd83SPoul-Henning Kamp char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */ 116b396cd83SPoul-Henning Kamp 117b396cd83SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, 1183a34a5c3SPoul-Henning Kamp CTLFLAG_RW, kernelname, sizeof kernelname, ""); 119b396cd83SPoul-Henning Kamp 120b396cd83SPoul-Henning Kamp SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime, 1213a34a5c3SPoul-Henning Kamp CTLFLAG_RW, &boottime, timeval, ""); 122b396cd83SPoul-Henning Kamp 1232e210993SPoul-Henning Kamp SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 124b396cd83SPoul-Henning Kamp 1252e210993SPoul-Henning Kamp SYSCTL_STRING(_hw, HW_MACHINE, model, CTLFLAG_RD, cpu_model, 0, ""); 126b396cd83SPoul-Henning Kamp 1272e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD, 0, 1, ""); 128b396cd83SPoul-Henning Kamp 1292e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD, 0, BYTE_ORDER, ""); 130b396cd83SPoul-Henning Kamp 1312e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_PAGESIZE, pagesize, CTLFLAG_RD, 0, PAGE_SIZE, ""); 132b396cd83SPoul-Henning Kamp 133b396cd83SPoul-Henning Kamp /* END_MIB */ 134b396cd83SPoul-Henning Kamp 135b396cd83SPoul-Henning Kamp extern int vfs_update_wakeup; 136b396cd83SPoul-Henning Kamp extern int vfs_update_interval; 137b396cd83SPoul-Henning Kamp static int 1383a34a5c3SPoul-Henning Kamp sysctl_kern_updateinterval SYSCTL_HANDLER_ARGS 139b396cd83SPoul-Henning Kamp { 1403a34a5c3SPoul-Henning Kamp int error = sysctl_handle_int(oidp, 1413a34a5c3SPoul-Henning Kamp oidp->oid_arg1, oidp->oid_arg2, 1423a34a5c3SPoul-Henning Kamp oldp, oldlenp, newp, newlen); 1433a34a5c3SPoul-Henning Kamp if (!error) 144b396cd83SPoul-Henning Kamp wakeup(&vfs_update_wakeup); 1453a34a5c3SPoul-Henning Kamp return error; 146b396cd83SPoul-Henning Kamp } 147b396cd83SPoul-Henning Kamp 1482e210993SPoul-Henning Kamp SYSCTL_PROC(_kern, KERN_UPDATEINTERVAL, update, CTLTYPE_INT|CTLFLAG_RW, 1493a34a5c3SPoul-Henning Kamp &vfs_update_interval, 0, sysctl_kern_updateinterval, ""); 150b396cd83SPoul-Henning Kamp 1512e210993SPoul-Henning Kamp 1522e210993SPoul-Henning Kamp char hostname[MAXHOSTNAMELEN]; 1532e210993SPoul-Henning Kamp int hostnamelen; 1542e210993SPoul-Henning Kamp static int 1552e210993SPoul-Henning Kamp sysctl_kern_hostname SYSCTL_HANDLER_ARGS 1562e210993SPoul-Henning Kamp { 1572e210993SPoul-Henning Kamp int error = sysctl_handle_string(oidp, 1582e210993SPoul-Henning Kamp oidp->oid_arg1, oidp->oid_arg2, 1592e210993SPoul-Henning Kamp oldp, oldlenp, newp, newlen); 1602e210993SPoul-Henning Kamp if (newp && (error == 0 || error == ENOMEM)) 1612e210993SPoul-Henning Kamp hostnamelen = newlen; 1622e210993SPoul-Henning Kamp return error; 1632e210993SPoul-Henning Kamp } 1642e210993SPoul-Henning Kamp 1652e210993SPoul-Henning Kamp SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname, CTLTYPE_STRING|CTLFLAG_RW, 1662e210993SPoul-Henning Kamp &hostname, sizeof(hostname), sysctl_kern_hostname, ""); 1672e210993SPoul-Henning Kamp 1682e210993SPoul-Henning Kamp 1692e210993SPoul-Henning Kamp char domainname[MAXHOSTNAMELEN]; 1702e210993SPoul-Henning Kamp int domainnamelen; 1712e210993SPoul-Henning Kamp static int 1722e210993SPoul-Henning Kamp sysctl_kern_domainname SYSCTL_HANDLER_ARGS 1732e210993SPoul-Henning Kamp { 1742e210993SPoul-Henning Kamp int error = sysctl_handle_string(oidp, 1752e210993SPoul-Henning Kamp oidp->oid_arg1, oidp->oid_arg2, 1762e210993SPoul-Henning Kamp oldp, oldlenp, newp, newlen); 1772e210993SPoul-Henning Kamp if (newp && (error == 0 || error == ENOMEM)) 1782e210993SPoul-Henning Kamp domainnamelen = newlen; 1792e210993SPoul-Henning Kamp return error; 1802e210993SPoul-Henning Kamp } 1812e210993SPoul-Henning Kamp 1822e210993SPoul-Henning Kamp SYSCTL_PROC(_kern, KERN_DOMAINNAME, domainname, CTLTYPE_STRING|CTLFLAG_RW, 1832e210993SPoul-Henning Kamp &domainname, sizeof(domainname), sysctl_kern_domainname, ""); 1842e210993SPoul-Henning Kamp 1852e210993SPoul-Henning Kamp long hostid; 1862e210993SPoul-Henning Kamp /* Some trouble here, if sizeof (int) != sizeof (long) */ 1872e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_HOSTID, hostid, CTLFLAG_RW, &hostid, 0, ""); 1882e210993SPoul-Henning Kamp 1893a34a5c3SPoul-Henning Kamp int 1903a34a5c3SPoul-Henning Kamp sysctl_handle_int SYSCTL_HANDLER_ARGS 191b396cd83SPoul-Henning Kamp { 192b396cd83SPoul-Henning Kamp /* If there isn't sufficient space to return */ 193b396cd83SPoul-Henning Kamp if (oldp && *oldlenp < sizeof(int)) 194b396cd83SPoul-Henning Kamp return (ENOMEM); 195b396cd83SPoul-Henning Kamp 196b396cd83SPoul-Henning Kamp /* If it is a constant, don't write */ 1973a34a5c3SPoul-Henning Kamp if (newp && !arg1) 198b396cd83SPoul-Henning Kamp return (EPERM); 199b396cd83SPoul-Henning Kamp 200b396cd83SPoul-Henning Kamp /* If we get more than an int */ 201b396cd83SPoul-Henning Kamp if (newp && newlen != sizeof(int)) 202b396cd83SPoul-Henning Kamp return (EINVAL); 203b396cd83SPoul-Henning Kamp 204b396cd83SPoul-Henning Kamp *oldlenp = sizeof(int); 2053a34a5c3SPoul-Henning Kamp if (oldp && arg1 ) 2062e210993SPoul-Henning Kamp bcopy(arg1, oldp, sizeof(int)); 207b396cd83SPoul-Henning Kamp else if (oldp) 2082e210993SPoul-Henning Kamp bcopy(&arg2, oldp, sizeof(int)); 2092e210993SPoul-Henning Kamp if (newp) 2102e210993SPoul-Henning Kamp bcopy(newp, arg1, sizeof(int)); 2112e210993SPoul-Henning Kamp return (0); 212b396cd83SPoul-Henning Kamp } 213b396cd83SPoul-Henning Kamp 2143a34a5c3SPoul-Henning Kamp int 2153a34a5c3SPoul-Henning Kamp sysctl_handle_string SYSCTL_HANDLER_ARGS 216b396cd83SPoul-Henning Kamp { 2172e210993SPoul-Henning Kamp int len, error=0; 2183a34a5c3SPoul-Henning Kamp char *str = (char *)arg1; 219b396cd83SPoul-Henning Kamp 220b396cd83SPoul-Henning Kamp len = strlen(str) + 1; 221b396cd83SPoul-Henning Kamp 222b396cd83SPoul-Henning Kamp if (oldp && *oldlenp < len) { 223b396cd83SPoul-Henning Kamp len = *oldlenp; 2242e210993SPoul-Henning Kamp error=ENOMEM; 225b396cd83SPoul-Henning Kamp } 226b396cd83SPoul-Henning Kamp 2273a34a5c3SPoul-Henning Kamp if (newp && newlen >= arg2) 228b396cd83SPoul-Henning Kamp return (EINVAL); 229b396cd83SPoul-Henning Kamp 230b396cd83SPoul-Henning Kamp if (oldp) { 231b396cd83SPoul-Henning Kamp *oldlenp = len; 2322e210993SPoul-Henning Kamp bcopy(str, oldp, len); 233b396cd83SPoul-Henning Kamp } 2342e210993SPoul-Henning Kamp 2352e210993SPoul-Henning Kamp if (newp) { 2362e210993SPoul-Henning Kamp bcopy(newp, str, newlen); 237b396cd83SPoul-Henning Kamp str[newlen] = 0; 238b396cd83SPoul-Henning Kamp } 2392e210993SPoul-Henning Kamp return (error); 240b396cd83SPoul-Henning Kamp } 241b396cd83SPoul-Henning Kamp 2423a34a5c3SPoul-Henning Kamp int 2433a34a5c3SPoul-Henning Kamp sysctl_handle_opaque SYSCTL_HANDLER_ARGS 244b396cd83SPoul-Henning Kamp { 2452e210993SPoul-Henning Kamp if (oldp && *oldlenp < arg2) 246b396cd83SPoul-Henning Kamp return (ENOMEM); 247b396cd83SPoul-Henning Kamp 2483a34a5c3SPoul-Henning Kamp if (newp && newlen != arg2) 249b396cd83SPoul-Henning Kamp return (EINVAL); 250b396cd83SPoul-Henning Kamp 251b396cd83SPoul-Henning Kamp if (oldp) { 2523a34a5c3SPoul-Henning Kamp *oldlenp = arg2; 2532e210993SPoul-Henning Kamp bcopy(arg1, oldp, arg2); 254b396cd83SPoul-Henning Kamp } 2552e210993SPoul-Henning Kamp if (newp) 2562e210993SPoul-Henning Kamp bcopy(newp, arg1, arg2); 2572e210993SPoul-Henning Kamp return (0); 258b396cd83SPoul-Henning Kamp } 259b396cd83SPoul-Henning Kamp 2603a34a5c3SPoul-Henning Kamp #ifdef DEBUG 2613a34a5c3SPoul-Henning Kamp static sysctlfn debug_sysctl; 2623a34a5c3SPoul-Henning Kamp #endif 263b396cd83SPoul-Henning Kamp 264df8bae1dSRodney W. Grimes /* 265df8bae1dSRodney W. Grimes * Locking and stats 266df8bae1dSRodney W. Grimes */ 267df8bae1dSRodney W. Grimes static struct sysctl_lock { 268df8bae1dSRodney W. Grimes int sl_lock; 269df8bae1dSRodney W. Grimes int sl_want; 270df8bae1dSRodney W. Grimes int sl_locked; 271df8bae1dSRodney W. Grimes } memlock; 272df8bae1dSRodney W. Grimes 273df8bae1dSRodney W. Grimes struct sysctl_args { 274df8bae1dSRodney W. Grimes int *name; 275df8bae1dSRodney W. Grimes u_int namelen; 276df8bae1dSRodney W. Grimes void *old; 277df8bae1dSRodney W. Grimes size_t *oldlenp; 278df8bae1dSRodney W. Grimes void *new; 279df8bae1dSRodney W. Grimes size_t newlen; 280df8bae1dSRodney W. Grimes }; 281df8bae1dSRodney W. Grimes 2822e210993SPoul-Henning Kamp 2832e210993SPoul-Henning Kamp 2842e210993SPoul-Henning Kamp /* 2852e210993SPoul-Henning Kamp * Traverse our tree, and find the right node, execute whatever it points 2862e210993SPoul-Henning Kamp * at, and return the resulting error code. 2872e210993SPoul-Henning Kamp * We work entirely in kernel-space at this time. 2882e210993SPoul-Henning Kamp */ 2892e210993SPoul-Henning Kamp 290b396cd83SPoul-Henning Kamp extern struct linker_set sysctl_; 291b396cd83SPoul-Henning Kamp 2922e210993SPoul-Henning Kamp int sysctl_dummy; 2932e210993SPoul-Henning Kamp 2942e210993SPoul-Henning Kamp int 2952e210993SPoul-Henning Kamp sysctl_root SYSCTL_HANDLER_ARGS 2962e210993SPoul-Henning Kamp { 2972e210993SPoul-Henning Kamp int *name = (int *) arg1; 2982e210993SPoul-Henning Kamp int namelen = arg2; 2992e210993SPoul-Henning Kamp int indx, i, j; 3002e210993SPoul-Henning Kamp struct sysctl_oid **oidpp; 3012e210993SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 3022e210993SPoul-Henning Kamp 3032e210993SPoul-Henning Kamp j = lsp->ls_length; 3042e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 3052e210993SPoul-Henning Kamp 3062e210993SPoul-Henning Kamp indx = 0; 3072e210993SPoul-Henning Kamp while (j-- && indx < CTL_MAXNAME) { 3082e210993SPoul-Henning Kamp if (*oidpp && 3092e210993SPoul-Henning Kamp ((void *)&sysctl_dummy != (void *)*oidpp) && 3102e210993SPoul-Henning Kamp ((*oidpp)->oid_number == name[indx])) { 3112e210993SPoul-Henning Kamp indx++; 3122e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 3132e210993SPoul-Henning Kamp if ((*oidpp)->oid_handler) 3142e210993SPoul-Henning Kamp goto found; 3152e210993SPoul-Henning Kamp if (indx == namelen) 3162e210993SPoul-Henning Kamp return ENOENT; 3172e210993SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 3182e210993SPoul-Henning Kamp j = lsp->ls_length; 3192e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 3202e210993SPoul-Henning Kamp } else { 3212e210993SPoul-Henning Kamp if (indx != namelen) 3222e210993SPoul-Henning Kamp return EISDIR; 3232e210993SPoul-Henning Kamp goto found; 3242e210993SPoul-Henning Kamp } 3252e210993SPoul-Henning Kamp } else { 3262e210993SPoul-Henning Kamp oidpp++; 3272e210993SPoul-Henning Kamp } 3282e210993SPoul-Henning Kamp } 3292e210993SPoul-Henning Kamp return EJUSTRETURN; 3302e210993SPoul-Henning Kamp found: 3312e210993SPoul-Henning Kamp 3322e210993SPoul-Henning Kamp /* If writing isn't allowed */ 3332e210993SPoul-Henning Kamp if (newp && !((*oidpp)->oid_kind & CTLFLAG_WR)) 3342e210993SPoul-Henning Kamp return (EPERM); 3352e210993SPoul-Henning Kamp 3362e210993SPoul-Henning Kamp if (!(*oidpp)->oid_handler) 3372e210993SPoul-Henning Kamp return EINVAL; 3382e210993SPoul-Henning Kamp 3392e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 3402e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 3412e210993SPoul-Henning Kamp name + indx, namelen - indx, 3422e210993SPoul-Henning Kamp oldp, oldlenp, newp, newlen); 3432e210993SPoul-Henning Kamp } else { 3442e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 3452e210993SPoul-Henning Kamp (*oidpp)->oid_arg1, (*oidpp)->oid_arg2, 3462e210993SPoul-Henning Kamp oldp, oldlenp, newp, newlen); 3472e210993SPoul-Henning Kamp } 3482e210993SPoul-Henning Kamp return (i); 3492e210993SPoul-Henning Kamp } 3502e210993SPoul-Henning Kamp 351df8bae1dSRodney W. Grimes int 352df8bae1dSRodney W. Grimes __sysctl(p, uap, retval) 353df8bae1dSRodney W. Grimes struct proc *p; 354df8bae1dSRodney W. Grimes register struct sysctl_args *uap; 355df8bae1dSRodney W. Grimes int *retval; 356df8bae1dSRodney W. Grimes { 357b396cd83SPoul-Henning Kamp int error, dolock = 1, i; 35826f9a767SRodney W. Grimes u_int savelen = 0, oldlen = 0; 359df8bae1dSRodney W. Grimes sysctlfn *fn; 360df8bae1dSRodney W. Grimes int name[CTL_MAXNAME]; 3612e210993SPoul-Henning Kamp void *oldp = 0; 3622e210993SPoul-Henning Kamp void *newp = 0; 363df8bae1dSRodney W. Grimes 364df8bae1dSRodney W. Grimes if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 365df8bae1dSRodney W. Grimes return (error); 366b396cd83SPoul-Henning Kamp 367df8bae1dSRodney W. Grimes /* 368df8bae1dSRodney W. Grimes * all top-level sysctl names are non-terminal 369df8bae1dSRodney W. Grimes */ 370b396cd83SPoul-Henning Kamp 371df8bae1dSRodney W. Grimes if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 372df8bae1dSRodney W. Grimes return (EINVAL); 373b396cd83SPoul-Henning Kamp 374797f2d22SPoul-Henning Kamp error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 375797f2d22SPoul-Henning Kamp if (error) 376df8bae1dSRodney W. Grimes return (error); 377df8bae1dSRodney W. Grimes 378b396cd83SPoul-Henning Kamp if (uap->oldlenp && 379b396cd83SPoul-Henning Kamp (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) 380b396cd83SPoul-Henning Kamp return (error); 381b396cd83SPoul-Henning Kamp 3822e210993SPoul-Henning Kamp if (uap->old) 3832e210993SPoul-Henning Kamp oldp = malloc(oldlen, M_TEMP, M_WAITOK); 3842e210993SPoul-Henning Kamp 3852e210993SPoul-Henning Kamp if (uap->newlen) { 3862e210993SPoul-Henning Kamp newp = malloc(uap->newlen, M_TEMP, M_WAITOK); 3872e210993SPoul-Henning Kamp error = copyin(uap->new, newp, uap->newlen); 388b396cd83SPoul-Henning Kamp } 3892e210993SPoul-Henning Kamp if (error) { 3902e210993SPoul-Henning Kamp if (oldp) 3912e210993SPoul-Henning Kamp free(oldp, M_TEMP); 3922e210993SPoul-Henning Kamp if (newp) 3932e210993SPoul-Henning Kamp free(newp, M_TEMP); 3942e210993SPoul-Henning Kamp return error; 395b396cd83SPoul-Henning Kamp } 396b396cd83SPoul-Henning Kamp 3972e210993SPoul-Henning Kamp error = sysctl_root(0, name, uap->namelen, oldp, &oldlen, 3982e210993SPoul-Henning Kamp newp, uap->newlen); 3992e210993SPoul-Henning Kamp #if 0 4002e210993SPoul-Henning Kamp if (error) { 4012e210993SPoul-Henning Kamp printf("SYSCTL_ROOT: "); 4022e210993SPoul-Henning Kamp for(i=0;i<uap->namelen;i++) 4032e210993SPoul-Henning Kamp printf("%d ", name[i]); 4042e210993SPoul-Henning Kamp printf("= %d\n", error); 4052e210993SPoul-Henning Kamp } 4062e210993SPoul-Henning Kamp #endif 407b396cd83SPoul-Henning Kamp 4082e210993SPoul-Henning Kamp if (!error || error == ENOMEM) { 4092e210993SPoul-Henning Kamp if (uap->oldlenp) { 4102e210993SPoul-Henning Kamp i = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); 411b396cd83SPoul-Henning Kamp if (i) 412b396cd83SPoul-Henning Kamp error = i; 4132e210993SPoul-Henning Kamp } 4142e210993SPoul-Henning Kamp if ((error == ENOMEM || !error ) && oldp) { 4152e210993SPoul-Henning Kamp i = copyout(oldp, uap->old, oldlen); 4162e210993SPoul-Henning Kamp if (i) 4172e210993SPoul-Henning Kamp error = i; 4182e210993SPoul-Henning Kamp free(oldp, M_TEMP); 4192e210993SPoul-Henning Kamp } 4202e210993SPoul-Henning Kamp if (newp) 4212e210993SPoul-Henning Kamp free(newp, M_TEMP); 4222e210993SPoul-Henning Kamp return (error); 4232e210993SPoul-Henning Kamp } 424b396cd83SPoul-Henning Kamp 4252e210993SPoul-Henning Kamp if (oldp) 4262e210993SPoul-Henning Kamp free(oldp, M_TEMP); 4272e210993SPoul-Henning Kamp if (newp) 4282e210993SPoul-Henning Kamp free(newp, M_TEMP); 4292e210993SPoul-Henning Kamp 430df8bae1dSRodney W. Grimes switch (name[0]) { 431df8bae1dSRodney W. Grimes case CTL_KERN: 432df8bae1dSRodney W. Grimes fn = kern_sysctl; 433e9e2a852SAndrey A. Chernov if (name[1] != KERN_VNODE) /* XXX */ 434df8bae1dSRodney W. Grimes dolock = 0; 435df8bae1dSRodney W. Grimes break; 436df8bae1dSRodney W. Grimes case CTL_HW: 437df8bae1dSRodney W. Grimes fn = hw_sysctl; 438df8bae1dSRodney W. Grimes break; 439df8bae1dSRodney W. Grimes case CTL_VM: 440df8bae1dSRodney W. Grimes fn = vm_sysctl; 441df8bae1dSRodney W. Grimes break; 442df8bae1dSRodney W. Grimes case CTL_NET: 4432e210993SPoul-Henning Kamp #if 0 4442e210993SPoul-Henning Kamp printf("SYSCTL_NET: "); 4452e210993SPoul-Henning Kamp for(i=0;i<uap->namelen;i++) 4462e210993SPoul-Henning Kamp printf("%d ", name[i]); 4472e210993SPoul-Henning Kamp printf("\n"); 4482e210993SPoul-Henning Kamp #endif 449df8bae1dSRodney W. Grimes fn = net_sysctl; 450df8bae1dSRodney W. Grimes break; 451df8bae1dSRodney W. Grimes case CTL_FS: 452df8bae1dSRodney W. Grimes fn = fs_sysctl; 453df8bae1dSRodney W. Grimes break; 454df8bae1dSRodney W. Grimes case CTL_MACHDEP: 455df8bae1dSRodney W. Grimes fn = cpu_sysctl; 456df8bae1dSRodney W. Grimes break; 457df8bae1dSRodney W. Grimes #ifdef DEBUG 458df8bae1dSRodney W. Grimes case CTL_DEBUG: 459df8bae1dSRodney W. Grimes fn = debug_sysctl; 460df8bae1dSRodney W. Grimes break; 461df8bae1dSRodney W. Grimes #endif 462df8bae1dSRodney W. Grimes default: 463df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 464df8bae1dSRodney W. Grimes } 465df8bae1dSRodney W. Grimes if (uap->old != NULL) { 466df8bae1dSRodney W. Grimes if (!useracc(uap->old, oldlen, B_WRITE)) 467df8bae1dSRodney W. Grimes return (EFAULT); 468df8bae1dSRodney W. Grimes while (memlock.sl_lock) { 469df8bae1dSRodney W. Grimes memlock.sl_want = 1; 47082478919SDavid Greenman (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 471df8bae1dSRodney W. Grimes memlock.sl_locked++; 472df8bae1dSRodney W. Grimes } 473df8bae1dSRodney W. Grimes memlock.sl_lock = 1; 474df8bae1dSRodney W. Grimes if (dolock) 475df8bae1dSRodney W. Grimes vslock(uap->old, oldlen); 476df8bae1dSRodney W. Grimes savelen = oldlen; 477df8bae1dSRodney W. Grimes } 478b396cd83SPoul-Henning Kamp 479b396cd83SPoul-Henning Kamp 480df8bae1dSRodney W. Grimes error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, 481df8bae1dSRodney W. Grimes uap->new, uap->newlen, p); 4822e210993SPoul-Henning Kamp 4832e210993SPoul-Henning Kamp 484df8bae1dSRodney W. Grimes if (uap->old != NULL) { 485df8bae1dSRodney W. Grimes if (dolock) 486df8bae1dSRodney W. Grimes vsunlock(uap->old, savelen, B_WRITE); 487df8bae1dSRodney W. Grimes memlock.sl_lock = 0; 488df8bae1dSRodney W. Grimes if (memlock.sl_want) { 489df8bae1dSRodney W. Grimes memlock.sl_want = 0; 490df8bae1dSRodney W. Grimes wakeup((caddr_t)&memlock); 491df8bae1dSRodney W. Grimes } 492df8bae1dSRodney W. Grimes } 493df8bae1dSRodney W. Grimes if (error) 494df8bae1dSRodney W. Grimes return (error); 495df8bae1dSRodney W. Grimes if (uap->oldlenp) 496df8bae1dSRodney W. Grimes error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); 497df8bae1dSRodney W. Grimes *retval = oldlen; 498df8bae1dSRodney W. Grimes return (0); 499df8bae1dSRodney W. Grimes } 500df8bae1dSRodney W. Grimes 501df8bae1dSRodney W. Grimes /* 502df8bae1dSRodney W. Grimes * Attributes stored in the kernel. 503df8bae1dSRodney W. Grimes */ 5046ae6a09bSGarrett Wollman int securelevel = -1; 505df8bae1dSRodney W. Grimes 506df8bae1dSRodney W. Grimes /* 507df8bae1dSRodney W. Grimes * kernel related system variables. 508df8bae1dSRodney W. Grimes */ 50926f9a767SRodney W. Grimes int 510df8bae1dSRodney W. Grimes kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 511df8bae1dSRodney W. Grimes int *name; 512df8bae1dSRodney W. Grimes u_int namelen; 513df8bae1dSRodney W. Grimes void *oldp; 514df8bae1dSRodney W. Grimes size_t *oldlenp; 515df8bae1dSRodney W. Grimes void *newp; 516df8bae1dSRodney W. Grimes size_t newlen; 517df8bae1dSRodney W. Grimes struct proc *p; 518df8bae1dSRodney W. Grimes { 5192e210993SPoul-Henning Kamp int error, level; 5205bb4f738SGarrett Wollman dev_t ndumpdev; 521df8bae1dSRodney W. Grimes 522df8bae1dSRodney W. Grimes /* all sysctl names at this level are terminal */ 5233f31c649SGarrett Wollman if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF 5243f31c649SGarrett Wollman || name[0] == KERN_NTP_PLL)) 525df8bae1dSRodney W. Grimes return (ENOTDIR); /* overloaded */ 526df8bae1dSRodney W. Grimes 527df8bae1dSRodney W. Grimes switch (name[0]) { 528b396cd83SPoul-Henning Kamp 529df8bae1dSRodney W. Grimes case KERN_SECURELVL: 530df8bae1dSRodney W. Grimes level = securelevel; 531df8bae1dSRodney W. Grimes if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 532df8bae1dSRodney W. Grimes newp == NULL) 533df8bae1dSRodney W. Grimes return (error); 534df8bae1dSRodney W. Grimes if (level < securelevel && p->p_pid != 1) 535df8bae1dSRodney W. Grimes return (EPERM); 536df8bae1dSRodney W. Grimes securelevel = level; 537df8bae1dSRodney W. Grimes return (0); 538df8bae1dSRodney W. Grimes case KERN_VNODE: 539df8bae1dSRodney W. Grimes return (sysctl_vnode(oldp, oldlenp)); 540df8bae1dSRodney W. Grimes case KERN_PROC: 541df8bae1dSRodney W. Grimes return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 542df8bae1dSRodney W. Grimes case KERN_FILE: 543df8bae1dSRodney W. Grimes return (sysctl_file(oldp, oldlenp)); 544df8bae1dSRodney W. Grimes #ifdef GPROF 545df8bae1dSRodney W. Grimes case KERN_PROF: 546df8bae1dSRodney W. Grimes return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 547df8bae1dSRodney W. Grimes newp, newlen)); 548df8bae1dSRodney W. Grimes #endif 5493f31c649SGarrett Wollman case KERN_NTP_PLL: 5503f31c649SGarrett Wollman return (ntp_sysctl(name + 1, namelen - 1, oldp, oldlenp, 5513f31c649SGarrett Wollman newp, newlen, p)); 5525bb4f738SGarrett Wollman case KERN_DUMPDEV: 5535bb4f738SGarrett Wollman ndumpdev = dumpdev; 5545bb4f738SGarrett Wollman error = sysctl_struct(oldp, oldlenp, newp, newlen, &ndumpdev, 5555bb4f738SGarrett Wollman sizeof ndumpdev); 5565bb4f738SGarrett Wollman if (!error && ndumpdev != dumpdev) { 5575bb4f738SGarrett Wollman error = setdumpdev(ndumpdev); 5585bb4f738SGarrett Wollman } 5595bb4f738SGarrett Wollman return error; 560df8bae1dSRodney W. Grimes default: 561df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 562df8bae1dSRodney W. Grimes } 563df8bae1dSRodney W. Grimes /* NOTREACHED */ 564df8bae1dSRodney W. Grimes } 565df8bae1dSRodney W. Grimes 566df8bae1dSRodney W. Grimes /* 567df8bae1dSRodney W. Grimes * hardware related system variables. 568df8bae1dSRodney W. Grimes */ 56926f9a767SRodney W. Grimes int 570df8bae1dSRodney W. Grimes hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 571df8bae1dSRodney W. Grimes int *name; 572df8bae1dSRodney W. Grimes u_int namelen; 573df8bae1dSRodney W. Grimes void *oldp; 574df8bae1dSRodney W. Grimes size_t *oldlenp; 575df8bae1dSRodney W. Grimes void *newp; 576df8bae1dSRodney W. Grimes size_t newlen; 577df8bae1dSRodney W. Grimes struct proc *p; 578df8bae1dSRodney W. Grimes { 5798478cabaSGarrett Wollman /* almost all sysctl names at this level are terminal */ 5808478cabaSGarrett Wollman if (namelen != 1 && name[0] != HW_DEVCONF) 581df8bae1dSRodney W. Grimes return (ENOTDIR); /* overloaded */ 582df8bae1dSRodney W. Grimes 583df8bae1dSRodney W. Grimes switch (name[0]) { 584df8bae1dSRodney W. Grimes case HW_PHYSMEM: 585df8bae1dSRodney W. Grimes return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 586df8bae1dSRodney W. Grimes case HW_USERMEM: 587df8bae1dSRodney W. Grimes return (sysctl_rdint(oldp, oldlenp, newp, 588df8bae1dSRodney W. Grimes ctob(physmem - cnt.v_wire_count))); 5898478cabaSGarrett Wollman case HW_DEVCONF: 5908478cabaSGarrett Wollman return (dev_sysctl(name + 1, namelen - 1, oldp, oldlenp, 5918478cabaSGarrett Wollman newp, newlen, p)); 592df8bae1dSRodney W. Grimes default: 593df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 594df8bae1dSRodney W. Grimes } 595df8bae1dSRodney W. Grimes /* NOTREACHED */ 596df8bae1dSRodney W. Grimes } 597df8bae1dSRodney W. Grimes 598df8bae1dSRodney W. Grimes #ifdef DEBUG 599df8bae1dSRodney W. Grimes /* 600df8bae1dSRodney W. Grimes * Debugging related system variables. 601df8bae1dSRodney W. Grimes */ 602df8bae1dSRodney W. Grimes struct ctldebug debug0, debug1, debug2, debug3, debug4; 603df8bae1dSRodney W. Grimes struct ctldebug debug5, debug6, debug7, debug8, debug9; 604df8bae1dSRodney W. Grimes struct ctldebug debug10, debug11, debug12, debug13, debug14; 605df8bae1dSRodney W. Grimes struct ctldebug debug15, debug16, debug17, debug18, debug19; 606df8bae1dSRodney W. Grimes static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 607df8bae1dSRodney W. Grimes &debug0, &debug1, &debug2, &debug3, &debug4, 608df8bae1dSRodney W. Grimes &debug5, &debug6, &debug7, &debug8, &debug9, 609df8bae1dSRodney W. Grimes &debug10, &debug11, &debug12, &debug13, &debug14, 610df8bae1dSRodney W. Grimes &debug15, &debug16, &debug17, &debug18, &debug19, 611df8bae1dSRodney W. Grimes }; 6126124ac44SBruce Evans static int 613df8bae1dSRodney W. Grimes debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 614df8bae1dSRodney W. Grimes int *name; 615df8bae1dSRodney W. Grimes u_int namelen; 616df8bae1dSRodney W. Grimes void *oldp; 617df8bae1dSRodney W. Grimes size_t *oldlenp; 618df8bae1dSRodney W. Grimes void *newp; 619df8bae1dSRodney W. Grimes size_t newlen; 620df8bae1dSRodney W. Grimes struct proc *p; 621df8bae1dSRodney W. Grimes { 622df8bae1dSRodney W. Grimes struct ctldebug *cdp; 623df8bae1dSRodney W. Grimes 624df8bae1dSRodney W. Grimes /* all sysctl names at this level are name and field */ 625df8bae1dSRodney W. Grimes if (namelen != 2) 626df8bae1dSRodney W. Grimes return (ENOTDIR); /* overloaded */ 627df8bae1dSRodney W. Grimes cdp = debugvars[name[0]]; 628df8bae1dSRodney W. Grimes if (cdp->debugname == 0) 629df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 630df8bae1dSRodney W. Grimes switch (name[1]) { 631df8bae1dSRodney W. Grimes case CTL_DEBUG_NAME: 632df8bae1dSRodney W. Grimes return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 633df8bae1dSRodney W. Grimes case CTL_DEBUG_VALUE: 634df8bae1dSRodney W. Grimes return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 635df8bae1dSRodney W. Grimes default: 636df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 637df8bae1dSRodney W. Grimes } 638df8bae1dSRodney W. Grimes /* NOTREACHED */ 639df8bae1dSRodney W. Grimes } 640df8bae1dSRodney W. Grimes #endif /* DEBUG */ 641df8bae1dSRodney W. Grimes 642df8bae1dSRodney W. Grimes /* 643df8bae1dSRodney W. Grimes * Validate parameters and get old / set new parameters 644df8bae1dSRodney W. Grimes * for an integer-valued sysctl function. 645df8bae1dSRodney W. Grimes */ 64626f9a767SRodney W. Grimes int 647df8bae1dSRodney W. Grimes sysctl_int(oldp, oldlenp, newp, newlen, valp) 648df8bae1dSRodney W. Grimes void *oldp; 649df8bae1dSRodney W. Grimes size_t *oldlenp; 650df8bae1dSRodney W. Grimes void *newp; 651df8bae1dSRodney W. Grimes size_t newlen; 652df8bae1dSRodney W. Grimes int *valp; 653df8bae1dSRodney W. Grimes { 654df8bae1dSRodney W. Grimes int error = 0; 655df8bae1dSRodney W. Grimes 656df8bae1dSRodney W. Grimes if (oldp && *oldlenp < sizeof(int)) 657df8bae1dSRodney W. Grimes return (ENOMEM); 658df8bae1dSRodney W. Grimes if (newp && newlen != sizeof(int)) 659df8bae1dSRodney W. Grimes return (EINVAL); 660df8bae1dSRodney W. Grimes *oldlenp = sizeof(int); 661df8bae1dSRodney W. Grimes if (oldp) 662df8bae1dSRodney W. Grimes error = copyout(valp, oldp, sizeof(int)); 663df8bae1dSRodney W. Grimes if (error == 0 && newp) 664df8bae1dSRodney W. Grimes error = copyin(newp, valp, sizeof(int)); 665df8bae1dSRodney W. Grimes return (error); 666df8bae1dSRodney W. Grimes } 667df8bae1dSRodney W. Grimes 668df8bae1dSRodney W. Grimes /* 669df8bae1dSRodney W. Grimes * As above, but read-only. 670df8bae1dSRodney W. Grimes */ 67126f9a767SRodney W. Grimes int 672df8bae1dSRodney W. Grimes sysctl_rdint(oldp, oldlenp, newp, val) 673df8bae1dSRodney W. Grimes void *oldp; 674df8bae1dSRodney W. Grimes size_t *oldlenp; 675df8bae1dSRodney W. Grimes void *newp; 676df8bae1dSRodney W. Grimes int val; 677df8bae1dSRodney W. Grimes { 678df8bae1dSRodney W. Grimes int error = 0; 679df8bae1dSRodney W. Grimes 680df8bae1dSRodney W. Grimes if (oldp && *oldlenp < sizeof(int)) 681df8bae1dSRodney W. Grimes return (ENOMEM); 682df8bae1dSRodney W. Grimes if (newp) 683df8bae1dSRodney W. Grimes return (EPERM); 684df8bae1dSRodney W. Grimes *oldlenp = sizeof(int); 685df8bae1dSRodney W. Grimes if (oldp) 686df8bae1dSRodney W. Grimes error = copyout((caddr_t)&val, oldp, sizeof(int)); 687df8bae1dSRodney W. Grimes return (error); 688df8bae1dSRodney W. Grimes } 689df8bae1dSRodney W. Grimes 690df8bae1dSRodney W. Grimes /* 691df8bae1dSRodney W. Grimes * Validate parameters and get old / set new parameters 692df8bae1dSRodney W. Grimes * for a string-valued sysctl function. 693df8bae1dSRodney W. Grimes */ 69426f9a767SRodney W. Grimes int 695df8bae1dSRodney W. Grimes sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 696df8bae1dSRodney W. Grimes void *oldp; 697df8bae1dSRodney W. Grimes size_t *oldlenp; 698df8bae1dSRodney W. Grimes void *newp; 699df8bae1dSRodney W. Grimes size_t newlen; 700df8bae1dSRodney W. Grimes char *str; 701df8bae1dSRodney W. Grimes int maxlen; 702df8bae1dSRodney W. Grimes { 703e1453736SMike Pritchard int len, error = 0, rval = 0; 704df8bae1dSRodney W. Grimes 705df8bae1dSRodney W. Grimes len = strlen(str) + 1; 706e1453736SMike Pritchard if (oldp && *oldlenp < len) { 707f81fcd41SGuido van Rooij len = *oldlenp; 708e1453736SMike Pritchard rval = ENOMEM; 709e1453736SMike Pritchard } 710df8bae1dSRodney W. Grimes if (newp && newlen >= maxlen) 711df8bae1dSRodney W. Grimes return (EINVAL); 712df8bae1dSRodney W. Grimes if (oldp) { 713df8bae1dSRodney W. Grimes *oldlenp = len; 714df8bae1dSRodney W. Grimes error = copyout(str, oldp, len); 715e1453736SMike Pritchard if (error) 716e1453736SMike Pritchard rval = error; 717df8bae1dSRodney W. Grimes } 718e1453736SMike Pritchard if ((error == 0 || error == ENOMEM) && newp) { 719df8bae1dSRodney W. Grimes error = copyin(newp, str, newlen); 720e1453736SMike Pritchard if (error) 721e1453736SMike Pritchard rval = error; 722df8bae1dSRodney W. Grimes str[newlen] = 0; 723df8bae1dSRodney W. Grimes } 724e1453736SMike Pritchard return (rval); 725df8bae1dSRodney W. Grimes } 726df8bae1dSRodney W. Grimes 727df8bae1dSRodney W. Grimes /* 728df8bae1dSRodney W. Grimes * As above, but read-only. 729df8bae1dSRodney W. Grimes */ 73026f9a767SRodney W. Grimes int 731df8bae1dSRodney W. Grimes sysctl_rdstring(oldp, oldlenp, newp, str) 732df8bae1dSRodney W. Grimes void *oldp; 733df8bae1dSRodney W. Grimes size_t *oldlenp; 734df8bae1dSRodney W. Grimes void *newp; 735df8bae1dSRodney W. Grimes char *str; 736df8bae1dSRodney W. Grimes { 737e1453736SMike Pritchard int len, error = 0, rval = 0; 738df8bae1dSRodney W. Grimes 739df8bae1dSRodney W. Grimes len = strlen(str) + 1; 740e1453736SMike Pritchard if (oldp && *oldlenp < len) { 741e1453736SMike Pritchard len = *oldlenp; 742e1453736SMike Pritchard rval = ENOMEM; 743e1453736SMike Pritchard } 744df8bae1dSRodney W. Grimes if (newp) 745df8bae1dSRodney W. Grimes return (EPERM); 746df8bae1dSRodney W. Grimes *oldlenp = len; 747df8bae1dSRodney W. Grimes if (oldp) 748df8bae1dSRodney W. Grimes error = copyout(str, oldp, len); 749e1453736SMike Pritchard if (error) 750e1453736SMike Pritchard rval = error; 751e1453736SMike Pritchard return (rval); 752df8bae1dSRodney W. Grimes } 753df8bae1dSRodney W. Grimes 754df8bae1dSRodney W. Grimes /* 755df8bae1dSRodney W. Grimes * Validate parameters and get old / set new parameters 756df8bae1dSRodney W. Grimes * for a structure oriented sysctl function. 757df8bae1dSRodney W. Grimes */ 75826f9a767SRodney W. Grimes int 759df8bae1dSRodney W. Grimes sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 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 void *sp; 765df8bae1dSRodney W. Grimes int len; 766df8bae1dSRodney W. Grimes { 767df8bae1dSRodney W. Grimes int error = 0; 768df8bae1dSRodney W. Grimes 769df8bae1dSRodney W. Grimes if (oldp && *oldlenp < len) 770df8bae1dSRodney W. Grimes return (ENOMEM); 771df8bae1dSRodney W. Grimes if (newp && newlen > len) 772df8bae1dSRodney W. Grimes return (EINVAL); 773df8bae1dSRodney W. Grimes if (oldp) { 774df8bae1dSRodney W. Grimes *oldlenp = len; 775df8bae1dSRodney W. Grimes error = copyout(sp, oldp, len); 776df8bae1dSRodney W. Grimes } 777df8bae1dSRodney W. Grimes if (error == 0 && newp) 778df8bae1dSRodney W. Grimes error = copyin(newp, sp, len); 779df8bae1dSRodney W. Grimes return (error); 780df8bae1dSRodney W. Grimes } 781df8bae1dSRodney W. Grimes 782df8bae1dSRodney W. Grimes /* 783df8bae1dSRodney W. Grimes * Validate parameters and get old parameters 784df8bae1dSRodney W. Grimes * for a structure oriented sysctl function. 785df8bae1dSRodney W. Grimes */ 78626f9a767SRodney W. Grimes int 787df8bae1dSRodney W. Grimes sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 788df8bae1dSRodney W. Grimes void *oldp; 789df8bae1dSRodney W. Grimes size_t *oldlenp; 790df8bae1dSRodney W. Grimes void *newp, *sp; 791df8bae1dSRodney W. Grimes int len; 792df8bae1dSRodney W. Grimes { 793df8bae1dSRodney W. Grimes int error = 0; 794df8bae1dSRodney W. Grimes 795df8bae1dSRodney W. Grimes if (oldp && *oldlenp < len) 796df8bae1dSRodney W. Grimes return (ENOMEM); 797df8bae1dSRodney W. Grimes if (newp) 798df8bae1dSRodney W. Grimes return (EPERM); 799df8bae1dSRodney W. Grimes *oldlenp = len; 800df8bae1dSRodney W. Grimes if (oldp) 801df8bae1dSRodney W. Grimes error = copyout(sp, oldp, len); 802df8bae1dSRodney W. Grimes return (error); 803df8bae1dSRodney W. Grimes } 804df8bae1dSRodney W. Grimes 805df8bae1dSRodney W. Grimes /* 806df8bae1dSRodney W. Grimes * Get file structures. 807df8bae1dSRodney W. Grimes */ 80826f9a767SRodney W. Grimes int 809df8bae1dSRodney W. Grimes sysctl_file(where, sizep) 810df8bae1dSRodney W. Grimes char *where; 811df8bae1dSRodney W. Grimes size_t *sizep; 812df8bae1dSRodney W. Grimes { 813df8bae1dSRodney W. Grimes int buflen, error; 814df8bae1dSRodney W. Grimes struct file *fp; 815df8bae1dSRodney W. Grimes char *start = where; 816df8bae1dSRodney W. Grimes 817df8bae1dSRodney W. Grimes buflen = *sizep; 818df8bae1dSRodney W. Grimes if (where == NULL) { 819df8bae1dSRodney W. Grimes /* 820df8bae1dSRodney W. Grimes * overestimate by 10 files 821df8bae1dSRodney W. Grimes */ 822df8bae1dSRodney W. Grimes *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 823df8bae1dSRodney W. Grimes return (0); 824df8bae1dSRodney W. Grimes } 825df8bae1dSRodney W. Grimes 826df8bae1dSRodney W. Grimes /* 827df8bae1dSRodney W. Grimes * first copyout filehead 828df8bae1dSRodney W. Grimes */ 829df8bae1dSRodney W. Grimes if (buflen < sizeof(filehead)) { 830df8bae1dSRodney W. Grimes *sizep = 0; 831df8bae1dSRodney W. Grimes return (0); 832df8bae1dSRodney W. Grimes } 833797f2d22SPoul-Henning Kamp error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 834797f2d22SPoul-Henning Kamp if (error) 835df8bae1dSRodney W. Grimes return (error); 836df8bae1dSRodney W. Grimes buflen -= sizeof(filehead); 837df8bae1dSRodney W. Grimes where += sizeof(filehead); 838df8bae1dSRodney W. Grimes 839df8bae1dSRodney W. Grimes /* 840df8bae1dSRodney W. Grimes * followed by an array of file structures 841df8bae1dSRodney W. Grimes */ 842df8bae1dSRodney W. Grimes for (fp = filehead; fp != NULL; fp = fp->f_filef) { 843df8bae1dSRodney W. Grimes if (buflen < sizeof(struct file)) { 844df8bae1dSRodney W. Grimes *sizep = where - start; 845df8bae1dSRodney W. Grimes return (ENOMEM); 846df8bae1dSRodney W. Grimes } 847797f2d22SPoul-Henning Kamp error = copyout((caddr_t)fp, where, sizeof (struct file)); 848797f2d22SPoul-Henning Kamp if (error) 849df8bae1dSRodney W. Grimes return (error); 850df8bae1dSRodney W. Grimes buflen -= sizeof(struct file); 851df8bae1dSRodney W. Grimes where += sizeof(struct file); 852df8bae1dSRodney W. Grimes } 853df8bae1dSRodney W. Grimes *sizep = where - start; 854df8bae1dSRodney W. Grimes return (0); 855df8bae1dSRodney W. Grimes } 856df8bae1dSRodney W. Grimes 857df8bae1dSRodney W. Grimes /* 858df8bae1dSRodney W. Grimes * try over estimating by 5 procs 859df8bae1dSRodney W. Grimes */ 860df8bae1dSRodney W. Grimes #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 861df8bae1dSRodney W. Grimes 86226f9a767SRodney W. Grimes int 863df8bae1dSRodney W. Grimes sysctl_doproc(name, namelen, where, sizep) 864df8bae1dSRodney W. Grimes int *name; 865df8bae1dSRodney W. Grimes u_int namelen; 866df8bae1dSRodney W. Grimes char *where; 867df8bae1dSRodney W. Grimes size_t *sizep; 868df8bae1dSRodney W. Grimes { 869df8bae1dSRodney W. Grimes register struct proc *p; 870df8bae1dSRodney W. Grimes register struct kinfo_proc *dp = (struct kinfo_proc *)where; 871df8bae1dSRodney W. Grimes register int needed = 0; 872df8bae1dSRodney W. Grimes int buflen = where != NULL ? *sizep : 0; 873df8bae1dSRodney W. Grimes int doingzomb; 874df8bae1dSRodney W. Grimes struct eproc eproc; 875df8bae1dSRodney W. Grimes int error = 0; 876df8bae1dSRodney W. Grimes 877df8bae1dSRodney W. Grimes if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 878df8bae1dSRodney W. Grimes return (EINVAL); 879df8bae1dSRodney W. Grimes p = (struct proc *)allproc; 880df8bae1dSRodney W. Grimes doingzomb = 0; 881df8bae1dSRodney W. Grimes again: 882df8bae1dSRodney W. Grimes for (; p != NULL; p = p->p_next) { 883df8bae1dSRodney W. Grimes /* 884df8bae1dSRodney W. Grimes * Skip embryonic processes. 885df8bae1dSRodney W. Grimes */ 886df8bae1dSRodney W. Grimes if (p->p_stat == SIDL) 887df8bae1dSRodney W. Grimes continue; 888df8bae1dSRodney W. Grimes /* 889df8bae1dSRodney W. Grimes * TODO - make more efficient (see notes below). 890df8bae1dSRodney W. Grimes * do by session. 891df8bae1dSRodney W. Grimes */ 892df8bae1dSRodney W. Grimes switch (name[0]) { 893df8bae1dSRodney W. Grimes 894df8bae1dSRodney W. Grimes case KERN_PROC_PID: 895df8bae1dSRodney W. Grimes /* could do this with just a lookup */ 896df8bae1dSRodney W. Grimes if (p->p_pid != (pid_t)name[1]) 897df8bae1dSRodney W. Grimes continue; 898df8bae1dSRodney W. Grimes break; 899df8bae1dSRodney W. Grimes 900df8bae1dSRodney W. Grimes case KERN_PROC_PGRP: 901df8bae1dSRodney W. Grimes /* could do this by traversing pgrp */ 902be6a1d14SDavid Greenman if (p->p_pgrp == NULL || p->p_pgrp->pg_id != (pid_t)name[1]) 903df8bae1dSRodney W. Grimes continue; 904df8bae1dSRodney W. Grimes break; 905df8bae1dSRodney W. Grimes 906df8bae1dSRodney W. Grimes case KERN_PROC_TTY: 907df8bae1dSRodney W. Grimes if ((p->p_flag & P_CONTROLT) == 0 || 908be6a1d14SDavid Greenman p->p_session == NULL || 909df8bae1dSRodney W. Grimes p->p_session->s_ttyp == NULL || 910df8bae1dSRodney W. Grimes p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 911df8bae1dSRodney W. Grimes continue; 912df8bae1dSRodney W. Grimes break; 913df8bae1dSRodney W. Grimes 914df8bae1dSRodney W. Grimes case KERN_PROC_UID: 915be6a1d14SDavid Greenman if (p->p_ucred == NULL || p->p_ucred->cr_uid != (uid_t)name[1]) 916df8bae1dSRodney W. Grimes continue; 917df8bae1dSRodney W. Grimes break; 918df8bae1dSRodney W. Grimes 919df8bae1dSRodney W. Grimes case KERN_PROC_RUID: 920be6a1d14SDavid Greenman if (p->p_ucred == NULL || p->p_cred->p_ruid != (uid_t)name[1]) 921df8bae1dSRodney W. Grimes continue; 922df8bae1dSRodney W. Grimes break; 923df8bae1dSRodney W. Grimes } 924df8bae1dSRodney W. Grimes if (buflen >= sizeof(struct kinfo_proc)) { 925df8bae1dSRodney W. Grimes fill_eproc(p, &eproc); 926797f2d22SPoul-Henning Kamp error = copyout((caddr_t)p, &dp->kp_proc, 927797f2d22SPoul-Henning Kamp sizeof(struct proc)); 928797f2d22SPoul-Henning Kamp if (error) 929df8bae1dSRodney W. Grimes return (error); 930797f2d22SPoul-Henning Kamp error = copyout((caddr_t)&eproc, &dp->kp_eproc, 931797f2d22SPoul-Henning Kamp sizeof(eproc)); 932797f2d22SPoul-Henning Kamp if (error) 933df8bae1dSRodney W. Grimes return (error); 934df8bae1dSRodney W. Grimes dp++; 935df8bae1dSRodney W. Grimes buflen -= sizeof(struct kinfo_proc); 936df8bae1dSRodney W. Grimes } 937df8bae1dSRodney W. Grimes needed += sizeof(struct kinfo_proc); 938df8bae1dSRodney W. Grimes } 939df8bae1dSRodney W. Grimes if (doingzomb == 0) { 940df8bae1dSRodney W. Grimes p = zombproc; 941df8bae1dSRodney W. Grimes doingzomb++; 942df8bae1dSRodney W. Grimes goto again; 943df8bae1dSRodney W. Grimes } 944df8bae1dSRodney W. Grimes if (where != NULL) { 945df8bae1dSRodney W. Grimes *sizep = (caddr_t)dp - where; 946df8bae1dSRodney W. Grimes if (needed > *sizep) 947df8bae1dSRodney W. Grimes return (ENOMEM); 948df8bae1dSRodney W. Grimes } else { 949df8bae1dSRodney W. Grimes needed += KERN_PROCSLOP; 950df8bae1dSRodney W. Grimes *sizep = needed; 951df8bae1dSRodney W. Grimes } 952df8bae1dSRodney W. Grimes return (0); 953df8bae1dSRodney W. Grimes } 954df8bae1dSRodney W. Grimes 955df8bae1dSRodney W. Grimes /* 956df8bae1dSRodney W. Grimes * Fill in an eproc structure for the specified process. 957df8bae1dSRodney W. Grimes */ 958df8bae1dSRodney W. Grimes void 959df8bae1dSRodney W. Grimes fill_eproc(p, ep) 960df8bae1dSRodney W. Grimes register struct proc *p; 961df8bae1dSRodney W. Grimes register struct eproc *ep; 962df8bae1dSRodney W. Grimes { 963df8bae1dSRodney W. Grimes register struct tty *tp; 964df8bae1dSRodney W. Grimes 965be6a1d14SDavid Greenman bzero(ep, sizeof(*ep)); 966be6a1d14SDavid Greenman 967df8bae1dSRodney W. Grimes ep->e_paddr = p; 9681c8fc26cSDavid Greenman if (p->p_cred) { 969df8bae1dSRodney W. Grimes ep->e_pcred = *p->p_cred; 970be6a1d14SDavid Greenman if (p->p_ucred) 971df8bae1dSRodney W. Grimes ep->e_ucred = *p->p_ucred; 9721c8fc26cSDavid Greenman } 9731c8fc26cSDavid Greenman if (p->p_stat != SIDL && p->p_stat != SZOMB && p->p_vmspace != NULL) { 974df8bae1dSRodney W. Grimes register struct vmspace *vm = p->p_vmspace; 975df8bae1dSRodney W. Grimes 976df8bae1dSRodney W. Grimes #ifdef pmap_resident_count 977df8bae1dSRodney W. Grimes ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/ 978df8bae1dSRodney W. Grimes #else 979df8bae1dSRodney W. Grimes ep->e_vm.vm_rssize = vm->vm_rssize; 980df8bae1dSRodney W. Grimes #endif 981df8bae1dSRodney W. Grimes ep->e_vm.vm_tsize = vm->vm_tsize; 982df8bae1dSRodney W. Grimes ep->e_vm.vm_dsize = vm->vm_dsize; 983df8bae1dSRodney W. Grimes ep->e_vm.vm_ssize = vm->vm_ssize; 984df8bae1dSRodney W. Grimes #ifndef sparc 985df8bae1dSRodney W. Grimes ep->e_vm.vm_pmap = vm->vm_pmap; 986df8bae1dSRodney W. Grimes #endif 987df8bae1dSRodney W. Grimes } 988df8bae1dSRodney W. Grimes if (p->p_pptr) 989df8bae1dSRodney W. Grimes ep->e_ppid = p->p_pptr->p_pid; 990be6a1d14SDavid Greenman if (p->p_pgrp) { 991be6a1d14SDavid Greenman ep->e_sess = p->p_pgrp->pg_session; 992df8bae1dSRodney W. Grimes ep->e_pgid = p->p_pgrp->pg_id; 993df8bae1dSRodney W. Grimes ep->e_jobc = p->p_pgrp->pg_jobc; 994be6a1d14SDavid Greenman } 995df8bae1dSRodney W. Grimes if ((p->p_flag & P_CONTROLT) && 996be6a1d14SDavid Greenman (ep->e_sess != NULL) && 997be6a1d14SDavid Greenman ((tp = ep->e_sess->s_ttyp) != NULL)) { 998df8bae1dSRodney W. Grimes ep->e_tdev = tp->t_dev; 999df8bae1dSRodney W. Grimes ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1000df8bae1dSRodney W. Grimes ep->e_tsess = tp->t_session; 1001df8bae1dSRodney W. Grimes } else 1002df8bae1dSRodney W. Grimes ep->e_tdev = NODEV; 1003be6a1d14SDavid Greenman if (ep->e_sess && ep->e_sess->s_ttyvp) 1004be6a1d14SDavid Greenman ep->e_flag = EPROC_CTTY; 1005df8bae1dSRodney W. Grimes if (SESS_LEADER(p)) 1006df8bae1dSRodney W. Grimes ep->e_flag |= EPROC_SLEADER; 1007be6a1d14SDavid Greenman if (p->p_wmesg) { 1008df8bae1dSRodney W. Grimes strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 1009be6a1d14SDavid Greenman ep->e_wmesg[WMESGLEN] = 0; 1010be6a1d14SDavid Greenman } 1011df8bae1dSRodney W. Grimes } 1012df8bae1dSRodney W. Grimes 1013df8bae1dSRodney W. Grimes #ifdef COMPAT_43 1014df8bae1dSRodney W. Grimes #include <sys/socket.h> 1015df8bae1dSRodney W. Grimes #define KINFO_PROC (0<<8) 1016df8bae1dSRodney W. Grimes #define KINFO_RT (1<<8) 1017df8bae1dSRodney W. Grimes #define KINFO_VNODE (2<<8) 1018df8bae1dSRodney W. Grimes #define KINFO_FILE (3<<8) 1019df8bae1dSRodney W. Grimes #define KINFO_METER (4<<8) 1020df8bae1dSRodney W. Grimes #define KINFO_LOADAVG (5<<8) 1021df8bae1dSRodney W. Grimes #define KINFO_CLOCKRATE (6<<8) 1022df8bae1dSRodney W. Grimes 10236ece4a51SPeter Wemm /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ 10246ece4a51SPeter Wemm #define KINFO_BSDI_SYSINFO (101<<8) 10256ece4a51SPeter Wemm 10266ece4a51SPeter Wemm /* 10276ece4a51SPeter Wemm * XXX this is bloat, but I hope it's better here than on the potentially 10286ece4a51SPeter Wemm * limited kernel stack... -Peter 10296ece4a51SPeter Wemm */ 10306ece4a51SPeter Wemm 10316ece4a51SPeter Wemm struct { 10326ece4a51SPeter Wemm int bsdi_machine; /* "i386" on BSD/386 */ 10336ece4a51SPeter Wemm /* ^^^ this is an offset to the string, relative to the struct start */ 10346ece4a51SPeter Wemm char *pad0; 10356ece4a51SPeter Wemm long pad1; 10366ece4a51SPeter Wemm long pad2; 10376ece4a51SPeter Wemm long pad3; 10386ece4a51SPeter Wemm u_long pad4; 10396ece4a51SPeter Wemm u_long pad5; 10406ece4a51SPeter Wemm u_long pad6; 10416ece4a51SPeter Wemm 10426ece4a51SPeter Wemm int bsdi_ostype; /* "BSD/386" on BSD/386 */ 10436ece4a51SPeter Wemm int bsdi_osrelease; /* "1.1" on BSD/386 */ 10446ece4a51SPeter Wemm long pad7; 10456ece4a51SPeter Wemm long pad8; 10466ece4a51SPeter Wemm char *pad9; 10476ece4a51SPeter Wemm 10486ece4a51SPeter Wemm long pad10; 10496ece4a51SPeter Wemm long pad11; 10506ece4a51SPeter Wemm int pad12; 10516ece4a51SPeter Wemm long pad13; 10526ece4a51SPeter Wemm quad_t pad14; 10536ece4a51SPeter Wemm long pad15; 10546ece4a51SPeter Wemm 10556ece4a51SPeter Wemm struct timeval pad16; 10566ece4a51SPeter Wemm /* we dont set this, because BSDI's uname used gethostname() instead */ 10576ece4a51SPeter Wemm int bsdi_hostname; /* hostname on BSD/386 */ 10586ece4a51SPeter Wemm 10596ece4a51SPeter Wemm /* the actual string data is appended here */ 10606ece4a51SPeter Wemm 10616ece4a51SPeter Wemm } bsdi_si; 10626ece4a51SPeter Wemm /* 10636ece4a51SPeter Wemm * this data is appended to the end of the bsdi_si structure during copyout. 10646ece4a51SPeter Wemm * The "char *" offsets are relative to the base of the bsdi_si struct. 10656ece4a51SPeter Wemm * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings 10666ece4a51SPeter Wemm * should not exceed the length of the buffer here... (or else!! :-) 10676ece4a51SPeter Wemm */ 10686ece4a51SPeter Wemm char bsdi_strings[80]; /* It had better be less than this! */ 10696ece4a51SPeter Wemm 1070df8bae1dSRodney W. Grimes struct getkerninfo_args { 1071df8bae1dSRodney W. Grimes int op; 1072df8bae1dSRodney W. Grimes char *where; 1073df8bae1dSRodney W. Grimes int *size; 1074df8bae1dSRodney W. Grimes int arg; 1075df8bae1dSRodney W. Grimes }; 1076df8bae1dSRodney W. Grimes 107726f9a767SRodney W. Grimes int 1078df8bae1dSRodney W. Grimes ogetkerninfo(p, uap, retval) 1079df8bae1dSRodney W. Grimes struct proc *p; 1080df8bae1dSRodney W. Grimes register struct getkerninfo_args *uap; 1081df8bae1dSRodney W. Grimes int *retval; 1082df8bae1dSRodney W. Grimes { 1083df8bae1dSRodney W. Grimes int error, name[5]; 1084df8bae1dSRodney W. Grimes u_int size; 1085df8bae1dSRodney W. Grimes 1086df8bae1dSRodney W. Grimes if (uap->size && 1087df8bae1dSRodney W. Grimes (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) 1088df8bae1dSRodney W. Grimes return (error); 1089df8bae1dSRodney W. Grimes 1090df8bae1dSRodney W. Grimes switch (uap->op & 0xff00) { 1091df8bae1dSRodney W. Grimes 1092df8bae1dSRodney W. Grimes case KINFO_RT: 1093df8bae1dSRodney W. Grimes name[0] = PF_ROUTE; 1094df8bae1dSRodney W. Grimes name[1] = 0; 1095df8bae1dSRodney W. Grimes name[2] = (uap->op & 0xff0000) >> 16; 1096df8bae1dSRodney W. Grimes name[3] = uap->op & 0xff; 1097df8bae1dSRodney W. Grimes name[4] = uap->arg; 1098df8bae1dSRodney W. Grimes error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); 1099df8bae1dSRodney W. Grimes break; 1100df8bae1dSRodney W. Grimes 1101df8bae1dSRodney W. Grimes case KINFO_VNODE: 1102df8bae1dSRodney W. Grimes name[0] = KERN_VNODE; 1103df8bae1dSRodney W. Grimes error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 1104df8bae1dSRodney W. Grimes break; 1105df8bae1dSRodney W. Grimes 1106df8bae1dSRodney W. Grimes case KINFO_PROC: 1107df8bae1dSRodney W. Grimes name[0] = KERN_PROC; 1108df8bae1dSRodney W. Grimes name[1] = uap->op & 0xff; 1109df8bae1dSRodney W. Grimes name[2] = uap->arg; 1110df8bae1dSRodney W. Grimes error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); 1111df8bae1dSRodney W. Grimes break; 1112df8bae1dSRodney W. Grimes 1113df8bae1dSRodney W. Grimes case KINFO_FILE: 1114df8bae1dSRodney W. Grimes name[0] = KERN_FILE; 1115df8bae1dSRodney W. Grimes error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 1116df8bae1dSRodney W. Grimes break; 1117df8bae1dSRodney W. Grimes 1118df8bae1dSRodney W. Grimes case KINFO_METER: 1119df8bae1dSRodney W. Grimes name[0] = VM_METER; 1120df8bae1dSRodney W. Grimes error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 1121df8bae1dSRodney W. Grimes break; 1122df8bae1dSRodney W. Grimes 1123df8bae1dSRodney W. Grimes case KINFO_LOADAVG: 1124df8bae1dSRodney W. Grimes name[0] = VM_LOADAVG; 1125df8bae1dSRodney W. Grimes error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 1126df8bae1dSRodney W. Grimes break; 1127df8bae1dSRodney W. Grimes 1128df8bae1dSRodney W. Grimes case KINFO_CLOCKRATE: 1129df8bae1dSRodney W. Grimes name[0] = KERN_CLOCKRATE; 1130df8bae1dSRodney W. Grimes error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 1131df8bae1dSRodney W. Grimes break; 1132df8bae1dSRodney W. Grimes 11336ece4a51SPeter Wemm case KINFO_BSDI_SYSINFO: { 11346ece4a51SPeter Wemm /* 11356ece4a51SPeter Wemm * this is pretty crude, but it's just enough for uname() 11366ece4a51SPeter Wemm * from BSDI's 1.x libc to work. 11376ece4a51SPeter Wemm * 11386ece4a51SPeter Wemm * In particular, it doesn't return the same results when 11396ece4a51SPeter Wemm * the supplied buffer is too small. BSDI's version apparently 11406ece4a51SPeter Wemm * will return the amount copied, and set the *size to how 11416ece4a51SPeter Wemm * much was needed. The emulation framework here isn't capable 11426ece4a51SPeter Wemm * of that, so we just set both to the amount copied. 11436ece4a51SPeter Wemm * BSDI's 2.x product apparently fails with ENOMEM in this 11446ece4a51SPeter Wemm * scenario. 11456ece4a51SPeter Wemm */ 11466ece4a51SPeter Wemm 11476ece4a51SPeter Wemm u_int needed; 11486ece4a51SPeter Wemm u_int left; 11496ece4a51SPeter Wemm char *s; 11506ece4a51SPeter Wemm 11516ece4a51SPeter Wemm bzero((char *)&bsdi_si, sizeof(bsdi_si)); 11526ece4a51SPeter Wemm bzero(bsdi_strings, sizeof(bsdi_strings)); 11536ece4a51SPeter Wemm 11546ece4a51SPeter Wemm s = bsdi_strings; 11556ece4a51SPeter Wemm 11566ece4a51SPeter Wemm bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); 11576ece4a51SPeter Wemm strcpy(s, ostype); 11586ece4a51SPeter Wemm s += strlen(s) + 1; 11596ece4a51SPeter Wemm 11606ece4a51SPeter Wemm bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); 11616ece4a51SPeter Wemm strcpy(s, osrelease); 11626ece4a51SPeter Wemm s += strlen(s) + 1; 11636ece4a51SPeter Wemm 11646ece4a51SPeter Wemm bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); 11656ece4a51SPeter Wemm strcpy(s, machine); 11666ece4a51SPeter Wemm s += strlen(s) + 1; 11676ece4a51SPeter Wemm 11686ece4a51SPeter Wemm needed = sizeof(bsdi_si) + (s - bsdi_strings); 11696ece4a51SPeter Wemm 11706ece4a51SPeter Wemm if (uap->where == NULL) { 11716ece4a51SPeter Wemm /* process is asking how much buffer to supply.. */ 11726ece4a51SPeter Wemm size = needed; 11736ece4a51SPeter Wemm error = 0; 11746ece4a51SPeter Wemm break; 11756ece4a51SPeter Wemm } 11766ece4a51SPeter Wemm 11776ece4a51SPeter Wemm 11786ece4a51SPeter Wemm /* if too much buffer supplied, trim it down */ 11796ece4a51SPeter Wemm if (size > needed) 11806ece4a51SPeter Wemm size = needed; 11816ece4a51SPeter Wemm 11826ece4a51SPeter Wemm /* how much of the buffer is remaining */ 11836ece4a51SPeter Wemm left = size; 11846ece4a51SPeter Wemm 11856ece4a51SPeter Wemm if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) 11866ece4a51SPeter Wemm break; 11876ece4a51SPeter Wemm 11886ece4a51SPeter Wemm /* is there any point in continuing? */ 11896ece4a51SPeter Wemm if (left > sizeof(bsdi_si)) { 11906ece4a51SPeter Wemm left -= sizeof(bsdi_si); 11916ece4a51SPeter Wemm error = copyout(&bsdi_strings, 11926ece4a51SPeter Wemm uap->where + sizeof(bsdi_si), left); 11936ece4a51SPeter Wemm } 11946ece4a51SPeter Wemm break; 11956ece4a51SPeter Wemm } 11966ece4a51SPeter Wemm 1197df8bae1dSRodney W. Grimes default: 1198df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 1199df8bae1dSRodney W. Grimes } 1200df8bae1dSRodney W. Grimes if (error) 1201df8bae1dSRodney W. Grimes return (error); 1202df8bae1dSRodney W. Grimes *retval = size; 1203df8bae1dSRodney W. Grimes if (uap->size) 1204df8bae1dSRodney W. Grimes error = copyout((caddr_t)&size, (caddr_t)uap->size, 1205df8bae1dSRodney W. Grimes sizeof(size)); 1206df8bae1dSRodney W. Grimes return (error); 1207df8bae1dSRodney W. Grimes } 1208df8bae1dSRodney W. Grimes #endif /* COMPAT_43 */ 1209