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 * 8946bb7a2SPoul-Henning Kamp * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD 9946bb7a2SPoul-Henning Kamp * project, to make these variables more userfriendly. 10946bb7a2SPoul-Henning Kamp * 11df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 12df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 13df8bae1dSRodney W. Grimes * are met: 14df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 15df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 16df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 17df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 18df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 19df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 20df8bae1dSRodney W. Grimes * must display the following acknowledgement: 21df8bae1dSRodney W. Grimes * This product includes software developed by the University of 22df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 23df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 24df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 25df8bae1dSRodney W. Grimes * without specific prior written permission. 26df8bae1dSRodney W. Grimes * 27df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37df8bae1dSRodney W. Grimes * SUCH DAMAGE. 38df8bae1dSRodney W. Grimes * 39df8bae1dSRodney W. Grimes * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 403ac9f819SPoul-Henning Kamp * $Id: kern_sysctl.c,v 1.57 1995/12/14 08:31:36 phk Exp $ 41df8bae1dSRodney W. Grimes */ 42df8bae1dSRodney W. Grimes 43df8bae1dSRodney W. Grimes #include <sys/param.h> 44df8bae1dSRodney W. Grimes #include <sys/systm.h> 45d2d3e875SBruce Evans #include <sys/sysproto.h> 46df8bae1dSRodney W. Grimes #include <sys/kernel.h> 47df8bae1dSRodney W. Grimes #include <sys/vnode.h> 48df8bae1dSRodney W. Grimes #include <sys/unistd.h> 495bb4f738SGarrett Wollman #include <sys/conf.h> 50df8bae1dSRodney W. Grimes #include <sys/sysctl.h> 51946bb7a2SPoul-Henning Kamp #include <sys/malloc.h> 52efeaf95aSDavid Greenman #include <sys/proc.h> 53df8bae1dSRodney W. Grimes 544cb03b1bSBruce Evans #include <vm/vm.h> 55efeaf95aSDavid Greenman #include <vm/vm_param.h> 56efeaf95aSDavid Greenman #include <vm/vm_extern.h> 574cb03b1bSBruce Evans 584b2af45fSPoul-Henning Kamp /* 594b2af45fSPoul-Henning Kamp * Locking and stats 604b2af45fSPoul-Henning Kamp */ 614b2af45fSPoul-Henning Kamp static struct sysctl_lock { 624b2af45fSPoul-Henning Kamp int sl_lock; 634b2af45fSPoul-Henning Kamp int sl_want; 644b2af45fSPoul-Henning Kamp int sl_locked; 654b2af45fSPoul-Henning Kamp } memlock; 664b2af45fSPoul-Henning Kamp 674b2af45fSPoul-Henning Kamp static int sysctl_root SYSCTL_HANDLER_ARGS; 684b2af45fSPoul-Henning Kamp 69787d58f2SPoul-Henning Kamp extern struct linker_set sysctl_; 70787d58f2SPoul-Henning Kamp 71946bb7a2SPoul-Henning Kamp /* 72946bb7a2SPoul-Henning Kamp * MIB definitions. XXX Very few of these, if any, belong here. 73946bb7a2SPoul-Henning Kamp */ 74787d58f2SPoul-Henning Kamp SYSCTL_NODE(, 0, sysctl, CTLFLAG_RW, 0, 75787d58f2SPoul-Henning Kamp "Sysctl internal magic"); 762e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_KERN, kern, CTLFLAG_RW, 0, 772e210993SPoul-Henning Kamp "High kernel, proc, limits &c"); 782e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_VM, vm, CTLFLAG_RW, 0, 792e210993SPoul-Henning Kamp "Virtual memory"); 802e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_FS, fs, CTLFLAG_RW, 0, 812e210993SPoul-Henning Kamp "File system"); 822e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_NET, net, CTLFLAG_RW, 0, 832e210993SPoul-Henning Kamp "Network, (see socket.h)"); 842e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_DEBUG, debug, CTLFLAG_RW, 0, 852e210993SPoul-Henning Kamp "Debugging"); 862e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_HW, hw, CTLFLAG_RW, 0, 872e210993SPoul-Henning Kamp "hardware"); 882e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_MACHDEP, machdep, CTLFLAG_RW, 0, 892e210993SPoul-Henning Kamp "machine dependent"); 902e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW, 0, 912e210993SPoul-Henning Kamp "user-level"); 92b396cd83SPoul-Henning Kamp 932e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD, osrelease, 0, ""); 94b396cd83SPoul-Henning Kamp 952e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD, 0, BSD, ""); 96b396cd83SPoul-Henning Kamp 972e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD, version, 0, ""); 98b396cd83SPoul-Henning Kamp 992e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD, ostype, 0, ""); 100b396cd83SPoul-Henning Kamp 101b396cd83SPoul-Henning Kamp extern int osreldate; 1022e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD, &osreldate, 0, ""); 103b396cd83SPoul-Henning Kamp 1042e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXPROC, maxproc, CTLFLAG_RD, &maxproc, 0, ""); 105b396cd83SPoul-Henning Kamp 106b396cd83SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXPROCPERUID, maxprocperuid, 1073a34a5c3SPoul-Henning Kamp CTLFLAG_RD, &maxprocperuid, 0, ""); 108b396cd83SPoul-Henning Kamp 1092e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_ARGMAX, argmax, CTLFLAG_RD, 0, ARG_MAX, ""); 110b396cd83SPoul-Henning Kamp 1112e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD, 0, _POSIX_VERSION, ""); 112b396cd83SPoul-Henning Kamp 1132e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RD, 0, NGROUPS_MAX, ""); 114b396cd83SPoul-Henning Kamp 1152e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control, CTLFLAG_RD, 0, 1, ""); 116b396cd83SPoul-Henning Kamp 117b396cd83SPoul-Henning Kamp #ifdef _POSIX_SAVED_IDS 1182e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 1, ""); 119b396cd83SPoul-Henning Kamp #else 1202e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 0, ""); 121b396cd83SPoul-Henning Kamp #endif 122b396cd83SPoul-Henning Kamp 123b396cd83SPoul-Henning Kamp char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */ 124b396cd83SPoul-Henning Kamp 125b396cd83SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, 1263a34a5c3SPoul-Henning Kamp CTLFLAG_RW, kernelname, sizeof kernelname, ""); 127b396cd83SPoul-Henning Kamp 1282e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD, 0, 1, ""); 129b396cd83SPoul-Henning Kamp 1302e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD, 0, BYTE_ORDER, ""); 131b396cd83SPoul-Henning Kamp 1322e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_PAGESIZE, pagesize, CTLFLAG_RD, 0, PAGE_SIZE, ""); 133b396cd83SPoul-Henning Kamp 1342e210993SPoul-Henning Kamp char hostname[MAXHOSTNAMELEN]; 1352e210993SPoul-Henning Kamp 1369565c0e6SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_HOSTNAME, hostname, CTLFLAG_RW, 1379565c0e6SPoul-Henning Kamp hostname, sizeof(hostname), ""); 1382e210993SPoul-Henning Kamp 1394b2af45fSPoul-Henning Kamp int securelevel = -1; 1404b2af45fSPoul-Henning Kamp 1414b2af45fSPoul-Henning Kamp static int 1424b2af45fSPoul-Henning Kamp sysctl_kern_securelvl SYSCTL_HANDLER_ARGS 1434b2af45fSPoul-Henning Kamp { 1444b2af45fSPoul-Henning Kamp int error, level; 1454b2af45fSPoul-Henning Kamp 1464b2af45fSPoul-Henning Kamp level = securelevel; 1474b2af45fSPoul-Henning Kamp error = sysctl_handle_int(oidp, &level, 0, req); 1484b2af45fSPoul-Henning Kamp if (error || !req->newptr) 1494b2af45fSPoul-Henning Kamp return (error); 1504b2af45fSPoul-Henning Kamp if (level < securelevel && req->p->p_pid != 1) 1514b2af45fSPoul-Henning Kamp return (EPERM); 1524b2af45fSPoul-Henning Kamp securelevel = level; 1534b2af45fSPoul-Henning Kamp return (error); 1544b2af45fSPoul-Henning Kamp } 1554b2af45fSPoul-Henning Kamp 1564b2af45fSPoul-Henning Kamp SYSCTL_PROC(_kern, KERN_SECURELVL, securelevel, CTLTYPE_INT|CTLFLAG_RW, 157946bb7a2SPoul-Henning Kamp 0, 0, sysctl_kern_securelvl, "I", ""); 1584b2af45fSPoul-Henning Kamp 159946bb7a2SPoul-Henning Kamp char domainname[MAXHOSTNAMELEN]; 160946bb7a2SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_DOMAINNAME, domainname, CTLFLAG_RW, 161946bb7a2SPoul-Henning Kamp &domainname, sizeof(domainname), ""); 1624b2af45fSPoul-Henning Kamp 163946bb7a2SPoul-Henning Kamp long hostid; 164946bb7a2SPoul-Henning Kamp /* Some trouble here, if sizeof (int) != sizeof (long) */ 165946bb7a2SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_HOSTID, hostid, CTLFLAG_RW, &hostid, 0, ""); 1664b2af45fSPoul-Henning Kamp 167946bb7a2SPoul-Henning Kamp /* 16865d0bc13SPoul-Henning Kamp * This is really cheating. These actually live in the libc, something 16965d0bc13SPoul-Henning Kamp * which I'm not quite sure is a good idea anyway, but in order for 17065d0bc13SPoul-Henning Kamp * getnext and friends to actually work, we define dummies here. 17165d0bc13SPoul-Henning Kamp */ 17265d0bc13SPoul-Henning Kamp 17365d0bc13SPoul-Henning Kamp SYSCTL_STRING(_user, USER_CS_PATH, cs_path, CTLFLAG_RW, "", 0, ""); 17465d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_BC_BASE_MAX, bc_base_max, CTLFLAG_RW, 0, 0, ""); 17565d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_BC_DIM_MAX, bc_dim_max, CTLFLAG_RW, 0, 0, ""); 17665d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_BC_SCALE_MAX, bc_scale_max, CTLFLAG_RW, 0, 0, ""); 17765d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_BC_STRING_MAX, bc_string_max, CTLFLAG_RW, 0, 0, ""); 17865d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_COLL_WEIGHTS_MAX, coll_weights_max, CTLFLAG_RW, 0, 0, ""); 17965d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_EXPR_NEST_MAX, expr_nest_max, CTLFLAG_RW, 0, 0, ""); 18065d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_LINE_MAX, line_max, CTLFLAG_RW, 0, 0, ""); 18165d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_RE_DUP_MAX, re_dup_max, CTLFLAG_RW, 0, 0, ""); 18265d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_POSIX2_VERSION, posix2_version, CTLFLAG_RW, 0, 0, ""); 18365d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_POSIX2_C_BIND, posix2_c_bind, CTLFLAG_RW, 0, 0, ""); 18465d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_POSIX2_C_DEV, posix2_c_dev, CTLFLAG_RW, 0, 0, ""); 18565d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_POSIX2_CHAR_TERM, posix2_char_term, CTLFLAG_RW, 0, 0, ""); 18665d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_POSIX2_FORT_DEV, posix2_fort_dev, CTLFLAG_RW, 0, 0, ""); 18765d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_POSIX2_FORT_RUN, posix2_fort_run, CTLFLAG_RW, 0, 0, ""); 18865d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_POSIX2_LOCALEDEF, posix2_localedef, CTLFLAG_RW, 0, 0, ""); 18965d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_POSIX2_SW_DEV, posix2_sw_dev, CTLFLAG_RW, 0, 0, ""); 19065d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_POSIX2_UPE, posix2_upe, CTLFLAG_RW, 0, 0, ""); 19165d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_STREAM_MAX, stream_max, CTLFLAG_RW, 0, 0, ""); 19265d0bc13SPoul-Henning Kamp SYSCTL_INT(_user, USER_TZNAME_MAX, tzname_max, CTLFLAG_RW, 0, 0, ""); 19365d0bc13SPoul-Henning Kamp 19465d0bc13SPoul-Henning Kamp 19565d0bc13SPoul-Henning Kamp /* 196946bb7a2SPoul-Henning Kamp * End of MIB definitions. 197946bb7a2SPoul-Henning Kamp */ 1984b2af45fSPoul-Henning Kamp 199946bb7a2SPoul-Henning Kamp /* 200946bb7a2SPoul-Henning Kamp * Initialization of the MIB tree. 201946bb7a2SPoul-Henning Kamp * 202946bb7a2SPoul-Henning Kamp * Order by number in each linker_set. 203946bb7a2SPoul-Henning Kamp */ 2044b2af45fSPoul-Henning Kamp 205787d58f2SPoul-Henning Kamp static int 2063c8e79ddSBruce Evans sysctl_order_cmp(const void *a, const void *b) 207787d58f2SPoul-Henning Kamp { 2083c8e79ddSBruce Evans const struct sysctl_oid **pa, **pb; 2093c8e79ddSBruce Evans 2103c8e79ddSBruce Evans pa = (const struct sysctl_oid **)a; 2113c8e79ddSBruce Evans pb = (const struct sysctl_oid **)b; 2123c8e79ddSBruce Evans if (*pa == NULL) 2133c8e79ddSBruce Evans return (1); 2143c8e79ddSBruce Evans if (*pb == NULL) 2153c8e79ddSBruce Evans return (-1); 216787d58f2SPoul-Henning Kamp return ((*pa)->oid_number - (*pb)->oid_number); 217787d58f2SPoul-Henning Kamp } 218787d58f2SPoul-Henning Kamp 219787d58f2SPoul-Henning Kamp static void 220787d58f2SPoul-Henning Kamp sysctl_order(void *arg) 221787d58f2SPoul-Henning Kamp { 222946bb7a2SPoul-Henning Kamp int j, k; 223787d58f2SPoul-Henning Kamp struct linker_set *l = (struct linker_set *) arg; 224787d58f2SPoul-Henning Kamp struct sysctl_oid **oidpp; 225787d58f2SPoul-Henning Kamp 226946bb7a2SPoul-Henning Kamp /* First, find the highest oid we have */ 227946bb7a2SPoul-Henning Kamp j = l->ls_length; 228946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 229946bb7a2SPoul-Henning Kamp for (k = 0; j--; oidpp++) 230946bb7a2SPoul-Henning Kamp if (*oidpp && (*oidpp)->oid_number > k) 231946bb7a2SPoul-Henning Kamp k = (*oidpp)->oid_number; 232946bb7a2SPoul-Henning Kamp 233946bb7a2SPoul-Henning Kamp /* Next, replace all OID_AUTO oids with new numbers */ 234946bb7a2SPoul-Henning Kamp j = l->ls_length; 235946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 236946bb7a2SPoul-Henning Kamp k += 100; 237946bb7a2SPoul-Henning Kamp for (; j--; oidpp++) 238946bb7a2SPoul-Henning Kamp if (*oidpp && (*oidpp)->oid_number == OID_AUTO) 239946bb7a2SPoul-Henning Kamp (*oidpp)->oid_number = k++; 240946bb7a2SPoul-Henning Kamp 241946bb7a2SPoul-Henning Kamp /* Finally: sort by oid */ 242787d58f2SPoul-Henning Kamp j = l->ls_length; 243787d58f2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 244787d58f2SPoul-Henning Kamp for (; j--; oidpp++) { 245787d58f2SPoul-Henning Kamp if (!*oidpp) 246787d58f2SPoul-Henning Kamp continue; 247787d58f2SPoul-Henning Kamp if ((*oidpp)->oid_arg1 == arg) { 248787d58f2SPoul-Henning Kamp *oidpp = 0; 249787d58f2SPoul-Henning Kamp continue; 250787d58f2SPoul-Henning Kamp } 251787d58f2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) 252787d58f2SPoul-Henning Kamp if (!(*oidpp)->oid_handler) 253787d58f2SPoul-Henning Kamp sysctl_order((*oidpp)->oid_arg1); 254787d58f2SPoul-Henning Kamp } 255787d58f2SPoul-Henning Kamp qsort(l->ls_items, l->ls_length, sizeof l->ls_items[0], 256787d58f2SPoul-Henning Kamp sysctl_order_cmp); 257787d58f2SPoul-Henning Kamp } 258787d58f2SPoul-Henning Kamp 259787d58f2SPoul-Henning Kamp SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_order, &sysctl_); 260787d58f2SPoul-Henning Kamp 261946bb7a2SPoul-Henning Kamp /* 262946bb7a2SPoul-Henning Kamp * "Staff-functions" 263946bb7a2SPoul-Henning Kamp * 26465d0bc13SPoul-Henning Kamp * These functions implement a presently undocumented interface 26565d0bc13SPoul-Henning Kamp * used by the sysctl program to walk the tree, and get the type 26665d0bc13SPoul-Henning Kamp * so it can print the value. 26765d0bc13SPoul-Henning Kamp * This interface is under work and consideration, and should probably 26865d0bc13SPoul-Henning Kamp * be killed with a big axe by the first person who can find the time. 26965d0bc13SPoul-Henning Kamp * (be aware though, that the proper interface isn't as obvious as it 27065d0bc13SPoul-Henning Kamp * may seem, there are various conflicting requirements. 27165d0bc13SPoul-Henning Kamp * 272946bb7a2SPoul-Henning Kamp * {0,0} printf the entire MIB-tree. 273946bb7a2SPoul-Henning Kamp * {0,1,...} return the name of the "..." OID. 274946bb7a2SPoul-Henning Kamp * {0,2,...} return the next OID. 275946bb7a2SPoul-Henning Kamp * {0,3} return the OID of the name in "new" 27665d0bc13SPoul-Henning Kamp * {0,4,...} return the kind & format info for the "..." OID. 277946bb7a2SPoul-Henning Kamp */ 278946bb7a2SPoul-Henning Kamp 279787d58f2SPoul-Henning Kamp static void 280787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node(struct linker_set *l, int i) 281787d58f2SPoul-Henning Kamp { 282787d58f2SPoul-Henning Kamp int j, k; 283787d58f2SPoul-Henning Kamp struct sysctl_oid **oidpp; 284787d58f2SPoul-Henning Kamp 285787d58f2SPoul-Henning Kamp j = l->ls_length; 286787d58f2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 287787d58f2SPoul-Henning Kamp for (; j--; oidpp++) { 288787d58f2SPoul-Henning Kamp 289787d58f2SPoul-Henning Kamp if (!*oidpp) 290787d58f2SPoul-Henning Kamp continue; 291787d58f2SPoul-Henning Kamp 292787d58f2SPoul-Henning Kamp for (k=0; k<i; k++) 293787d58f2SPoul-Henning Kamp printf(" "); 294787d58f2SPoul-Henning Kamp 295787d58f2SPoul-Henning Kamp if ((*oidpp)->oid_number > 100) { 296b8da2396SPoul-Henning Kamp printf("Junk! %p # %d %s k %x a1 %p a2 %x h %p\n", 297787d58f2SPoul-Henning Kamp *oidpp, 298787d58f2SPoul-Henning Kamp (*oidpp)->oid_number, (*oidpp)->oid_name, 299787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind, (*oidpp)->oid_arg1, 300787d58f2SPoul-Henning Kamp (*oidpp)->oid_arg2, (*oidpp)->oid_handler); 301787d58f2SPoul-Henning Kamp continue; 302787d58f2SPoul-Henning Kamp } 303787d58f2SPoul-Henning Kamp printf("%d %s ", (*oidpp)->oid_number, (*oidpp)->oid_name); 304787d58f2SPoul-Henning Kamp 305787d58f2SPoul-Henning Kamp printf("%c%c", 306787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind & CTLFLAG_RD ? 'R':' ', 307787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind & CTLFLAG_WR ? 'W':' '); 308787d58f2SPoul-Henning Kamp 309787d58f2SPoul-Henning Kamp switch ((*oidpp)->oid_kind & CTLTYPE) { 310787d58f2SPoul-Henning Kamp case CTLTYPE_NODE: 311787d58f2SPoul-Henning Kamp if ((*oidpp)->oid_handler) { 312787d58f2SPoul-Henning Kamp printf(" Node(proc)\n"); 313787d58f2SPoul-Henning Kamp } else { 314787d58f2SPoul-Henning Kamp printf(" Node\n"); 315787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node( 316787d58f2SPoul-Henning Kamp (*oidpp)->oid_arg1, i+2); 317787d58f2SPoul-Henning Kamp } 318787d58f2SPoul-Henning Kamp break; 319787d58f2SPoul-Henning Kamp case CTLTYPE_INT: printf(" Int\n"); break; 320787d58f2SPoul-Henning Kamp case CTLTYPE_STRING: printf(" String\n"); break; 321787d58f2SPoul-Henning Kamp case CTLTYPE_QUAD: printf(" Quad\n"); break; 322787d58f2SPoul-Henning Kamp case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break; 323787d58f2SPoul-Henning Kamp default: printf("\n"); 324787d58f2SPoul-Henning Kamp } 325787d58f2SPoul-Henning Kamp 326787d58f2SPoul-Henning Kamp } 327787d58f2SPoul-Henning Kamp } 328787d58f2SPoul-Henning Kamp 329787d58f2SPoul-Henning Kamp static int 330787d58f2SPoul-Henning Kamp sysctl_sysctl_debug SYSCTL_HANDLER_ARGS 331787d58f2SPoul-Henning Kamp { 332787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node(&sysctl_, 0); 333787d58f2SPoul-Henning Kamp return ENOENT; 334787d58f2SPoul-Henning Kamp } 335787d58f2SPoul-Henning Kamp 336787d58f2SPoul-Henning Kamp SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD, 337946bb7a2SPoul-Henning Kamp 0, 0, sysctl_sysctl_debug, "-", ""); 3382e210993SPoul-Henning Kamp 339946bb7a2SPoul-Henning Kamp static int 340946bb7a2SPoul-Henning Kamp sysctl_sysctl_name SYSCTL_HANDLER_ARGS 341946bb7a2SPoul-Henning Kamp { 342946bb7a2SPoul-Henning Kamp int *name = (int *) arg1; 343946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 344946bb7a2SPoul-Henning Kamp int i, j, error = 0; 345946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 346946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 347946bb7a2SPoul-Henning Kamp char buf[10]; 3482e210993SPoul-Henning Kamp 349946bb7a2SPoul-Henning Kamp while (namelen) { 350946bb7a2SPoul-Henning Kamp if (!lsp) { 351946bb7a2SPoul-Henning Kamp sprintf(buf,"%d",*name); 352946bb7a2SPoul-Henning Kamp if (req->oldidx) 353946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, ".", 1); 354946bb7a2SPoul-Henning Kamp if (!error) 355946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, buf, strlen(buf)); 356946bb7a2SPoul-Henning Kamp if (error) 357946bb7a2SPoul-Henning Kamp return (error); 358946bb7a2SPoul-Henning Kamp namelen--; 359946bb7a2SPoul-Henning Kamp name++; 360946bb7a2SPoul-Henning Kamp continue; 361946bb7a2SPoul-Henning Kamp } 362946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 363946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 364946bb7a2SPoul-Henning Kamp lsp = 0; 365946bb7a2SPoul-Henning Kamp for (i = 0; i < j; i++, oidpp++) { 366946bb7a2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number != *name)) 367946bb7a2SPoul-Henning Kamp continue; 368946bb7a2SPoul-Henning Kamp 369946bb7a2SPoul-Henning Kamp if (req->oldidx) 370946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, ".", 1); 371946bb7a2SPoul-Henning Kamp if (!error) 372946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, (*oidpp)->oid_name, 373946bb7a2SPoul-Henning Kamp strlen((*oidpp)->oid_name)); 374946bb7a2SPoul-Henning Kamp if (error) 375946bb7a2SPoul-Henning Kamp return (error); 376946bb7a2SPoul-Henning Kamp 377946bb7a2SPoul-Henning Kamp namelen--; 378946bb7a2SPoul-Henning Kamp name++; 379946bb7a2SPoul-Henning Kamp 380946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 381946bb7a2SPoul-Henning Kamp break; 382946bb7a2SPoul-Henning Kamp 383946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 384946bb7a2SPoul-Henning Kamp break; 385946bb7a2SPoul-Henning Kamp 386946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 387946bb7a2SPoul-Henning Kamp break; 388946bb7a2SPoul-Henning Kamp } 389946bb7a2SPoul-Henning Kamp } 390946bb7a2SPoul-Henning Kamp return (SYSCTL_OUT(req, "", 1)); 391946bb7a2SPoul-Henning Kamp } 392946bb7a2SPoul-Henning Kamp 393946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD, sysctl_sysctl_name, ""); 394946bb7a2SPoul-Henning Kamp 395946bb7a2SPoul-Henning Kamp static int 396946bb7a2SPoul-Henning Kamp sysctl_sysctl_next_ls (struct linker_set *lsp, int *name, u_int namelen, 397946bb7a2SPoul-Henning Kamp int *next, int *len, int level, struct sysctl_oid **oidp) 398946bb7a2SPoul-Henning Kamp { 399946bb7a2SPoul-Henning Kamp int i, j; 400946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 401946bb7a2SPoul-Henning Kamp 402946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 403946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 404946bb7a2SPoul-Henning Kamp *len = level; 405946bb7a2SPoul-Henning Kamp for (i = 0; i < j; i++, oidpp++) { 406946bb7a2SPoul-Henning Kamp if (!*oidpp) 407946bb7a2SPoul-Henning Kamp continue; 408946bb7a2SPoul-Henning Kamp 409946bb7a2SPoul-Henning Kamp *next = (*oidpp)->oid_number; 410946bb7a2SPoul-Henning Kamp *oidp = *oidpp; 411946bb7a2SPoul-Henning Kamp 412946bb7a2SPoul-Henning Kamp if (!namelen) { 413946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 414946bb7a2SPoul-Henning Kamp return 0; 415946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 416946bb7a2SPoul-Henning Kamp /* We really should call the handler here...*/ 417946bb7a2SPoul-Henning Kamp return 0; 418946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 419946bb7a2SPoul-Henning Kamp return (sysctl_sysctl_next_ls (lsp, 0, 0, next+1, 420946bb7a2SPoul-Henning Kamp len, level+1, oidp)); 421946bb7a2SPoul-Henning Kamp } 422946bb7a2SPoul-Henning Kamp 423946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_number < *name) 424946bb7a2SPoul-Henning Kamp continue; 425946bb7a2SPoul-Henning Kamp 426946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_number > *name) { 427946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 428946bb7a2SPoul-Henning Kamp return 0; 429946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 430946bb7a2SPoul-Henning Kamp return 0; 431946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 432946bb7a2SPoul-Henning Kamp if (!sysctl_sysctl_next_ls (lsp, name+1, namelen-1, 433946bb7a2SPoul-Henning Kamp next+1, len, level+1, oidp)) 434946bb7a2SPoul-Henning Kamp return (0); 435946bb7a2SPoul-Henning Kamp namelen = 1; 436946bb7a2SPoul-Henning Kamp *len = level; 437946bb7a2SPoul-Henning Kamp continue; 438946bb7a2SPoul-Henning Kamp } 439946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 440946bb7a2SPoul-Henning Kamp continue; 441946bb7a2SPoul-Henning Kamp 442946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 443946bb7a2SPoul-Henning Kamp continue; 444946bb7a2SPoul-Henning Kamp 445946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 446946bb7a2SPoul-Henning Kamp if (!sysctl_sysctl_next_ls (lsp, name+1, namelen-1, next+1, 447946bb7a2SPoul-Henning Kamp len, level+1, oidp)) 448946bb7a2SPoul-Henning Kamp return (0); 449946bb7a2SPoul-Henning Kamp namelen = 1; 450946bb7a2SPoul-Henning Kamp *len = level; 451946bb7a2SPoul-Henning Kamp } 452946bb7a2SPoul-Henning Kamp return 1; 453946bb7a2SPoul-Henning Kamp } 454946bb7a2SPoul-Henning Kamp 455946bb7a2SPoul-Henning Kamp static int 456946bb7a2SPoul-Henning Kamp sysctl_sysctl_next SYSCTL_HANDLER_ARGS 457946bb7a2SPoul-Henning Kamp { 458946bb7a2SPoul-Henning Kamp int *name = (int *) arg1; 459946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 460946bb7a2SPoul-Henning Kamp int i, j, error; 461946bb7a2SPoul-Henning Kamp struct sysctl_oid *oid; 462946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 463946bb7a2SPoul-Henning Kamp int newoid[CTL_MAXNAME]; 464946bb7a2SPoul-Henning Kamp 465946bb7a2SPoul-Henning Kamp i = sysctl_sysctl_next_ls (lsp, name, namelen, newoid, &j, 1, &oid); 466946bb7a2SPoul-Henning Kamp if (i) 467946bb7a2SPoul-Henning Kamp return ENOENT; 468946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, newoid, j * sizeof (int)); 469946bb7a2SPoul-Henning Kamp return (error); 470946bb7a2SPoul-Henning Kamp } 471946bb7a2SPoul-Henning Kamp 472946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, ""); 473946bb7a2SPoul-Henning Kamp 474946bb7a2SPoul-Henning Kamp static int 475946bb7a2SPoul-Henning Kamp name2oid (char *name, int *oid, int *len, struct sysctl_oid **oidp) 476946bb7a2SPoul-Henning Kamp { 477946bb7a2SPoul-Henning Kamp int i, j; 478946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 479946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 480946bb7a2SPoul-Henning Kamp char *p; 481946bb7a2SPoul-Henning Kamp 482946bb7a2SPoul-Henning Kamp if (!*name) 483946bb7a2SPoul-Henning Kamp return ENOENT; 484946bb7a2SPoul-Henning Kamp 485946bb7a2SPoul-Henning Kamp p = name + strlen(name) - 1 ; 486946bb7a2SPoul-Henning Kamp if (*p == '.') 487946bb7a2SPoul-Henning Kamp *p = '\0'; 488946bb7a2SPoul-Henning Kamp 489946bb7a2SPoul-Henning Kamp *len = 0; 490946bb7a2SPoul-Henning Kamp 491946bb7a2SPoul-Henning Kamp for (p = name; *p && *p != '.'; p++) 492946bb7a2SPoul-Henning Kamp ; 493946bb7a2SPoul-Henning Kamp i = *p; 494946bb7a2SPoul-Henning Kamp if (i == '.') 495946bb7a2SPoul-Henning Kamp *p = '\0'; 496946bb7a2SPoul-Henning Kamp 497946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 498946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 499946bb7a2SPoul-Henning Kamp 500946bb7a2SPoul-Henning Kamp while (j-- && *len < CTL_MAXNAME) { 501946bb7a2SPoul-Henning Kamp if (!*oidpp) 502946bb7a2SPoul-Henning Kamp continue; 503946bb7a2SPoul-Henning Kamp if (strcmp(name, (*oidpp)->oid_name)) { 504946bb7a2SPoul-Henning Kamp oidpp++; 505946bb7a2SPoul-Henning Kamp continue; 506946bb7a2SPoul-Henning Kamp } 507946bb7a2SPoul-Henning Kamp *oid++ = (*oidpp)->oid_number; 508946bb7a2SPoul-Henning Kamp (*len)++; 509946bb7a2SPoul-Henning Kamp 510946bb7a2SPoul-Henning Kamp if (!i) { 511946bb7a2SPoul-Henning Kamp if (oidp) 512946bb7a2SPoul-Henning Kamp *oidp = *oidpp; 513946bb7a2SPoul-Henning Kamp return (0); 514946bb7a2SPoul-Henning Kamp } 515946bb7a2SPoul-Henning Kamp 516946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 517946bb7a2SPoul-Henning Kamp break; 518946bb7a2SPoul-Henning Kamp 519946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 520946bb7a2SPoul-Henning Kamp break; 521946bb7a2SPoul-Henning Kamp 522946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 523946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 524946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 525946bb7a2SPoul-Henning Kamp name = p+1; 526946bb7a2SPoul-Henning Kamp for (p = name; *p && *p != '.'; p++) 527946bb7a2SPoul-Henning Kamp ; 528946bb7a2SPoul-Henning Kamp i = *p; 529946bb7a2SPoul-Henning Kamp if (i == '.') 530946bb7a2SPoul-Henning Kamp *p = '\0'; 531946bb7a2SPoul-Henning Kamp } 532946bb7a2SPoul-Henning Kamp return ENOENT; 533946bb7a2SPoul-Henning Kamp } 534946bb7a2SPoul-Henning Kamp 535946bb7a2SPoul-Henning Kamp static int 536946bb7a2SPoul-Henning Kamp sysctl_sysctl_name2oid SYSCTL_HANDLER_ARGS 537946bb7a2SPoul-Henning Kamp { 538946bb7a2SPoul-Henning Kamp char *p; 539946bb7a2SPoul-Henning Kamp int error, oid[CTL_MAXNAME], len; 540946bb7a2SPoul-Henning Kamp struct sysctl_oid *op = 0; 541946bb7a2SPoul-Henning Kamp 542946bb7a2SPoul-Henning Kamp if (!req->newlen) 543946bb7a2SPoul-Henning Kamp return ENOENT; 544946bb7a2SPoul-Henning Kamp 545946bb7a2SPoul-Henning Kamp p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK); 546946bb7a2SPoul-Henning Kamp 547946bb7a2SPoul-Henning Kamp error = SYSCTL_IN(req, p, req->newlen); 548946bb7a2SPoul-Henning Kamp if (error) { 549946bb7a2SPoul-Henning Kamp free(p, M_SYSCTL); 550946bb7a2SPoul-Henning Kamp return (error); 551946bb7a2SPoul-Henning Kamp } 552946bb7a2SPoul-Henning Kamp 553946bb7a2SPoul-Henning Kamp p [req->newlen] = '\0'; 554946bb7a2SPoul-Henning Kamp 555946bb7a2SPoul-Henning Kamp error = name2oid(p, oid, &len, &op); 556946bb7a2SPoul-Henning Kamp 557946bb7a2SPoul-Henning Kamp free(p, M_SYSCTL); 558946bb7a2SPoul-Henning Kamp 559946bb7a2SPoul-Henning Kamp if (error) 560946bb7a2SPoul-Henning Kamp return (error); 561946bb7a2SPoul-Henning Kamp 562946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, oid, len * sizeof *oid); 563946bb7a2SPoul-Henning Kamp return (error); 564946bb7a2SPoul-Henning Kamp } 565946bb7a2SPoul-Henning Kamp 5663ac9f819SPoul-Henning Kamp SYSCTL_PROC(_sysctl, 3, name2oid, CTLFLAG_RW|CTLFLAG_ANYBODY, 0, 0, 567946bb7a2SPoul-Henning Kamp sysctl_sysctl_name2oid, "I", ""); 568946bb7a2SPoul-Henning Kamp 569946bb7a2SPoul-Henning Kamp static int 570946bb7a2SPoul-Henning Kamp sysctl_sysctl_oidfmt SYSCTL_HANDLER_ARGS 571946bb7a2SPoul-Henning Kamp { 57265d0bc13SPoul-Henning Kamp int *name = (int *) arg1, error; 573946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 574946bb7a2SPoul-Henning Kamp int indx, j; 575946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 576946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 577946bb7a2SPoul-Henning Kamp 578946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 579946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 580946bb7a2SPoul-Henning Kamp 581946bb7a2SPoul-Henning Kamp indx = 0; 582946bb7a2SPoul-Henning Kamp while (j-- && indx < CTL_MAXNAME) { 583946bb7a2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number == name[indx])) { 584946bb7a2SPoul-Henning Kamp indx++; 585946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 586946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 587946bb7a2SPoul-Henning Kamp goto found; 588946bb7a2SPoul-Henning Kamp if (indx == namelen) 58965d0bc13SPoul-Henning Kamp goto found; 590946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 591946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 592946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 593946bb7a2SPoul-Henning Kamp } else { 594946bb7a2SPoul-Henning Kamp if (indx != namelen) 595946bb7a2SPoul-Henning Kamp return EISDIR; 596946bb7a2SPoul-Henning Kamp goto found; 597946bb7a2SPoul-Henning Kamp } 598946bb7a2SPoul-Henning Kamp } else { 599946bb7a2SPoul-Henning Kamp oidpp++; 600946bb7a2SPoul-Henning Kamp } 601946bb7a2SPoul-Henning Kamp } 602946bb7a2SPoul-Henning Kamp return ENOENT; 603946bb7a2SPoul-Henning Kamp found: 604946bb7a2SPoul-Henning Kamp if (!(*oidpp)->oid_fmt) 605946bb7a2SPoul-Henning Kamp return ENOENT; 60665d0bc13SPoul-Henning Kamp error = SYSCTL_OUT(req, 60765d0bc13SPoul-Henning Kamp &(*oidpp)->oid_kind, sizeof((*oidpp)->oid_kind)); 60865d0bc13SPoul-Henning Kamp if (!error) 60965d0bc13SPoul-Henning Kamp error = SYSCTL_OUT(req, (*oidpp)->oid_fmt, 61065d0bc13SPoul-Henning Kamp strlen((*oidpp)->oid_fmt)+1); 61165d0bc13SPoul-Henning Kamp return (error); 612946bb7a2SPoul-Henning Kamp } 613946bb7a2SPoul-Henning Kamp 614946bb7a2SPoul-Henning Kamp 615946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD, sysctl_sysctl_oidfmt, ""); 616946bb7a2SPoul-Henning Kamp 617946bb7a2SPoul-Henning Kamp /* 618946bb7a2SPoul-Henning Kamp * Default "handler" functions. 619946bb7a2SPoul-Henning Kamp */ 6202e210993SPoul-Henning Kamp 621ae0eb976SPoul-Henning Kamp /* 622ae0eb976SPoul-Henning Kamp * Handle an integer, signed or unsigned. 623ae0eb976SPoul-Henning Kamp * Two cases: 624ae0eb976SPoul-Henning Kamp * a variable: point arg1 at it. 625ae0eb976SPoul-Henning Kamp * a constant: pass it in arg2. 626ae0eb976SPoul-Henning Kamp */ 627ae0eb976SPoul-Henning Kamp 6283a34a5c3SPoul-Henning Kamp int 6293a34a5c3SPoul-Henning Kamp sysctl_handle_int SYSCTL_HANDLER_ARGS 630b396cd83SPoul-Henning Kamp { 631ae0eb976SPoul-Henning Kamp int error = 0; 632b396cd83SPoul-Henning Kamp 633ae0eb976SPoul-Henning Kamp if (arg1) 634ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, sizeof(int)); 635ae0eb976SPoul-Henning Kamp else if (arg2) 636ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, &arg2, sizeof(int)); 637b396cd83SPoul-Henning Kamp 638ae0eb976SPoul-Henning Kamp if (error || !req->newptr) 639ae0eb976SPoul-Henning Kamp return (error); 640b396cd83SPoul-Henning Kamp 641ae0eb976SPoul-Henning Kamp if (!arg1) 642ae0eb976SPoul-Henning Kamp error = EPERM; 643ae0eb976SPoul-Henning Kamp else 644ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, sizeof(int)); 645ae0eb976SPoul-Henning Kamp return (error); 646b396cd83SPoul-Henning Kamp } 647b396cd83SPoul-Henning Kamp 648ae0eb976SPoul-Henning Kamp /* 649ae0eb976SPoul-Henning Kamp * Handle our generic '\0' terminated 'C' string. 650ae0eb976SPoul-Henning Kamp * Two cases: 651ae0eb976SPoul-Henning Kamp * a variable string: point arg1 at it, arg2 is max length. 652ae0eb976SPoul-Henning Kamp * a constant string: point arg1 at it, arg2 is zero. 653ae0eb976SPoul-Henning Kamp */ 654ae0eb976SPoul-Henning Kamp 6553a34a5c3SPoul-Henning Kamp int 6563a34a5c3SPoul-Henning Kamp sysctl_handle_string SYSCTL_HANDLER_ARGS 657b396cd83SPoul-Henning Kamp { 658ae0eb976SPoul-Henning Kamp int error=0; 659b396cd83SPoul-Henning Kamp 660ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, strlen((char *)arg1)+1); 661b396cd83SPoul-Henning Kamp 662deae269aSPoul-Henning Kamp if (error || !req->newptr || !arg2) 663ae0eb976SPoul-Henning Kamp return (error); 664ae0eb976SPoul-Henning Kamp 665ae0eb976SPoul-Henning Kamp if ((req->newlen - req->newidx) > arg2) { 666ae0eb976SPoul-Henning Kamp error = E2BIG; 667ae0eb976SPoul-Henning Kamp } else { 668ae0eb976SPoul-Henning Kamp arg2 = (req->newlen - req->newidx); 669ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, arg2); 670ae0eb976SPoul-Henning Kamp ((char *)arg1)[arg2] = '\0'; 671b396cd83SPoul-Henning Kamp } 672b396cd83SPoul-Henning Kamp 6732e210993SPoul-Henning Kamp return (error); 674b396cd83SPoul-Henning Kamp } 675b396cd83SPoul-Henning Kamp 676ae0eb976SPoul-Henning Kamp /* 677ae0eb976SPoul-Henning Kamp * Handle any kind of opaque data. 678ae0eb976SPoul-Henning Kamp * arg1 points to it, arg2 is the size. 679ae0eb976SPoul-Henning Kamp */ 680ae0eb976SPoul-Henning Kamp 6813a34a5c3SPoul-Henning Kamp int 6823a34a5c3SPoul-Henning Kamp sysctl_handle_opaque SYSCTL_HANDLER_ARGS 683b396cd83SPoul-Henning Kamp { 684ae0eb976SPoul-Henning Kamp int error; 685b396cd83SPoul-Henning Kamp 686ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, arg2); 687b396cd83SPoul-Henning Kamp 688ae0eb976SPoul-Henning Kamp if (error || !req->newptr) 689ae0eb976SPoul-Henning Kamp return (error); 690ae0eb976SPoul-Henning Kamp 691ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, arg2); 692ae0eb976SPoul-Henning Kamp 693ae0eb976SPoul-Henning Kamp return (error); 694b396cd83SPoul-Henning Kamp } 695ae0eb976SPoul-Henning Kamp 696deae269aSPoul-Henning Kamp /* 697deae269aSPoul-Henning Kamp * Transfer functions to/from kernel space. 698deae269aSPoul-Henning Kamp * XXX: rather untested at this point 699deae269aSPoul-Henning Kamp */ 700deae269aSPoul-Henning Kamp static int 7013ac9f819SPoul-Henning Kamp sysctl_old_kernel(struct sysctl_req *req, const void *p, int l) 702ae0eb976SPoul-Henning Kamp { 703deae269aSPoul-Henning Kamp int i = 0; 704deae269aSPoul-Henning Kamp 705deae269aSPoul-Henning Kamp if (req->oldptr) { 706deae269aSPoul-Henning Kamp i = min(req->oldlen - req->oldidx, l); 707deae269aSPoul-Henning Kamp if (i > 0) 708ae0eb976SPoul-Henning Kamp bcopy(p, req->oldptr + req->oldidx, i); 709ae0eb976SPoul-Henning Kamp } 710deae269aSPoul-Henning Kamp req->oldidx += l; 711ae0eb976SPoul-Henning Kamp if (i != l) 712ae0eb976SPoul-Henning Kamp return (ENOMEM); 7132e210993SPoul-Henning Kamp return (0); 714ae0eb976SPoul-Henning Kamp 715ae0eb976SPoul-Henning Kamp } 716ae0eb976SPoul-Henning Kamp 717deae269aSPoul-Henning Kamp static int 7183ac9f819SPoul-Henning Kamp sysctl_new_kernel(struct sysctl_req *req, const void *p, int l) 719ae0eb976SPoul-Henning Kamp { 720deae269aSPoul-Henning Kamp if (!req->newptr) 721deae269aSPoul-Henning Kamp return 0; 722deae269aSPoul-Henning Kamp if (req->newlen - req->newidx < l) 723ae0eb976SPoul-Henning Kamp return (EINVAL); 724ae0eb976SPoul-Henning Kamp bcopy(req->newptr + req->newidx, p, l); 725ae0eb976SPoul-Henning Kamp req->newidx += l; 726ae0eb976SPoul-Henning Kamp return (0); 727ae0eb976SPoul-Henning Kamp } 728ae0eb976SPoul-Henning Kamp 729deae269aSPoul-Henning Kamp /* 730deae269aSPoul-Henning Kamp * Transfer function to/from user space. 731deae269aSPoul-Henning Kamp */ 732deae269aSPoul-Henning Kamp static int 7333ac9f819SPoul-Henning Kamp sysctl_old_user(struct sysctl_req *req, const void *p, int l) 734ae0eb976SPoul-Henning Kamp { 735deae269aSPoul-Henning Kamp int error = 0, i = 0; 736ae0eb976SPoul-Henning Kamp 7374b2af45fSPoul-Henning Kamp if (req->lock == 1 && req->oldptr) { 7384b2af45fSPoul-Henning Kamp vslock(req->oldptr, req->oldlen); 7394b2af45fSPoul-Henning Kamp req->lock = 2; 7404b2af45fSPoul-Henning Kamp } 741deae269aSPoul-Henning Kamp if (req->oldptr) { 742deae269aSPoul-Henning Kamp i = min(req->oldlen - req->oldidx, l); 743deae269aSPoul-Henning Kamp if (i > 0) 744ae0eb976SPoul-Henning Kamp error = copyout(p, req->oldptr + req->oldidx, i); 745deae269aSPoul-Henning Kamp } 746deae269aSPoul-Henning Kamp req->oldidx += l; 747ae0eb976SPoul-Henning Kamp if (error) 748ae0eb976SPoul-Henning Kamp return (error); 749deae269aSPoul-Henning Kamp if (req->oldptr && i < l) 750ae0eb976SPoul-Henning Kamp return (ENOMEM); 751deae269aSPoul-Henning Kamp return (0); 752ae0eb976SPoul-Henning Kamp } 753ae0eb976SPoul-Henning Kamp 754deae269aSPoul-Henning Kamp static int 755ae0eb976SPoul-Henning Kamp sysctl_new_user(struct sysctl_req *req, void *p, int l) 756ae0eb976SPoul-Henning Kamp { 75716cd04a3SPoul-Henning Kamp int error; 758deae269aSPoul-Henning Kamp 759deae269aSPoul-Henning Kamp if (!req->newptr) 760deae269aSPoul-Henning Kamp return 0; 761deae269aSPoul-Henning Kamp if (req->newlen - req->newidx < l) 762ae0eb976SPoul-Henning Kamp return (EINVAL); 763ae0eb976SPoul-Henning Kamp error = copyin(req->newptr + req->newidx, p, l); 764ae0eb976SPoul-Henning Kamp req->newidx += l; 765ae0eb976SPoul-Henning Kamp return (error); 766b396cd83SPoul-Henning Kamp } 767b396cd83SPoul-Henning Kamp 768df8bae1dSRodney W. Grimes /* 7692e210993SPoul-Henning Kamp * Traverse our tree, and find the right node, execute whatever it points 7702e210993SPoul-Henning Kamp * at, and return the resulting error code. 7712e210993SPoul-Henning Kamp */ 7722e210993SPoul-Henning Kamp 7732e210993SPoul-Henning Kamp int 7742e210993SPoul-Henning Kamp sysctl_root SYSCTL_HANDLER_ARGS 7752e210993SPoul-Henning Kamp { 7762e210993SPoul-Henning Kamp int *name = (int *) arg1; 777946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 7782e210993SPoul-Henning Kamp int indx, i, j; 7792e210993SPoul-Henning Kamp struct sysctl_oid **oidpp; 7802e210993SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 7812e210993SPoul-Henning Kamp 7822e210993SPoul-Henning Kamp j = lsp->ls_length; 7832e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 7842e210993SPoul-Henning Kamp 7852e210993SPoul-Henning Kamp indx = 0; 7862e210993SPoul-Henning Kamp while (j-- && indx < CTL_MAXNAME) { 787787d58f2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number == name[indx])) { 7882e210993SPoul-Henning Kamp indx++; 7894b2af45fSPoul-Henning Kamp if ((*oidpp)->oid_kind & CTLFLAG_NOLOCK) 7904b2af45fSPoul-Henning Kamp req->lock = 0; 7912e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 7922e210993SPoul-Henning Kamp if ((*oidpp)->oid_handler) 7932e210993SPoul-Henning Kamp goto found; 7942e210993SPoul-Henning Kamp if (indx == namelen) 7952e210993SPoul-Henning Kamp return ENOENT; 7962e210993SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 7972e210993SPoul-Henning Kamp j = lsp->ls_length; 7982e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 7992e210993SPoul-Henning Kamp } else { 8002e210993SPoul-Henning Kamp if (indx != namelen) 8012e210993SPoul-Henning Kamp return EISDIR; 8022e210993SPoul-Henning Kamp goto found; 8032e210993SPoul-Henning Kamp } 8042e210993SPoul-Henning Kamp } else { 8052e210993SPoul-Henning Kamp oidpp++; 8062e210993SPoul-Henning Kamp } 8072e210993SPoul-Henning Kamp } 808deae269aSPoul-Henning Kamp return ENOENT; 8092e210993SPoul-Henning Kamp found: 8102e210993SPoul-Henning Kamp /* If writing isn't allowed */ 811ae0eb976SPoul-Henning Kamp if (req->newptr && !((*oidpp)->oid_kind & CTLFLAG_WR)) 8122e210993SPoul-Henning Kamp return (EPERM); 8132e210993SPoul-Henning Kamp 8143ac9f819SPoul-Henning Kamp /* Most likely only root can write */ 8153ac9f819SPoul-Henning Kamp if (!((*oidpp)->oid_kind & CTLFLAG_ANYBODY) && 8163ac9f819SPoul-Henning Kamp req->newptr && req->p && 8173ac9f819SPoul-Henning Kamp (i = suser(req->p->p_ucred, &req->p->p_acflag))) 8183ac9f819SPoul-Henning Kamp return (i); 8193ac9f819SPoul-Henning Kamp 8202e210993SPoul-Henning Kamp if (!(*oidpp)->oid_handler) 8212e210993SPoul-Henning Kamp return EINVAL; 8222e210993SPoul-Henning Kamp 8232e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 8242e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 8252e210993SPoul-Henning Kamp name + indx, namelen - indx, 826ae0eb976SPoul-Henning Kamp req); 8272e210993SPoul-Henning Kamp } else { 8282e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 8292e210993SPoul-Henning Kamp (*oidpp)->oid_arg1, (*oidpp)->oid_arg2, 830ae0eb976SPoul-Henning Kamp req); 8312e210993SPoul-Henning Kamp } 8322e210993SPoul-Henning Kamp return (i); 8332e210993SPoul-Henning Kamp } 8342e210993SPoul-Henning Kamp 835d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 836b8da2396SPoul-Henning Kamp struct sysctl_args { 837b8da2396SPoul-Henning Kamp int *name; 838b8da2396SPoul-Henning Kamp u_int namelen; 839b8da2396SPoul-Henning Kamp void *old; 840b8da2396SPoul-Henning Kamp size_t *oldlenp; 841b8da2396SPoul-Henning Kamp void *new; 842b8da2396SPoul-Henning Kamp size_t newlen; 843b8da2396SPoul-Henning Kamp }; 844d2d3e875SBruce Evans #endif 845b8da2396SPoul-Henning Kamp 846df8bae1dSRodney W. Grimes int 8474b2af45fSPoul-Henning Kamp __sysctl(struct proc *p, struct sysctl_args *uap, int *retval) 848df8bae1dSRodney W. Grimes { 849deae269aSPoul-Henning Kamp int error, i, j, name[CTL_MAXNAME]; 850b396cd83SPoul-Henning Kamp 851df8bae1dSRodney W. Grimes if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 852df8bae1dSRodney W. Grimes return (EINVAL); 853b396cd83SPoul-Henning Kamp 854797f2d22SPoul-Henning Kamp error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 855797f2d22SPoul-Henning Kamp if (error) 856df8bae1dSRodney W. Grimes return (error); 857df8bae1dSRodney W. Grimes 858deae269aSPoul-Henning Kamp error = userland_sysctl(p, name, uap->namelen, 859b8da2396SPoul-Henning Kamp uap->old, uap->oldlenp, 0, 860deae269aSPoul-Henning Kamp uap->new, uap->newlen, &j); 861deae269aSPoul-Henning Kamp if (error && error != ENOMEM) 862deae269aSPoul-Henning Kamp return (error); 863deae269aSPoul-Henning Kamp if (uap->oldlenp) { 864deae269aSPoul-Henning Kamp i = copyout(&j, uap->oldlenp, sizeof(j)); 865deae269aSPoul-Henning Kamp if (i) 866deae269aSPoul-Henning Kamp return (i); 867deae269aSPoul-Henning Kamp } 868deae269aSPoul-Henning Kamp return (error); 869b8da2396SPoul-Henning Kamp } 870b8da2396SPoul-Henning Kamp 871b8da2396SPoul-Henning Kamp /* 872b8da2396SPoul-Henning Kamp * This is used from various compatibility syscalls too. That's why name 873b8da2396SPoul-Henning Kamp * must be in kernel space. 874b8da2396SPoul-Henning Kamp */ 875b8da2396SPoul-Henning Kamp int 876b8da2396SPoul-Henning Kamp userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen, int *retval) 877b8da2396SPoul-Henning Kamp { 8784b2af45fSPoul-Henning Kamp int error = 0; 879ae0eb976SPoul-Henning Kamp struct sysctl_req req; 880ae0eb976SPoul-Henning Kamp 881ae0eb976SPoul-Henning Kamp bzero(&req, sizeof req); 882b8da2396SPoul-Henning Kamp 88316cd04a3SPoul-Henning Kamp req.p = p; 88416cd04a3SPoul-Henning Kamp 885b8da2396SPoul-Henning Kamp if (oldlenp) { 886b8da2396SPoul-Henning Kamp if (inkernel) { 887ae0eb976SPoul-Henning Kamp req.oldlen = *oldlenp; 888b8da2396SPoul-Henning Kamp } else { 889deae269aSPoul-Henning Kamp error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp)); 890b8da2396SPoul-Henning Kamp if (error) 891b8da2396SPoul-Henning Kamp return (error); 892b8da2396SPoul-Henning Kamp } 893b8da2396SPoul-Henning Kamp } 894b8da2396SPoul-Henning Kamp 895ae0eb976SPoul-Henning Kamp if (old) { 896ae0eb976SPoul-Henning Kamp if (!useracc(old, req.oldlen, B_WRITE)) 897ae0eb976SPoul-Henning Kamp return (EFAULT); 898ae0eb976SPoul-Henning Kamp req.oldptr= old; 899ae0eb976SPoul-Henning Kamp } 9002e210993SPoul-Henning Kamp 901b8da2396SPoul-Henning Kamp if (newlen) { 902ae0eb976SPoul-Henning Kamp if (!useracc(new, req.newlen, B_READ)) 903ae0eb976SPoul-Henning Kamp return (EFAULT); 904ae0eb976SPoul-Henning Kamp req.newlen = newlen; 905ae0eb976SPoul-Henning Kamp req.newptr = new; 906b396cd83SPoul-Henning Kamp } 907b396cd83SPoul-Henning Kamp 908ae0eb976SPoul-Henning Kamp req.oldfunc = sysctl_old_user; 909ae0eb976SPoul-Henning Kamp req.newfunc = sysctl_new_user; 9104b2af45fSPoul-Henning Kamp req.lock = 1; 9114b2af45fSPoul-Henning Kamp 9124b2af45fSPoul-Henning Kamp /* XXX this should probably be done in a general way */ 9134b2af45fSPoul-Henning Kamp while (memlock.sl_lock) { 9144b2af45fSPoul-Henning Kamp memlock.sl_want = 1; 9154b2af45fSPoul-Henning Kamp (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 9164b2af45fSPoul-Henning Kamp memlock.sl_locked++; 9174b2af45fSPoul-Henning Kamp } 9184b2af45fSPoul-Henning Kamp memlock.sl_lock = 1; 919ae0eb976SPoul-Henning Kamp 920ae0eb976SPoul-Henning Kamp error = sysctl_root(0, name, namelen, &req); 921b396cd83SPoul-Henning Kamp 9224b2af45fSPoul-Henning Kamp if (req.lock == 2) 9234b2af45fSPoul-Henning Kamp vsunlock(req.oldptr, req.oldlen, B_WRITE); 9244b2af45fSPoul-Henning Kamp 9254b2af45fSPoul-Henning Kamp memlock.sl_lock = 0; 9264b2af45fSPoul-Henning Kamp 9274b2af45fSPoul-Henning Kamp if (memlock.sl_want) { 9284b2af45fSPoul-Henning Kamp memlock.sl_want = 0; 9294b2af45fSPoul-Henning Kamp wakeup((caddr_t)&memlock); 9304b2af45fSPoul-Henning Kamp } 9314b2af45fSPoul-Henning Kamp 932deae269aSPoul-Henning Kamp if (error && error != ENOMEM) 933deae269aSPoul-Henning Kamp return (error); 934deae269aSPoul-Henning Kamp 935deae269aSPoul-Henning Kamp if (retval) { 936deae269aSPoul-Henning Kamp if (req.oldptr && req.oldidx > req.oldlen) 937ae0eb976SPoul-Henning Kamp *retval = req.oldlen; 938deae269aSPoul-Henning Kamp else 939deae269aSPoul-Henning Kamp *retval = req.oldidx; 940b8da2396SPoul-Henning Kamp } 9412e210993SPoul-Henning Kamp return (error); 942df8bae1dSRodney W. Grimes } 943df8bae1dSRodney W. Grimes 944df8bae1dSRodney W. Grimes #ifdef COMPAT_43 945df8bae1dSRodney W. Grimes #include <sys/socket.h> 946df8bae1dSRodney W. Grimes #define KINFO_PROC (0<<8) 947df8bae1dSRodney W. Grimes #define KINFO_RT (1<<8) 948df8bae1dSRodney W. Grimes #define KINFO_VNODE (2<<8) 949df8bae1dSRodney W. Grimes #define KINFO_FILE (3<<8) 950df8bae1dSRodney W. Grimes #define KINFO_METER (4<<8) 951df8bae1dSRodney W. Grimes #define KINFO_LOADAVG (5<<8) 952df8bae1dSRodney W. Grimes #define KINFO_CLOCKRATE (6<<8) 953df8bae1dSRodney W. Grimes 9546ece4a51SPeter Wemm /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ 9556ece4a51SPeter Wemm #define KINFO_BSDI_SYSINFO (101<<8) 9566ece4a51SPeter Wemm 9576ece4a51SPeter Wemm /* 9586ece4a51SPeter Wemm * XXX this is bloat, but I hope it's better here than on the potentially 9596ece4a51SPeter Wemm * limited kernel stack... -Peter 9606ece4a51SPeter Wemm */ 9616ece4a51SPeter Wemm 96287b6de2bSPoul-Henning Kamp static struct { 9636ece4a51SPeter Wemm int bsdi_machine; /* "i386" on BSD/386 */ 9646ece4a51SPeter Wemm /* ^^^ this is an offset to the string, relative to the struct start */ 9656ece4a51SPeter Wemm char *pad0; 9666ece4a51SPeter Wemm long pad1; 9676ece4a51SPeter Wemm long pad2; 9686ece4a51SPeter Wemm long pad3; 9696ece4a51SPeter Wemm u_long pad4; 9706ece4a51SPeter Wemm u_long pad5; 9716ece4a51SPeter Wemm u_long pad6; 9726ece4a51SPeter Wemm 9736ece4a51SPeter Wemm int bsdi_ostype; /* "BSD/386" on BSD/386 */ 9746ece4a51SPeter Wemm int bsdi_osrelease; /* "1.1" on BSD/386 */ 9756ece4a51SPeter Wemm long pad7; 9766ece4a51SPeter Wemm long pad8; 9776ece4a51SPeter Wemm char *pad9; 9786ece4a51SPeter Wemm 9796ece4a51SPeter Wemm long pad10; 9806ece4a51SPeter Wemm long pad11; 9816ece4a51SPeter Wemm int pad12; 9826ece4a51SPeter Wemm long pad13; 9836ece4a51SPeter Wemm quad_t pad14; 9846ece4a51SPeter Wemm long pad15; 9856ece4a51SPeter Wemm 9866ece4a51SPeter Wemm struct timeval pad16; 9876ece4a51SPeter Wemm /* we dont set this, because BSDI's uname used gethostname() instead */ 9886ece4a51SPeter Wemm int bsdi_hostname; /* hostname on BSD/386 */ 9896ece4a51SPeter Wemm 9906ece4a51SPeter Wemm /* the actual string data is appended here */ 9916ece4a51SPeter Wemm 9926ece4a51SPeter Wemm } bsdi_si; 9936ece4a51SPeter Wemm /* 9946ece4a51SPeter Wemm * this data is appended to the end of the bsdi_si structure during copyout. 9956ece4a51SPeter Wemm * The "char *" offsets are relative to the base of the bsdi_si struct. 9966ece4a51SPeter Wemm * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings 9976ece4a51SPeter Wemm * should not exceed the length of the buffer here... (or else!! :-) 9986ece4a51SPeter Wemm */ 99987b6de2bSPoul-Henning Kamp static char bsdi_strings[80]; /* It had better be less than this! */ 10006ece4a51SPeter Wemm 1001d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1002df8bae1dSRodney W. Grimes struct getkerninfo_args { 1003df8bae1dSRodney W. Grimes int op; 1004df8bae1dSRodney W. Grimes char *where; 1005df8bae1dSRodney W. Grimes int *size; 1006df8bae1dSRodney W. Grimes int arg; 1007df8bae1dSRodney W. Grimes }; 1008d2d3e875SBruce Evans #endif 1009df8bae1dSRodney W. Grimes 101026f9a767SRodney W. Grimes int 10114b2af45fSPoul-Henning Kamp ogetkerninfo(struct proc *p, struct getkerninfo_args *uap, int *retval) 1012df8bae1dSRodney W. Grimes { 1013b8da2396SPoul-Henning Kamp int error, name[6]; 1014df8bae1dSRodney W. Grimes u_int size; 1015df8bae1dSRodney W. Grimes 1016df8bae1dSRodney W. Grimes switch (uap->op & 0xff00) { 1017df8bae1dSRodney W. Grimes 1018df8bae1dSRodney W. Grimes case KINFO_RT: 1019b8da2396SPoul-Henning Kamp name[0] = CTL_NET; 1020b8da2396SPoul-Henning Kamp name[1] = PF_ROUTE; 1021b8da2396SPoul-Henning Kamp name[2] = 0; 1022b8da2396SPoul-Henning Kamp name[3] = (uap->op & 0xff0000) >> 16; 1023b8da2396SPoul-Henning Kamp name[4] = uap->op & 0xff; 1024b8da2396SPoul-Henning Kamp name[5] = uap->arg; 1025b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 6, uap->where, uap->size, 10264b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1027df8bae1dSRodney W. Grimes break; 1028df8bae1dSRodney W. Grimes 1029df8bae1dSRodney W. Grimes case KINFO_VNODE: 1030b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1031b8da2396SPoul-Henning Kamp name[1] = KERN_VNODE; 1032b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10334b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1034df8bae1dSRodney W. Grimes break; 1035df8bae1dSRodney W. Grimes 1036df8bae1dSRodney W. Grimes case KINFO_PROC: 1037b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1038b8da2396SPoul-Henning Kamp name[1] = KERN_PROC; 1039b8da2396SPoul-Henning Kamp name[2] = uap->op & 0xff; 1040b8da2396SPoul-Henning Kamp name[3] = uap->arg; 1041b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 4, uap->where, uap->size, 10424b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1043df8bae1dSRodney W. Grimes break; 1044df8bae1dSRodney W. Grimes 1045df8bae1dSRodney W. Grimes case KINFO_FILE: 1046b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1047b8da2396SPoul-Henning Kamp name[1] = KERN_FILE; 1048b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10494b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1050df8bae1dSRodney W. Grimes break; 1051df8bae1dSRodney W. Grimes 1052df8bae1dSRodney W. Grimes case KINFO_METER: 1053b8da2396SPoul-Henning Kamp name[0] = CTL_VM; 1054b8da2396SPoul-Henning Kamp name[1] = VM_METER; 1055b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10564b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1057df8bae1dSRodney W. Grimes break; 1058df8bae1dSRodney W. Grimes 1059df8bae1dSRodney W. Grimes case KINFO_LOADAVG: 1060b8da2396SPoul-Henning Kamp name[0] = CTL_VM; 1061b8da2396SPoul-Henning Kamp name[1] = VM_LOADAVG; 1062b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10634b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1064df8bae1dSRodney W. Grimes break; 1065df8bae1dSRodney W. Grimes 1066df8bae1dSRodney W. Grimes case KINFO_CLOCKRATE: 1067b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1068b8da2396SPoul-Henning Kamp name[1] = KERN_CLOCKRATE; 1069b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10704b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1071df8bae1dSRodney W. Grimes break; 1072df8bae1dSRodney W. Grimes 10736ece4a51SPeter Wemm case KINFO_BSDI_SYSINFO: { 10746ece4a51SPeter Wemm /* 10756ece4a51SPeter Wemm * this is pretty crude, but it's just enough for uname() 10766ece4a51SPeter Wemm * from BSDI's 1.x libc to work. 10776ece4a51SPeter Wemm * 10786ece4a51SPeter Wemm * In particular, it doesn't return the same results when 10796ece4a51SPeter Wemm * the supplied buffer is too small. BSDI's version apparently 10806ece4a51SPeter Wemm * will return the amount copied, and set the *size to how 10816ece4a51SPeter Wemm * much was needed. The emulation framework here isn't capable 10826ece4a51SPeter Wemm * of that, so we just set both to the amount copied. 10836ece4a51SPeter Wemm * BSDI's 2.x product apparently fails with ENOMEM in this 10846ece4a51SPeter Wemm * scenario. 10856ece4a51SPeter Wemm */ 10866ece4a51SPeter Wemm 10876ece4a51SPeter Wemm u_int needed; 10886ece4a51SPeter Wemm u_int left; 10896ece4a51SPeter Wemm char *s; 10906ece4a51SPeter Wemm 10916ece4a51SPeter Wemm bzero((char *)&bsdi_si, sizeof(bsdi_si)); 10926ece4a51SPeter Wemm bzero(bsdi_strings, sizeof(bsdi_strings)); 10936ece4a51SPeter Wemm 10946ece4a51SPeter Wemm s = bsdi_strings; 10956ece4a51SPeter Wemm 10966ece4a51SPeter Wemm bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); 10976ece4a51SPeter Wemm strcpy(s, ostype); 10986ece4a51SPeter Wemm s += strlen(s) + 1; 10996ece4a51SPeter Wemm 11006ece4a51SPeter Wemm bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); 11016ece4a51SPeter Wemm strcpy(s, osrelease); 11026ece4a51SPeter Wemm s += strlen(s) + 1; 11036ece4a51SPeter Wemm 11046ece4a51SPeter Wemm bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); 11056ece4a51SPeter Wemm strcpy(s, machine); 11066ece4a51SPeter Wemm s += strlen(s) + 1; 11076ece4a51SPeter Wemm 11086ece4a51SPeter Wemm needed = sizeof(bsdi_si) + (s - bsdi_strings); 11096ece4a51SPeter Wemm 11106ece4a51SPeter Wemm if (uap->where == NULL) { 11116ece4a51SPeter Wemm /* process is asking how much buffer to supply.. */ 11126ece4a51SPeter Wemm size = needed; 11136ece4a51SPeter Wemm error = 0; 11146ece4a51SPeter Wemm break; 11156ece4a51SPeter Wemm } 11166ece4a51SPeter Wemm 11176ece4a51SPeter Wemm 11186ece4a51SPeter Wemm /* if too much buffer supplied, trim it down */ 11196ece4a51SPeter Wemm if (size > needed) 11206ece4a51SPeter Wemm size = needed; 11216ece4a51SPeter Wemm 11226ece4a51SPeter Wemm /* how much of the buffer is remaining */ 11236ece4a51SPeter Wemm left = size; 11246ece4a51SPeter Wemm 11256ece4a51SPeter Wemm if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) 11266ece4a51SPeter Wemm break; 11276ece4a51SPeter Wemm 11286ece4a51SPeter Wemm /* is there any point in continuing? */ 11296ece4a51SPeter Wemm if (left > sizeof(bsdi_si)) { 11306ece4a51SPeter Wemm left -= sizeof(bsdi_si); 11316ece4a51SPeter Wemm error = copyout(&bsdi_strings, 11326ece4a51SPeter Wemm uap->where + sizeof(bsdi_si), left); 11336ece4a51SPeter Wemm } 11346ece4a51SPeter Wemm break; 11356ece4a51SPeter Wemm } 11366ece4a51SPeter Wemm 1137df8bae1dSRodney W. Grimes default: 1138df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 1139df8bae1dSRodney W. Grimes } 1140df8bae1dSRodney W. Grimes if (error) 1141df8bae1dSRodney W. Grimes return (error); 1142df8bae1dSRodney W. Grimes *retval = size; 1143df8bae1dSRodney W. Grimes if (uap->size) 1144df8bae1dSRodney W. Grimes error = copyout((caddr_t)&size, (caddr_t)uap->size, 1145df8bae1dSRodney W. Grimes sizeof(size)); 1146df8bae1dSRodney W. Grimes return (error); 1147df8bae1dSRodney W. Grimes } 1148df8bae1dSRodney W. Grimes #endif /* COMPAT_43 */ 1149