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 40946bb7a2SPoul-Henning Kamp * $Id: kern_sysctl.c,v 1.52 1995/11/20 12:42:03 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> 52df8bae1dSRodney W. Grimes 534b2af45fSPoul-Henning Kamp /* 544b2af45fSPoul-Henning Kamp * Locking and stats 554b2af45fSPoul-Henning Kamp */ 564b2af45fSPoul-Henning Kamp static struct sysctl_lock { 574b2af45fSPoul-Henning Kamp int sl_lock; 584b2af45fSPoul-Henning Kamp int sl_want; 594b2af45fSPoul-Henning Kamp int sl_locked; 604b2af45fSPoul-Henning Kamp } memlock; 614b2af45fSPoul-Henning Kamp 624b2af45fSPoul-Henning Kamp static int sysctl_root SYSCTL_HANDLER_ARGS; 634b2af45fSPoul-Henning Kamp 64787d58f2SPoul-Henning Kamp extern struct linker_set sysctl_; 65787d58f2SPoul-Henning Kamp 66946bb7a2SPoul-Henning Kamp /* 67946bb7a2SPoul-Henning Kamp * MIB definitions. XXX Very few of these, if any, belong here. 68946bb7a2SPoul-Henning Kamp */ 69787d58f2SPoul-Henning Kamp SYSCTL_NODE(, 0, sysctl, CTLFLAG_RW, 0, 70787d58f2SPoul-Henning Kamp "Sysctl internal magic"); 712e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_KERN, kern, CTLFLAG_RW, 0, 722e210993SPoul-Henning Kamp "High kernel, proc, limits &c"); 732e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_VM, vm, CTLFLAG_RW, 0, 742e210993SPoul-Henning Kamp "Virtual memory"); 752e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_FS, fs, CTLFLAG_RW, 0, 762e210993SPoul-Henning Kamp "File system"); 772e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_NET, net, CTLFLAG_RW, 0, 782e210993SPoul-Henning Kamp "Network, (see socket.h)"); 792e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_DEBUG, debug, CTLFLAG_RW, 0, 802e210993SPoul-Henning Kamp "Debugging"); 812e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_HW, hw, CTLFLAG_RW, 0, 822e210993SPoul-Henning Kamp "hardware"); 832e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_MACHDEP, machdep, CTLFLAG_RW, 0, 842e210993SPoul-Henning Kamp "machine dependent"); 852e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW, 0, 862e210993SPoul-Henning Kamp "user-level"); 87b396cd83SPoul-Henning Kamp 882e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD, osrelease, 0, ""); 89b396cd83SPoul-Henning Kamp 902e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD, 0, BSD, ""); 91b396cd83SPoul-Henning Kamp 922e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD, version, 0, ""); 93b396cd83SPoul-Henning Kamp 942e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD, ostype, 0, ""); 95b396cd83SPoul-Henning Kamp 96b396cd83SPoul-Henning Kamp extern int osreldate; 972e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD, &osreldate, 0, ""); 98b396cd83SPoul-Henning Kamp 992e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXPROC, maxproc, CTLFLAG_RD, &maxproc, 0, ""); 100b396cd83SPoul-Henning Kamp 101b396cd83SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXPROCPERUID, maxprocperuid, 1023a34a5c3SPoul-Henning Kamp CTLFLAG_RD, &maxprocperuid, 0, ""); 103b396cd83SPoul-Henning Kamp 1042e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_ARGMAX, argmax, CTLFLAG_RD, 0, ARG_MAX, ""); 105b396cd83SPoul-Henning Kamp 1062e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD, 0, _POSIX_VERSION, ""); 107b396cd83SPoul-Henning Kamp 1082e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RD, 0, NGROUPS_MAX, ""); 109b396cd83SPoul-Henning Kamp 1102e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control, CTLFLAG_RD, 0, 1, ""); 111b396cd83SPoul-Henning Kamp 112b396cd83SPoul-Henning Kamp #ifdef _POSIX_SAVED_IDS 1132e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 1, ""); 114b396cd83SPoul-Henning Kamp #else 1152e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 0, ""); 116b396cd83SPoul-Henning Kamp #endif 117b396cd83SPoul-Henning Kamp 118b396cd83SPoul-Henning Kamp char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */ 119b396cd83SPoul-Henning Kamp 120b396cd83SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, 1213a34a5c3SPoul-Henning Kamp CTLFLAG_RW, kernelname, sizeof kernelname, ""); 122b396cd83SPoul-Henning Kamp 1232e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD, 0, 1, ""); 124b396cd83SPoul-Henning Kamp 1252e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD, 0, BYTE_ORDER, ""); 126b396cd83SPoul-Henning Kamp 1272e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_PAGESIZE, pagesize, CTLFLAG_RD, 0, PAGE_SIZE, ""); 128b396cd83SPoul-Henning Kamp 1292e210993SPoul-Henning Kamp char hostname[MAXHOSTNAMELEN]; 1302e210993SPoul-Henning Kamp 1319565c0e6SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_HOSTNAME, hostname, CTLFLAG_RW, 1329565c0e6SPoul-Henning Kamp hostname, sizeof(hostname), ""); 1332e210993SPoul-Henning Kamp 1344b2af45fSPoul-Henning Kamp int securelevel = -1; 1354b2af45fSPoul-Henning Kamp 1364b2af45fSPoul-Henning Kamp static int 1374b2af45fSPoul-Henning Kamp sysctl_kern_securelvl SYSCTL_HANDLER_ARGS 1384b2af45fSPoul-Henning Kamp { 1394b2af45fSPoul-Henning Kamp int error, level; 1404b2af45fSPoul-Henning Kamp 1414b2af45fSPoul-Henning Kamp level = securelevel; 1424b2af45fSPoul-Henning Kamp error = sysctl_handle_int(oidp, &level, 0, req); 1434b2af45fSPoul-Henning Kamp if (error || !req->newptr) 1444b2af45fSPoul-Henning Kamp return (error); 1454b2af45fSPoul-Henning Kamp if (level < securelevel && req->p->p_pid != 1) 1464b2af45fSPoul-Henning Kamp return (EPERM); 1474b2af45fSPoul-Henning Kamp securelevel = level; 1484b2af45fSPoul-Henning Kamp return (error); 1494b2af45fSPoul-Henning Kamp } 1504b2af45fSPoul-Henning Kamp 1514b2af45fSPoul-Henning Kamp SYSCTL_PROC(_kern, KERN_SECURELVL, securelevel, CTLTYPE_INT|CTLFLAG_RW, 152946bb7a2SPoul-Henning Kamp 0, 0, sysctl_kern_securelvl, "I", ""); 1534b2af45fSPoul-Henning Kamp 154946bb7a2SPoul-Henning Kamp char domainname[MAXHOSTNAMELEN]; 155946bb7a2SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_DOMAINNAME, domainname, CTLFLAG_RW, 156946bb7a2SPoul-Henning Kamp &domainname, sizeof(domainname), ""); 1574b2af45fSPoul-Henning Kamp 158946bb7a2SPoul-Henning Kamp long hostid; 159946bb7a2SPoul-Henning Kamp /* Some trouble here, if sizeof (int) != sizeof (long) */ 160946bb7a2SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_HOSTID, hostid, CTLFLAG_RW, &hostid, 0, ""); 1614b2af45fSPoul-Henning Kamp 162946bb7a2SPoul-Henning Kamp /* 163946bb7a2SPoul-Henning Kamp * End of MIB definitions. 164946bb7a2SPoul-Henning Kamp */ 1654b2af45fSPoul-Henning Kamp 166946bb7a2SPoul-Henning Kamp /* 167946bb7a2SPoul-Henning Kamp * Initialization of the MIB tree. 168946bb7a2SPoul-Henning Kamp * 169946bb7a2SPoul-Henning Kamp * Order by number in each linker_set. 170946bb7a2SPoul-Henning Kamp */ 1714b2af45fSPoul-Henning Kamp 172787d58f2SPoul-Henning Kamp static int 1733c8e79ddSBruce Evans sysctl_order_cmp(const void *a, const void *b) 174787d58f2SPoul-Henning Kamp { 1753c8e79ddSBruce Evans const struct sysctl_oid **pa, **pb; 1763c8e79ddSBruce Evans 1773c8e79ddSBruce Evans pa = (const struct sysctl_oid **)a; 1783c8e79ddSBruce Evans pb = (const struct sysctl_oid **)b; 1793c8e79ddSBruce Evans if (*pa == NULL) 1803c8e79ddSBruce Evans return (1); 1813c8e79ddSBruce Evans if (*pb == NULL) 1823c8e79ddSBruce Evans return (-1); 183787d58f2SPoul-Henning Kamp return ((*pa)->oid_number - (*pb)->oid_number); 184787d58f2SPoul-Henning Kamp } 185787d58f2SPoul-Henning Kamp 186787d58f2SPoul-Henning Kamp static void 187787d58f2SPoul-Henning Kamp sysctl_order(void *arg) 188787d58f2SPoul-Henning Kamp { 189946bb7a2SPoul-Henning Kamp int j, k; 190787d58f2SPoul-Henning Kamp struct linker_set *l = (struct linker_set *) arg; 191787d58f2SPoul-Henning Kamp struct sysctl_oid **oidpp; 192787d58f2SPoul-Henning Kamp 193946bb7a2SPoul-Henning Kamp /* First, find the highest oid we have */ 194946bb7a2SPoul-Henning Kamp j = l->ls_length; 195946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 196946bb7a2SPoul-Henning Kamp for (k = 0; j--; oidpp++) 197946bb7a2SPoul-Henning Kamp if (*oidpp && (*oidpp)->oid_number > k) 198946bb7a2SPoul-Henning Kamp k = (*oidpp)->oid_number; 199946bb7a2SPoul-Henning Kamp 200946bb7a2SPoul-Henning Kamp /* Next, replace all OID_AUTO oids with new numbers */ 201946bb7a2SPoul-Henning Kamp j = l->ls_length; 202946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 203946bb7a2SPoul-Henning Kamp k += 100; 204946bb7a2SPoul-Henning Kamp for (; j--; oidpp++) 205946bb7a2SPoul-Henning Kamp if (*oidpp && (*oidpp)->oid_number == OID_AUTO) 206946bb7a2SPoul-Henning Kamp (*oidpp)->oid_number = k++; 207946bb7a2SPoul-Henning Kamp 208946bb7a2SPoul-Henning Kamp /* Finally: sort by oid */ 209787d58f2SPoul-Henning Kamp j = l->ls_length; 210787d58f2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 211787d58f2SPoul-Henning Kamp for (; j--; oidpp++) { 212787d58f2SPoul-Henning Kamp if (!*oidpp) 213787d58f2SPoul-Henning Kamp continue; 214787d58f2SPoul-Henning Kamp if ((*oidpp)->oid_arg1 == arg) { 215787d58f2SPoul-Henning Kamp *oidpp = 0; 216787d58f2SPoul-Henning Kamp continue; 217787d58f2SPoul-Henning Kamp } 218787d58f2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) 219787d58f2SPoul-Henning Kamp if (!(*oidpp)->oid_handler) 220787d58f2SPoul-Henning Kamp sysctl_order((*oidpp)->oid_arg1); 221787d58f2SPoul-Henning Kamp } 222787d58f2SPoul-Henning Kamp qsort(l->ls_items, l->ls_length, sizeof l->ls_items[0], 223787d58f2SPoul-Henning Kamp sysctl_order_cmp); 224787d58f2SPoul-Henning Kamp } 225787d58f2SPoul-Henning Kamp 226787d58f2SPoul-Henning Kamp SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_order, &sysctl_); 227787d58f2SPoul-Henning Kamp 228946bb7a2SPoul-Henning Kamp /* 229946bb7a2SPoul-Henning Kamp * "Staff-functions" 230946bb7a2SPoul-Henning Kamp * 231946bb7a2SPoul-Henning Kamp * {0,0} printf the entire MIB-tree. 232946bb7a2SPoul-Henning Kamp * {0,1,...} return the name of the "..." OID. 233946bb7a2SPoul-Henning Kamp * {0,2,...} return the next OID. 234946bb7a2SPoul-Henning Kamp * {0,3} return the OID of the name in "new" 235946bb7a2SPoul-Henning Kamp * {0,4,...} return the format info for the "..." OID. 236946bb7a2SPoul-Henning Kamp */ 237946bb7a2SPoul-Henning Kamp 238787d58f2SPoul-Henning Kamp static void 239787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node(struct linker_set *l, int i) 240787d58f2SPoul-Henning Kamp { 241787d58f2SPoul-Henning Kamp int j, k; 242787d58f2SPoul-Henning Kamp struct sysctl_oid **oidpp; 243787d58f2SPoul-Henning Kamp 244787d58f2SPoul-Henning Kamp j = l->ls_length; 245787d58f2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 246787d58f2SPoul-Henning Kamp for (; j--; oidpp++) { 247787d58f2SPoul-Henning Kamp 248787d58f2SPoul-Henning Kamp if (!*oidpp) 249787d58f2SPoul-Henning Kamp continue; 250787d58f2SPoul-Henning Kamp 251787d58f2SPoul-Henning Kamp for (k=0; k<i; k++) 252787d58f2SPoul-Henning Kamp printf(" "); 253787d58f2SPoul-Henning Kamp 254787d58f2SPoul-Henning Kamp if ((*oidpp)->oid_number > 100) { 255b8da2396SPoul-Henning Kamp printf("Junk! %p # %d %s k %x a1 %p a2 %x h %p\n", 256787d58f2SPoul-Henning Kamp *oidpp, 257787d58f2SPoul-Henning Kamp (*oidpp)->oid_number, (*oidpp)->oid_name, 258787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind, (*oidpp)->oid_arg1, 259787d58f2SPoul-Henning Kamp (*oidpp)->oid_arg2, (*oidpp)->oid_handler); 260787d58f2SPoul-Henning Kamp continue; 261787d58f2SPoul-Henning Kamp } 262787d58f2SPoul-Henning Kamp printf("%d %s ", (*oidpp)->oid_number, (*oidpp)->oid_name); 263787d58f2SPoul-Henning Kamp 264787d58f2SPoul-Henning Kamp printf("%c%c", 265787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind & CTLFLAG_RD ? 'R':' ', 266787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind & CTLFLAG_WR ? 'W':' '); 267787d58f2SPoul-Henning Kamp 268787d58f2SPoul-Henning Kamp switch ((*oidpp)->oid_kind & CTLTYPE) { 269787d58f2SPoul-Henning Kamp case CTLTYPE_NODE: 270787d58f2SPoul-Henning Kamp if ((*oidpp)->oid_handler) { 271787d58f2SPoul-Henning Kamp printf(" Node(proc)\n"); 272787d58f2SPoul-Henning Kamp } else { 273787d58f2SPoul-Henning Kamp printf(" Node\n"); 274787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node( 275787d58f2SPoul-Henning Kamp (*oidpp)->oid_arg1, i+2); 276787d58f2SPoul-Henning Kamp } 277787d58f2SPoul-Henning Kamp break; 278787d58f2SPoul-Henning Kamp case CTLTYPE_INT: printf(" Int\n"); break; 279787d58f2SPoul-Henning Kamp case CTLTYPE_STRING: printf(" String\n"); break; 280787d58f2SPoul-Henning Kamp case CTLTYPE_QUAD: printf(" Quad\n"); break; 281787d58f2SPoul-Henning Kamp case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break; 282787d58f2SPoul-Henning Kamp default: printf("\n"); 283787d58f2SPoul-Henning Kamp } 284787d58f2SPoul-Henning Kamp 285787d58f2SPoul-Henning Kamp } 286787d58f2SPoul-Henning Kamp } 287787d58f2SPoul-Henning Kamp 288787d58f2SPoul-Henning Kamp static int 289787d58f2SPoul-Henning Kamp sysctl_sysctl_debug SYSCTL_HANDLER_ARGS 290787d58f2SPoul-Henning Kamp { 291787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node(&sysctl_, 0); 292787d58f2SPoul-Henning Kamp return ENOENT; 293787d58f2SPoul-Henning Kamp } 294787d58f2SPoul-Henning Kamp 295787d58f2SPoul-Henning Kamp SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD, 296946bb7a2SPoul-Henning Kamp 0, 0, sysctl_sysctl_debug, "-", ""); 2972e210993SPoul-Henning Kamp 298946bb7a2SPoul-Henning Kamp static int 299946bb7a2SPoul-Henning Kamp sysctl_sysctl_name SYSCTL_HANDLER_ARGS 300946bb7a2SPoul-Henning Kamp { 301946bb7a2SPoul-Henning Kamp int *name = (int *) arg1; 302946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 303946bb7a2SPoul-Henning Kamp int i, j, error = 0; 304946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 305946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 306946bb7a2SPoul-Henning Kamp char buf[10]; 3072e210993SPoul-Henning Kamp 308946bb7a2SPoul-Henning Kamp while (namelen) { 309946bb7a2SPoul-Henning Kamp if (!lsp) { 310946bb7a2SPoul-Henning Kamp sprintf(buf,"%d",*name); 311946bb7a2SPoul-Henning Kamp if (req->oldidx) 312946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, ".", 1); 313946bb7a2SPoul-Henning Kamp if (!error) 314946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, buf, strlen(buf)); 315946bb7a2SPoul-Henning Kamp if (error) 316946bb7a2SPoul-Henning Kamp return (error); 317946bb7a2SPoul-Henning Kamp namelen--; 318946bb7a2SPoul-Henning Kamp name++; 319946bb7a2SPoul-Henning Kamp continue; 320946bb7a2SPoul-Henning Kamp } 321946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 322946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 323946bb7a2SPoul-Henning Kamp lsp = 0; 324946bb7a2SPoul-Henning Kamp for (i = 0; i < j; i++, oidpp++) { 325946bb7a2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number != *name)) 326946bb7a2SPoul-Henning Kamp continue; 327946bb7a2SPoul-Henning Kamp 328946bb7a2SPoul-Henning Kamp if (req->oldidx) 329946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, ".", 1); 330946bb7a2SPoul-Henning Kamp if (!error) 331946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, (*oidpp)->oid_name, 332946bb7a2SPoul-Henning Kamp strlen((*oidpp)->oid_name)); 333946bb7a2SPoul-Henning Kamp if (error) 334946bb7a2SPoul-Henning Kamp return (error); 335946bb7a2SPoul-Henning Kamp 336946bb7a2SPoul-Henning Kamp namelen--; 337946bb7a2SPoul-Henning Kamp name++; 338946bb7a2SPoul-Henning Kamp 339946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 340946bb7a2SPoul-Henning Kamp break; 341946bb7a2SPoul-Henning Kamp 342946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 343946bb7a2SPoul-Henning Kamp break; 344946bb7a2SPoul-Henning Kamp 345946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 346946bb7a2SPoul-Henning Kamp break; 347946bb7a2SPoul-Henning Kamp } 348946bb7a2SPoul-Henning Kamp } 349946bb7a2SPoul-Henning Kamp return (SYSCTL_OUT(req, "", 1)); 350946bb7a2SPoul-Henning Kamp } 351946bb7a2SPoul-Henning Kamp 352946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD, sysctl_sysctl_name, ""); 353946bb7a2SPoul-Henning Kamp 354946bb7a2SPoul-Henning Kamp static int 355946bb7a2SPoul-Henning Kamp sysctl_sysctl_next_ls (struct linker_set *lsp, int *name, u_int namelen, 356946bb7a2SPoul-Henning Kamp int *next, int *len, int level, struct sysctl_oid **oidp) 357946bb7a2SPoul-Henning Kamp { 358946bb7a2SPoul-Henning Kamp int i, j; 359946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 360946bb7a2SPoul-Henning Kamp 361946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 362946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 363946bb7a2SPoul-Henning Kamp *len = level; 364946bb7a2SPoul-Henning Kamp for (i = 0; i < j; i++, oidpp++) { 365946bb7a2SPoul-Henning Kamp if (!*oidpp) 366946bb7a2SPoul-Henning Kamp continue; 367946bb7a2SPoul-Henning Kamp 368946bb7a2SPoul-Henning Kamp *next = (*oidpp)->oid_number; 369946bb7a2SPoul-Henning Kamp *oidp = *oidpp; 370946bb7a2SPoul-Henning Kamp 371946bb7a2SPoul-Henning Kamp if (!namelen) { 372946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 373946bb7a2SPoul-Henning Kamp return 0; 374946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 375946bb7a2SPoul-Henning Kamp /* We really should call the handler here...*/ 376946bb7a2SPoul-Henning Kamp return 0; 377946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 378946bb7a2SPoul-Henning Kamp return (sysctl_sysctl_next_ls (lsp, 0, 0, next+1, 379946bb7a2SPoul-Henning Kamp len, level+1, oidp)); 380946bb7a2SPoul-Henning Kamp } 381946bb7a2SPoul-Henning Kamp 382946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_number < *name) 383946bb7a2SPoul-Henning Kamp continue; 384946bb7a2SPoul-Henning Kamp 385946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_number > *name) { 386946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 387946bb7a2SPoul-Henning Kamp return 0; 388946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 389946bb7a2SPoul-Henning Kamp return 0; 390946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 391946bb7a2SPoul-Henning Kamp if (!sysctl_sysctl_next_ls (lsp, name+1, namelen-1, 392946bb7a2SPoul-Henning Kamp next+1, len, level+1, oidp)) 393946bb7a2SPoul-Henning Kamp return (0); 394946bb7a2SPoul-Henning Kamp namelen = 1; 395946bb7a2SPoul-Henning Kamp *len = level; 396946bb7a2SPoul-Henning Kamp continue; 397946bb7a2SPoul-Henning Kamp } 398946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 399946bb7a2SPoul-Henning Kamp continue; 400946bb7a2SPoul-Henning Kamp 401946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 402946bb7a2SPoul-Henning Kamp continue; 403946bb7a2SPoul-Henning Kamp 404946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 405946bb7a2SPoul-Henning Kamp if (!sysctl_sysctl_next_ls (lsp, name+1, namelen-1, next+1, 406946bb7a2SPoul-Henning Kamp len, level+1, oidp)) 407946bb7a2SPoul-Henning Kamp return (0); 408946bb7a2SPoul-Henning Kamp namelen = 1; 409946bb7a2SPoul-Henning Kamp *len = level; 410946bb7a2SPoul-Henning Kamp } 411946bb7a2SPoul-Henning Kamp return 1; 412946bb7a2SPoul-Henning Kamp } 413946bb7a2SPoul-Henning Kamp 414946bb7a2SPoul-Henning Kamp static int 415946bb7a2SPoul-Henning Kamp sysctl_sysctl_next SYSCTL_HANDLER_ARGS 416946bb7a2SPoul-Henning Kamp { 417946bb7a2SPoul-Henning Kamp int *name = (int *) arg1; 418946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 419946bb7a2SPoul-Henning Kamp int i, j, error; 420946bb7a2SPoul-Henning Kamp struct sysctl_oid *oid; 421946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 422946bb7a2SPoul-Henning Kamp int newoid[CTL_MAXNAME]; 423946bb7a2SPoul-Henning Kamp 424946bb7a2SPoul-Henning Kamp i = sysctl_sysctl_next_ls (lsp, name, namelen, newoid, &j, 1, &oid); 425946bb7a2SPoul-Henning Kamp if (i) 426946bb7a2SPoul-Henning Kamp return ENOENT; 427946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, &oid->oid_kind, sizeof oid->oid_kind); 428946bb7a2SPoul-Henning Kamp if (!error) 429946bb7a2SPoul-Henning Kamp error =SYSCTL_OUT(req, newoid, j * sizeof (int)); 430946bb7a2SPoul-Henning Kamp return (error); 431946bb7a2SPoul-Henning Kamp } 432946bb7a2SPoul-Henning Kamp 433946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, ""); 434946bb7a2SPoul-Henning Kamp 435946bb7a2SPoul-Henning Kamp static int 436946bb7a2SPoul-Henning Kamp name2oid (char *name, int *oid, int *len, struct sysctl_oid **oidp) 437946bb7a2SPoul-Henning Kamp { 438946bb7a2SPoul-Henning Kamp int i, j; 439946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 440946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 441946bb7a2SPoul-Henning Kamp char *p; 442946bb7a2SPoul-Henning Kamp 443946bb7a2SPoul-Henning Kamp if (!*name) 444946bb7a2SPoul-Henning Kamp return ENOENT; 445946bb7a2SPoul-Henning Kamp 446946bb7a2SPoul-Henning Kamp p = name + strlen(name) - 1 ; 447946bb7a2SPoul-Henning Kamp if (*p == '.') 448946bb7a2SPoul-Henning Kamp *p = '\0'; 449946bb7a2SPoul-Henning Kamp 450946bb7a2SPoul-Henning Kamp *len = 0; 451946bb7a2SPoul-Henning Kamp 452946bb7a2SPoul-Henning Kamp for (p = name; *p && *p != '.'; p++) 453946bb7a2SPoul-Henning Kamp ; 454946bb7a2SPoul-Henning Kamp i = *p; 455946bb7a2SPoul-Henning Kamp if (i == '.') 456946bb7a2SPoul-Henning Kamp *p = '\0'; 457946bb7a2SPoul-Henning Kamp 458946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 459946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 460946bb7a2SPoul-Henning Kamp 461946bb7a2SPoul-Henning Kamp while (j-- && *len < CTL_MAXNAME) { 462946bb7a2SPoul-Henning Kamp if (!*oidpp) 463946bb7a2SPoul-Henning Kamp continue; 464946bb7a2SPoul-Henning Kamp if (strcmp(name, (*oidpp)->oid_name)) { 465946bb7a2SPoul-Henning Kamp oidpp++; 466946bb7a2SPoul-Henning Kamp continue; 467946bb7a2SPoul-Henning Kamp } 468946bb7a2SPoul-Henning Kamp *oid++ = (*oidpp)->oid_number; 469946bb7a2SPoul-Henning Kamp (*len)++; 470946bb7a2SPoul-Henning Kamp 471946bb7a2SPoul-Henning Kamp if (!i) { 472946bb7a2SPoul-Henning Kamp if (oidp) 473946bb7a2SPoul-Henning Kamp *oidp = *oidpp; 474946bb7a2SPoul-Henning Kamp return (0); 475946bb7a2SPoul-Henning Kamp } 476946bb7a2SPoul-Henning Kamp 477946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 478946bb7a2SPoul-Henning Kamp break; 479946bb7a2SPoul-Henning Kamp 480946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 481946bb7a2SPoul-Henning Kamp break; 482946bb7a2SPoul-Henning Kamp 483946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 484946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 485946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 486946bb7a2SPoul-Henning Kamp name = p+1; 487946bb7a2SPoul-Henning Kamp for (p = name; *p && *p != '.'; p++) 488946bb7a2SPoul-Henning Kamp ; 489946bb7a2SPoul-Henning Kamp i = *p; 490946bb7a2SPoul-Henning Kamp if (i == '.') 491946bb7a2SPoul-Henning Kamp *p = '\0'; 492946bb7a2SPoul-Henning Kamp } 493946bb7a2SPoul-Henning Kamp return ENOENT; 494946bb7a2SPoul-Henning Kamp } 495946bb7a2SPoul-Henning Kamp 496946bb7a2SPoul-Henning Kamp static int 497946bb7a2SPoul-Henning Kamp sysctl_sysctl_name2oid SYSCTL_HANDLER_ARGS 498946bb7a2SPoul-Henning Kamp { 499946bb7a2SPoul-Henning Kamp char *p; 500946bb7a2SPoul-Henning Kamp int error, oid[CTL_MAXNAME], len; 501946bb7a2SPoul-Henning Kamp struct sysctl_oid *op = 0; 502946bb7a2SPoul-Henning Kamp 503946bb7a2SPoul-Henning Kamp if (!req->newlen) 504946bb7a2SPoul-Henning Kamp return ENOENT; 505946bb7a2SPoul-Henning Kamp 506946bb7a2SPoul-Henning Kamp p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK); 507946bb7a2SPoul-Henning Kamp 508946bb7a2SPoul-Henning Kamp error = SYSCTL_IN(req, p, req->newlen); 509946bb7a2SPoul-Henning Kamp if (error) { 510946bb7a2SPoul-Henning Kamp free(p, M_SYSCTL); 511946bb7a2SPoul-Henning Kamp return (error); 512946bb7a2SPoul-Henning Kamp } 513946bb7a2SPoul-Henning Kamp 514946bb7a2SPoul-Henning Kamp p [req->newlen] = '\0'; 515946bb7a2SPoul-Henning Kamp 516946bb7a2SPoul-Henning Kamp error = name2oid(p, oid, &len, &op); 517946bb7a2SPoul-Henning Kamp 518946bb7a2SPoul-Henning Kamp free(p, M_SYSCTL); 519946bb7a2SPoul-Henning Kamp 520946bb7a2SPoul-Henning Kamp if (error) 521946bb7a2SPoul-Henning Kamp return (error); 522946bb7a2SPoul-Henning Kamp 523946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, &op->oid_kind, sizeof op->oid_kind); 524946bb7a2SPoul-Henning Kamp if (!error) 525946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, oid, len * sizeof *oid); 526946bb7a2SPoul-Henning Kamp return (error); 527946bb7a2SPoul-Henning Kamp } 528946bb7a2SPoul-Henning Kamp 529946bb7a2SPoul-Henning Kamp SYSCTL_PROC(_sysctl, 3, name2oid, CTLFLAG_RW, 0, 0, 530946bb7a2SPoul-Henning Kamp sysctl_sysctl_name2oid, "I", ""); 531946bb7a2SPoul-Henning Kamp 532946bb7a2SPoul-Henning Kamp static int 533946bb7a2SPoul-Henning Kamp sysctl_sysctl_oidfmt SYSCTL_HANDLER_ARGS 534946bb7a2SPoul-Henning Kamp { 535946bb7a2SPoul-Henning Kamp int *name = (int *) arg1; 536946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 537946bb7a2SPoul-Henning Kamp int indx, j; 538946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 539946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 540946bb7a2SPoul-Henning Kamp 541946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 542946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 543946bb7a2SPoul-Henning Kamp 544946bb7a2SPoul-Henning Kamp indx = 0; 545946bb7a2SPoul-Henning Kamp while (j-- && indx < CTL_MAXNAME) { 546946bb7a2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number == name[indx])) { 547946bb7a2SPoul-Henning Kamp indx++; 548946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 549946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 550946bb7a2SPoul-Henning Kamp goto found; 551946bb7a2SPoul-Henning Kamp if (indx == namelen) 552946bb7a2SPoul-Henning Kamp return ENOENT; 553946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 554946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 555946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 556946bb7a2SPoul-Henning Kamp } else { 557946bb7a2SPoul-Henning Kamp if (indx != namelen) 558946bb7a2SPoul-Henning Kamp return EISDIR; 559946bb7a2SPoul-Henning Kamp goto found; 560946bb7a2SPoul-Henning Kamp } 561946bb7a2SPoul-Henning Kamp } else { 562946bb7a2SPoul-Henning Kamp oidpp++; 563946bb7a2SPoul-Henning Kamp } 564946bb7a2SPoul-Henning Kamp } 565946bb7a2SPoul-Henning Kamp return ENOENT; 566946bb7a2SPoul-Henning Kamp found: 567946bb7a2SPoul-Henning Kamp if (!(*oidpp)->oid_fmt) 568946bb7a2SPoul-Henning Kamp return ENOENT; 569946bb7a2SPoul-Henning Kamp return (SYSCTL_OUT(req, (*oidpp)->oid_fmt, 570946bb7a2SPoul-Henning Kamp strlen((*oidpp)->oid_fmt)+1)); 571946bb7a2SPoul-Henning Kamp } 572946bb7a2SPoul-Henning Kamp 573946bb7a2SPoul-Henning Kamp 574946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD, sysctl_sysctl_oidfmt, ""); 575946bb7a2SPoul-Henning Kamp 576946bb7a2SPoul-Henning Kamp /* 577946bb7a2SPoul-Henning Kamp * Default "handler" functions. 578946bb7a2SPoul-Henning Kamp */ 5792e210993SPoul-Henning Kamp 580ae0eb976SPoul-Henning Kamp /* 581ae0eb976SPoul-Henning Kamp * Handle an integer, signed or unsigned. 582ae0eb976SPoul-Henning Kamp * Two cases: 583ae0eb976SPoul-Henning Kamp * a variable: point arg1 at it. 584ae0eb976SPoul-Henning Kamp * a constant: pass it in arg2. 585ae0eb976SPoul-Henning Kamp */ 586ae0eb976SPoul-Henning Kamp 5873a34a5c3SPoul-Henning Kamp int 5883a34a5c3SPoul-Henning Kamp sysctl_handle_int SYSCTL_HANDLER_ARGS 589b396cd83SPoul-Henning Kamp { 590ae0eb976SPoul-Henning Kamp int error = 0; 591b396cd83SPoul-Henning Kamp 592ae0eb976SPoul-Henning Kamp if (arg1) 593ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, sizeof(int)); 594ae0eb976SPoul-Henning Kamp else if (arg2) 595ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, &arg2, sizeof(int)); 596b396cd83SPoul-Henning Kamp 597ae0eb976SPoul-Henning Kamp if (error || !req->newptr) 598ae0eb976SPoul-Henning Kamp return (error); 599b396cd83SPoul-Henning Kamp 600ae0eb976SPoul-Henning Kamp if (!arg1) 601ae0eb976SPoul-Henning Kamp error = EPERM; 602ae0eb976SPoul-Henning Kamp else 603ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, sizeof(int)); 604ae0eb976SPoul-Henning Kamp return (error); 605b396cd83SPoul-Henning Kamp } 606b396cd83SPoul-Henning Kamp 607ae0eb976SPoul-Henning Kamp /* 608ae0eb976SPoul-Henning Kamp * Handle our generic '\0' terminated 'C' string. 609ae0eb976SPoul-Henning Kamp * Two cases: 610ae0eb976SPoul-Henning Kamp * a variable string: point arg1 at it, arg2 is max length. 611ae0eb976SPoul-Henning Kamp * a constant string: point arg1 at it, arg2 is zero. 612ae0eb976SPoul-Henning Kamp */ 613ae0eb976SPoul-Henning Kamp 6143a34a5c3SPoul-Henning Kamp int 6153a34a5c3SPoul-Henning Kamp sysctl_handle_string SYSCTL_HANDLER_ARGS 616b396cd83SPoul-Henning Kamp { 617ae0eb976SPoul-Henning Kamp int error=0; 618b396cd83SPoul-Henning Kamp 619ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, strlen((char *)arg1)+1); 620b396cd83SPoul-Henning Kamp 621deae269aSPoul-Henning Kamp if (error || !req->newptr || !arg2) 622ae0eb976SPoul-Henning Kamp return (error); 623ae0eb976SPoul-Henning Kamp 624ae0eb976SPoul-Henning Kamp if ((req->newlen - req->newidx) > arg2) { 625ae0eb976SPoul-Henning Kamp error = E2BIG; 626ae0eb976SPoul-Henning Kamp } else { 627ae0eb976SPoul-Henning Kamp arg2 = (req->newlen - req->newidx); 628ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, arg2); 629ae0eb976SPoul-Henning Kamp ((char *)arg1)[arg2] = '\0'; 630b396cd83SPoul-Henning Kamp } 631b396cd83SPoul-Henning Kamp 6322e210993SPoul-Henning Kamp return (error); 633b396cd83SPoul-Henning Kamp } 634b396cd83SPoul-Henning Kamp 635ae0eb976SPoul-Henning Kamp /* 636ae0eb976SPoul-Henning Kamp * Handle any kind of opaque data. 637ae0eb976SPoul-Henning Kamp * arg1 points to it, arg2 is the size. 638ae0eb976SPoul-Henning Kamp */ 639ae0eb976SPoul-Henning Kamp 6403a34a5c3SPoul-Henning Kamp int 6413a34a5c3SPoul-Henning Kamp sysctl_handle_opaque SYSCTL_HANDLER_ARGS 642b396cd83SPoul-Henning Kamp { 643ae0eb976SPoul-Henning Kamp int error; 644b396cd83SPoul-Henning Kamp 645ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, arg2); 646b396cd83SPoul-Henning Kamp 647ae0eb976SPoul-Henning Kamp if (error || !req->newptr) 648ae0eb976SPoul-Henning Kamp return (error); 649ae0eb976SPoul-Henning Kamp 650ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, arg2); 651ae0eb976SPoul-Henning Kamp 652ae0eb976SPoul-Henning Kamp return (error); 653b396cd83SPoul-Henning Kamp } 654ae0eb976SPoul-Henning Kamp 655deae269aSPoul-Henning Kamp /* 656deae269aSPoul-Henning Kamp * Transfer functions to/from kernel space. 657deae269aSPoul-Henning Kamp * XXX: rather untested at this point 658deae269aSPoul-Henning Kamp */ 659deae269aSPoul-Henning Kamp static int 660ae0eb976SPoul-Henning Kamp sysctl_old_kernel(struct sysctl_req *req, void *p, int l) 661ae0eb976SPoul-Henning Kamp { 662deae269aSPoul-Henning Kamp int i = 0; 663deae269aSPoul-Henning Kamp 664deae269aSPoul-Henning Kamp if (req->oldptr) { 665deae269aSPoul-Henning Kamp i = min(req->oldlen - req->oldidx, l); 666deae269aSPoul-Henning Kamp if (i > 0) 667ae0eb976SPoul-Henning Kamp bcopy(p, req->oldptr + req->oldidx, i); 668ae0eb976SPoul-Henning Kamp } 669deae269aSPoul-Henning Kamp req->oldidx += l; 670ae0eb976SPoul-Henning Kamp if (i != l) 671ae0eb976SPoul-Henning Kamp return (ENOMEM); 6722e210993SPoul-Henning Kamp return (0); 673ae0eb976SPoul-Henning Kamp 674ae0eb976SPoul-Henning Kamp } 675ae0eb976SPoul-Henning Kamp 676deae269aSPoul-Henning Kamp static int 677ae0eb976SPoul-Henning Kamp sysctl_new_kernel(struct sysctl_req *req, void *p, int l) 678ae0eb976SPoul-Henning Kamp { 679deae269aSPoul-Henning Kamp if (!req->newptr) 680deae269aSPoul-Henning Kamp return 0; 681deae269aSPoul-Henning Kamp if (req->newlen - req->newidx < l) 682ae0eb976SPoul-Henning Kamp return (EINVAL); 683ae0eb976SPoul-Henning Kamp bcopy(req->newptr + req->newidx, p, l); 684ae0eb976SPoul-Henning Kamp req->newidx += l; 685ae0eb976SPoul-Henning Kamp return (0); 686ae0eb976SPoul-Henning Kamp } 687ae0eb976SPoul-Henning Kamp 688deae269aSPoul-Henning Kamp /* 689deae269aSPoul-Henning Kamp * Transfer function to/from user space. 690deae269aSPoul-Henning Kamp */ 691deae269aSPoul-Henning Kamp static int 692ae0eb976SPoul-Henning Kamp sysctl_old_user(struct sysctl_req *req, void *p, int l) 693ae0eb976SPoul-Henning Kamp { 694deae269aSPoul-Henning Kamp int error = 0, i = 0; 695ae0eb976SPoul-Henning Kamp 6964b2af45fSPoul-Henning Kamp if (req->lock == 1 && req->oldptr) { 6974b2af45fSPoul-Henning Kamp vslock(req->oldptr, req->oldlen); 6984b2af45fSPoul-Henning Kamp req->lock = 2; 6994b2af45fSPoul-Henning Kamp } 700deae269aSPoul-Henning Kamp if (req->oldptr) { 701deae269aSPoul-Henning Kamp i = min(req->oldlen - req->oldidx, l); 702deae269aSPoul-Henning Kamp if (i > 0) 703ae0eb976SPoul-Henning Kamp error = copyout(p, req->oldptr + req->oldidx, i); 704deae269aSPoul-Henning Kamp } 705deae269aSPoul-Henning Kamp req->oldidx += l; 706ae0eb976SPoul-Henning Kamp if (error) 707ae0eb976SPoul-Henning Kamp return (error); 708deae269aSPoul-Henning Kamp if (req->oldptr && i < l) 709ae0eb976SPoul-Henning Kamp return (ENOMEM); 710deae269aSPoul-Henning Kamp return (0); 711ae0eb976SPoul-Henning Kamp } 712ae0eb976SPoul-Henning Kamp 713deae269aSPoul-Henning Kamp static int 714ae0eb976SPoul-Henning Kamp sysctl_new_user(struct sysctl_req *req, void *p, int l) 715ae0eb976SPoul-Henning Kamp { 71616cd04a3SPoul-Henning Kamp int error; 717deae269aSPoul-Henning Kamp 718deae269aSPoul-Henning Kamp if (!req->newptr) 719deae269aSPoul-Henning Kamp return 0; 720deae269aSPoul-Henning Kamp if (req->newlen - req->newidx < l) 721ae0eb976SPoul-Henning Kamp return (EINVAL); 722ae0eb976SPoul-Henning Kamp error = copyin(req->newptr + req->newidx, p, l); 723ae0eb976SPoul-Henning Kamp req->newidx += l; 724ae0eb976SPoul-Henning Kamp return (error); 725b396cd83SPoul-Henning Kamp } 726b396cd83SPoul-Henning Kamp 727df8bae1dSRodney W. Grimes /* 7282e210993SPoul-Henning Kamp * Traverse our tree, and find the right node, execute whatever it points 7292e210993SPoul-Henning Kamp * at, and return the resulting error code. 7302e210993SPoul-Henning Kamp */ 7312e210993SPoul-Henning Kamp 7322e210993SPoul-Henning Kamp int 7332e210993SPoul-Henning Kamp sysctl_root SYSCTL_HANDLER_ARGS 7342e210993SPoul-Henning Kamp { 7352e210993SPoul-Henning Kamp int *name = (int *) arg1; 736946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 7372e210993SPoul-Henning Kamp int indx, i, j; 7382e210993SPoul-Henning Kamp struct sysctl_oid **oidpp; 7392e210993SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 7402e210993SPoul-Henning Kamp 7412e210993SPoul-Henning Kamp j = lsp->ls_length; 7422e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 7432e210993SPoul-Henning Kamp 7442e210993SPoul-Henning Kamp indx = 0; 7452e210993SPoul-Henning Kamp while (j-- && indx < CTL_MAXNAME) { 746787d58f2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number == name[indx])) { 7472e210993SPoul-Henning Kamp indx++; 7484b2af45fSPoul-Henning Kamp if ((*oidpp)->oid_kind & CTLFLAG_NOLOCK) 7494b2af45fSPoul-Henning Kamp req->lock = 0; 7502e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 7512e210993SPoul-Henning Kamp if ((*oidpp)->oid_handler) 7522e210993SPoul-Henning Kamp goto found; 7532e210993SPoul-Henning Kamp if (indx == namelen) 7542e210993SPoul-Henning Kamp return ENOENT; 7552e210993SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 7562e210993SPoul-Henning Kamp j = lsp->ls_length; 7572e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 7582e210993SPoul-Henning Kamp } else { 7592e210993SPoul-Henning Kamp if (indx != namelen) 7602e210993SPoul-Henning Kamp return EISDIR; 7612e210993SPoul-Henning Kamp goto found; 7622e210993SPoul-Henning Kamp } 7632e210993SPoul-Henning Kamp } else { 7642e210993SPoul-Henning Kamp oidpp++; 7652e210993SPoul-Henning Kamp } 7662e210993SPoul-Henning Kamp } 767deae269aSPoul-Henning Kamp return ENOENT; 7682e210993SPoul-Henning Kamp found: 7692e210993SPoul-Henning Kamp 7702e210993SPoul-Henning Kamp /* If writing isn't allowed */ 771ae0eb976SPoul-Henning Kamp if (req->newptr && !((*oidpp)->oid_kind & CTLFLAG_WR)) 7722e210993SPoul-Henning Kamp return (EPERM); 7732e210993SPoul-Henning Kamp 7742e210993SPoul-Henning Kamp if (!(*oidpp)->oid_handler) 7752e210993SPoul-Henning Kamp return EINVAL; 7762e210993SPoul-Henning Kamp 7772e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 7782e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 7792e210993SPoul-Henning Kamp name + indx, namelen - indx, 780ae0eb976SPoul-Henning Kamp req); 7812e210993SPoul-Henning Kamp } else { 7822e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 7832e210993SPoul-Henning Kamp (*oidpp)->oid_arg1, (*oidpp)->oid_arg2, 784ae0eb976SPoul-Henning Kamp req); 7852e210993SPoul-Henning Kamp } 7862e210993SPoul-Henning Kamp return (i); 7872e210993SPoul-Henning Kamp } 7882e210993SPoul-Henning Kamp 789d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 790b8da2396SPoul-Henning Kamp struct sysctl_args { 791b8da2396SPoul-Henning Kamp int *name; 792b8da2396SPoul-Henning Kamp u_int namelen; 793b8da2396SPoul-Henning Kamp void *old; 794b8da2396SPoul-Henning Kamp size_t *oldlenp; 795b8da2396SPoul-Henning Kamp void *new; 796b8da2396SPoul-Henning Kamp size_t newlen; 797b8da2396SPoul-Henning Kamp }; 798d2d3e875SBruce Evans #endif 799b8da2396SPoul-Henning Kamp 800df8bae1dSRodney W. Grimes int 8014b2af45fSPoul-Henning Kamp __sysctl(struct proc *p, struct sysctl_args *uap, int *retval) 802df8bae1dSRodney W. Grimes { 803deae269aSPoul-Henning Kamp int error, i, j, name[CTL_MAXNAME]; 804b396cd83SPoul-Henning Kamp 805df8bae1dSRodney W. Grimes if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 806df8bae1dSRodney W. Grimes return (EINVAL); 807b396cd83SPoul-Henning Kamp 808797f2d22SPoul-Henning Kamp error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 809797f2d22SPoul-Henning Kamp if (error) 810df8bae1dSRodney W. Grimes return (error); 811df8bae1dSRodney W. Grimes 812deae269aSPoul-Henning Kamp error = userland_sysctl(p, name, uap->namelen, 813b8da2396SPoul-Henning Kamp uap->old, uap->oldlenp, 0, 814deae269aSPoul-Henning Kamp uap->new, uap->newlen, &j); 815deae269aSPoul-Henning Kamp if (error && error != ENOMEM) 816deae269aSPoul-Henning Kamp return (error); 817deae269aSPoul-Henning Kamp if (uap->oldlenp) { 818deae269aSPoul-Henning Kamp i = copyout(&j, uap->oldlenp, sizeof(j)); 819deae269aSPoul-Henning Kamp if (i) 820deae269aSPoul-Henning Kamp return (i); 821deae269aSPoul-Henning Kamp } 822deae269aSPoul-Henning Kamp return (error); 823b8da2396SPoul-Henning Kamp } 824b8da2396SPoul-Henning Kamp 825b8da2396SPoul-Henning Kamp /* 826b8da2396SPoul-Henning Kamp * This is used from various compatibility syscalls too. That's why name 827b8da2396SPoul-Henning Kamp * must be in kernel space. 828b8da2396SPoul-Henning Kamp */ 829b8da2396SPoul-Henning Kamp int 830b8da2396SPoul-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) 831b8da2396SPoul-Henning Kamp { 8324b2af45fSPoul-Henning Kamp int error = 0; 833ae0eb976SPoul-Henning Kamp struct sysctl_req req; 834ae0eb976SPoul-Henning Kamp 835ae0eb976SPoul-Henning Kamp bzero(&req, sizeof req); 836b8da2396SPoul-Henning Kamp 83716cd04a3SPoul-Henning Kamp req.p = p; 83816cd04a3SPoul-Henning Kamp 839b8da2396SPoul-Henning Kamp if (new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 840b396cd83SPoul-Henning Kamp return (error); 841b396cd83SPoul-Henning Kamp 842b8da2396SPoul-Henning Kamp if (oldlenp) { 843b8da2396SPoul-Henning Kamp if (inkernel) { 844ae0eb976SPoul-Henning Kamp req.oldlen = *oldlenp; 845b8da2396SPoul-Henning Kamp } else { 846deae269aSPoul-Henning Kamp error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp)); 847b8da2396SPoul-Henning Kamp if (error) 848b8da2396SPoul-Henning Kamp return (error); 849b8da2396SPoul-Henning Kamp } 850b8da2396SPoul-Henning Kamp } 851b8da2396SPoul-Henning Kamp 852ae0eb976SPoul-Henning Kamp if (old) { 853ae0eb976SPoul-Henning Kamp if (!useracc(old, req.oldlen, B_WRITE)) 854ae0eb976SPoul-Henning Kamp return (EFAULT); 855ae0eb976SPoul-Henning Kamp req.oldptr= old; 856ae0eb976SPoul-Henning Kamp } 8572e210993SPoul-Henning Kamp 858b8da2396SPoul-Henning Kamp if (newlen) { 859ae0eb976SPoul-Henning Kamp if (!useracc(new, req.newlen, B_READ)) 860ae0eb976SPoul-Henning Kamp return (EFAULT); 861ae0eb976SPoul-Henning Kamp req.newlen = newlen; 862ae0eb976SPoul-Henning Kamp req.newptr = new; 863b396cd83SPoul-Henning Kamp } 864b396cd83SPoul-Henning Kamp 865ae0eb976SPoul-Henning Kamp req.oldfunc = sysctl_old_user; 866ae0eb976SPoul-Henning Kamp req.newfunc = sysctl_new_user; 8674b2af45fSPoul-Henning Kamp req.lock = 1; 8684b2af45fSPoul-Henning Kamp 8694b2af45fSPoul-Henning Kamp /* XXX this should probably be done in a general way */ 8704b2af45fSPoul-Henning Kamp while (memlock.sl_lock) { 8714b2af45fSPoul-Henning Kamp memlock.sl_want = 1; 8724b2af45fSPoul-Henning Kamp (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 8734b2af45fSPoul-Henning Kamp memlock.sl_locked++; 8744b2af45fSPoul-Henning Kamp } 8754b2af45fSPoul-Henning Kamp memlock.sl_lock = 1; 876ae0eb976SPoul-Henning Kamp 877ae0eb976SPoul-Henning Kamp error = sysctl_root(0, name, namelen, &req); 878b396cd83SPoul-Henning Kamp 8794b2af45fSPoul-Henning Kamp if (req.lock == 2) 8804b2af45fSPoul-Henning Kamp vsunlock(req.oldptr, req.oldlen, B_WRITE); 8814b2af45fSPoul-Henning Kamp 8824b2af45fSPoul-Henning Kamp memlock.sl_lock = 0; 8834b2af45fSPoul-Henning Kamp 8844b2af45fSPoul-Henning Kamp if (memlock.sl_want) { 8854b2af45fSPoul-Henning Kamp memlock.sl_want = 0; 8864b2af45fSPoul-Henning Kamp wakeup((caddr_t)&memlock); 8874b2af45fSPoul-Henning Kamp } 8884b2af45fSPoul-Henning Kamp 889deae269aSPoul-Henning Kamp if (error && error != ENOMEM) 890deae269aSPoul-Henning Kamp return (error); 891deae269aSPoul-Henning Kamp 892deae269aSPoul-Henning Kamp if (retval) { 893deae269aSPoul-Henning Kamp if (req.oldptr && req.oldidx > req.oldlen) 894ae0eb976SPoul-Henning Kamp *retval = req.oldlen; 895deae269aSPoul-Henning Kamp else 896deae269aSPoul-Henning Kamp *retval = req.oldidx; 897b8da2396SPoul-Henning Kamp } 8982e210993SPoul-Henning Kamp return (error); 899df8bae1dSRodney W. Grimes } 900df8bae1dSRodney W. Grimes 901df8bae1dSRodney W. Grimes #ifdef COMPAT_43 902df8bae1dSRodney W. Grimes #include <sys/socket.h> 903df8bae1dSRodney W. Grimes #define KINFO_PROC (0<<8) 904df8bae1dSRodney W. Grimes #define KINFO_RT (1<<8) 905df8bae1dSRodney W. Grimes #define KINFO_VNODE (2<<8) 906df8bae1dSRodney W. Grimes #define KINFO_FILE (3<<8) 907df8bae1dSRodney W. Grimes #define KINFO_METER (4<<8) 908df8bae1dSRodney W. Grimes #define KINFO_LOADAVG (5<<8) 909df8bae1dSRodney W. Grimes #define KINFO_CLOCKRATE (6<<8) 910df8bae1dSRodney W. Grimes 9116ece4a51SPeter Wemm /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ 9126ece4a51SPeter Wemm #define KINFO_BSDI_SYSINFO (101<<8) 9136ece4a51SPeter Wemm 9146ece4a51SPeter Wemm /* 9156ece4a51SPeter Wemm * XXX this is bloat, but I hope it's better here than on the potentially 9166ece4a51SPeter Wemm * limited kernel stack... -Peter 9176ece4a51SPeter Wemm */ 9186ece4a51SPeter Wemm 9196ece4a51SPeter Wemm struct { 9206ece4a51SPeter Wemm int bsdi_machine; /* "i386" on BSD/386 */ 9216ece4a51SPeter Wemm /* ^^^ this is an offset to the string, relative to the struct start */ 9226ece4a51SPeter Wemm char *pad0; 9236ece4a51SPeter Wemm long pad1; 9246ece4a51SPeter Wemm long pad2; 9256ece4a51SPeter Wemm long pad3; 9266ece4a51SPeter Wemm u_long pad4; 9276ece4a51SPeter Wemm u_long pad5; 9286ece4a51SPeter Wemm u_long pad6; 9296ece4a51SPeter Wemm 9306ece4a51SPeter Wemm int bsdi_ostype; /* "BSD/386" on BSD/386 */ 9316ece4a51SPeter Wemm int bsdi_osrelease; /* "1.1" on BSD/386 */ 9326ece4a51SPeter Wemm long pad7; 9336ece4a51SPeter Wemm long pad8; 9346ece4a51SPeter Wemm char *pad9; 9356ece4a51SPeter Wemm 9366ece4a51SPeter Wemm long pad10; 9376ece4a51SPeter Wemm long pad11; 9386ece4a51SPeter Wemm int pad12; 9396ece4a51SPeter Wemm long pad13; 9406ece4a51SPeter Wemm quad_t pad14; 9416ece4a51SPeter Wemm long pad15; 9426ece4a51SPeter Wemm 9436ece4a51SPeter Wemm struct timeval pad16; 9446ece4a51SPeter Wemm /* we dont set this, because BSDI's uname used gethostname() instead */ 9456ece4a51SPeter Wemm int bsdi_hostname; /* hostname on BSD/386 */ 9466ece4a51SPeter Wemm 9476ece4a51SPeter Wemm /* the actual string data is appended here */ 9486ece4a51SPeter Wemm 9496ece4a51SPeter Wemm } bsdi_si; 9506ece4a51SPeter Wemm /* 9516ece4a51SPeter Wemm * this data is appended to the end of the bsdi_si structure during copyout. 9526ece4a51SPeter Wemm * The "char *" offsets are relative to the base of the bsdi_si struct. 9536ece4a51SPeter Wemm * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings 9546ece4a51SPeter Wemm * should not exceed the length of the buffer here... (or else!! :-) 9556ece4a51SPeter Wemm */ 9566ece4a51SPeter Wemm char bsdi_strings[80]; /* It had better be less than this! */ 9576ece4a51SPeter Wemm 958d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 959df8bae1dSRodney W. Grimes struct getkerninfo_args { 960df8bae1dSRodney W. Grimes int op; 961df8bae1dSRodney W. Grimes char *where; 962df8bae1dSRodney W. Grimes int *size; 963df8bae1dSRodney W. Grimes int arg; 964df8bae1dSRodney W. Grimes }; 965d2d3e875SBruce Evans #endif 966df8bae1dSRodney W. Grimes 96726f9a767SRodney W. Grimes int 9684b2af45fSPoul-Henning Kamp ogetkerninfo(struct proc *p, struct getkerninfo_args *uap, int *retval) 969df8bae1dSRodney W. Grimes { 970b8da2396SPoul-Henning Kamp int error, name[6]; 971df8bae1dSRodney W. Grimes u_int size; 972df8bae1dSRodney W. Grimes 973df8bae1dSRodney W. Grimes switch (uap->op & 0xff00) { 974df8bae1dSRodney W. Grimes 975df8bae1dSRodney W. Grimes case KINFO_RT: 976b8da2396SPoul-Henning Kamp name[0] = CTL_NET; 977b8da2396SPoul-Henning Kamp name[1] = PF_ROUTE; 978b8da2396SPoul-Henning Kamp name[2] = 0; 979b8da2396SPoul-Henning Kamp name[3] = (uap->op & 0xff0000) >> 16; 980b8da2396SPoul-Henning Kamp name[4] = uap->op & 0xff; 981b8da2396SPoul-Henning Kamp name[5] = uap->arg; 982b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 6, uap->where, uap->size, 9834b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 984df8bae1dSRodney W. Grimes break; 985df8bae1dSRodney W. Grimes 986df8bae1dSRodney W. Grimes case KINFO_VNODE: 987b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 988b8da2396SPoul-Henning Kamp name[1] = KERN_VNODE; 989b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 9904b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 991df8bae1dSRodney W. Grimes break; 992df8bae1dSRodney W. Grimes 993df8bae1dSRodney W. Grimes case KINFO_PROC: 994b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 995b8da2396SPoul-Henning Kamp name[1] = KERN_PROC; 996b8da2396SPoul-Henning Kamp name[2] = uap->op & 0xff; 997b8da2396SPoul-Henning Kamp name[3] = uap->arg; 998b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 4, uap->where, uap->size, 9994b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1000df8bae1dSRodney W. Grimes break; 1001df8bae1dSRodney W. Grimes 1002df8bae1dSRodney W. Grimes case KINFO_FILE: 1003b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1004b8da2396SPoul-Henning Kamp name[1] = KERN_FILE; 1005b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10064b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1007df8bae1dSRodney W. Grimes break; 1008df8bae1dSRodney W. Grimes 1009df8bae1dSRodney W. Grimes case KINFO_METER: 1010b8da2396SPoul-Henning Kamp name[0] = CTL_VM; 1011b8da2396SPoul-Henning Kamp name[1] = VM_METER; 1012b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10134b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1014df8bae1dSRodney W. Grimes break; 1015df8bae1dSRodney W. Grimes 1016df8bae1dSRodney W. Grimes case KINFO_LOADAVG: 1017b8da2396SPoul-Henning Kamp name[0] = CTL_VM; 1018b8da2396SPoul-Henning Kamp name[1] = VM_LOADAVG; 1019b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10204b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1021df8bae1dSRodney W. Grimes break; 1022df8bae1dSRodney W. Grimes 1023df8bae1dSRodney W. Grimes case KINFO_CLOCKRATE: 1024b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1025b8da2396SPoul-Henning Kamp name[1] = KERN_CLOCKRATE; 1026b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10274b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1028df8bae1dSRodney W. Grimes break; 1029df8bae1dSRodney W. Grimes 10306ece4a51SPeter Wemm case KINFO_BSDI_SYSINFO: { 10316ece4a51SPeter Wemm /* 10326ece4a51SPeter Wemm * this is pretty crude, but it's just enough for uname() 10336ece4a51SPeter Wemm * from BSDI's 1.x libc to work. 10346ece4a51SPeter Wemm * 10356ece4a51SPeter Wemm * In particular, it doesn't return the same results when 10366ece4a51SPeter Wemm * the supplied buffer is too small. BSDI's version apparently 10376ece4a51SPeter Wemm * will return the amount copied, and set the *size to how 10386ece4a51SPeter Wemm * much was needed. The emulation framework here isn't capable 10396ece4a51SPeter Wemm * of that, so we just set both to the amount copied. 10406ece4a51SPeter Wemm * BSDI's 2.x product apparently fails with ENOMEM in this 10416ece4a51SPeter Wemm * scenario. 10426ece4a51SPeter Wemm */ 10436ece4a51SPeter Wemm 10446ece4a51SPeter Wemm u_int needed; 10456ece4a51SPeter Wemm u_int left; 10466ece4a51SPeter Wemm char *s; 10476ece4a51SPeter Wemm 10486ece4a51SPeter Wemm bzero((char *)&bsdi_si, sizeof(bsdi_si)); 10496ece4a51SPeter Wemm bzero(bsdi_strings, sizeof(bsdi_strings)); 10506ece4a51SPeter Wemm 10516ece4a51SPeter Wemm s = bsdi_strings; 10526ece4a51SPeter Wemm 10536ece4a51SPeter Wemm bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); 10546ece4a51SPeter Wemm strcpy(s, ostype); 10556ece4a51SPeter Wemm s += strlen(s) + 1; 10566ece4a51SPeter Wemm 10576ece4a51SPeter Wemm bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); 10586ece4a51SPeter Wemm strcpy(s, osrelease); 10596ece4a51SPeter Wemm s += strlen(s) + 1; 10606ece4a51SPeter Wemm 10616ece4a51SPeter Wemm bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); 10626ece4a51SPeter Wemm strcpy(s, machine); 10636ece4a51SPeter Wemm s += strlen(s) + 1; 10646ece4a51SPeter Wemm 10656ece4a51SPeter Wemm needed = sizeof(bsdi_si) + (s - bsdi_strings); 10666ece4a51SPeter Wemm 10676ece4a51SPeter Wemm if (uap->where == NULL) { 10686ece4a51SPeter Wemm /* process is asking how much buffer to supply.. */ 10696ece4a51SPeter Wemm size = needed; 10706ece4a51SPeter Wemm error = 0; 10716ece4a51SPeter Wemm break; 10726ece4a51SPeter Wemm } 10736ece4a51SPeter Wemm 10746ece4a51SPeter Wemm 10756ece4a51SPeter Wemm /* if too much buffer supplied, trim it down */ 10766ece4a51SPeter Wemm if (size > needed) 10776ece4a51SPeter Wemm size = needed; 10786ece4a51SPeter Wemm 10796ece4a51SPeter Wemm /* how much of the buffer is remaining */ 10806ece4a51SPeter Wemm left = size; 10816ece4a51SPeter Wemm 10826ece4a51SPeter Wemm if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) 10836ece4a51SPeter Wemm break; 10846ece4a51SPeter Wemm 10856ece4a51SPeter Wemm /* is there any point in continuing? */ 10866ece4a51SPeter Wemm if (left > sizeof(bsdi_si)) { 10876ece4a51SPeter Wemm left -= sizeof(bsdi_si); 10886ece4a51SPeter Wemm error = copyout(&bsdi_strings, 10896ece4a51SPeter Wemm uap->where + sizeof(bsdi_si), left); 10906ece4a51SPeter Wemm } 10916ece4a51SPeter Wemm break; 10926ece4a51SPeter Wemm } 10936ece4a51SPeter Wemm 1094df8bae1dSRodney W. Grimes default: 1095df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 1096df8bae1dSRodney W. Grimes } 1097df8bae1dSRodney W. Grimes if (error) 1098df8bae1dSRodney W. Grimes return (error); 1099df8bae1dSRodney W. Grimes *retval = size; 1100df8bae1dSRodney W. Grimes if (uap->size) 1101df8bae1dSRodney W. Grimes error = copyout((caddr_t)&size, (caddr_t)uap->size, 1102df8bae1dSRodney W. Grimes sizeof(size)); 1103df8bae1dSRodney W. Grimes return (error); 1104df8bae1dSRodney W. Grimes } 1105df8bae1dSRodney W. Grimes #endif /* COMPAT_43 */ 1106