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 402127f260SArchie Cobbs * $Id: kern_sysctl.c,v 1.78 1998/10/16 03:55:00 peter Exp $ 41df8bae1dSRodney W. Grimes */ 42df8bae1dSRodney W. Grimes 435591b823SEivind Eklund #include "opt_compat.h" 445591b823SEivind Eklund 45df8bae1dSRodney W. Grimes #include <sys/param.h> 464e750649SBruce Evans #include <sys/buf.h> 47df8bae1dSRodney W. Grimes #include <sys/kernel.h> 48df8bae1dSRodney W. Grimes #include <sys/sysctl.h> 49946bb7a2SPoul-Henning Kamp #include <sys/malloc.h> 50efeaf95aSDavid Greenman #include <sys/proc.h> 5145ec3b38SPoul-Henning Kamp #include <sys/systm.h> 5245ec3b38SPoul-Henning Kamp #include <sys/sysproto.h> 534cb03b1bSBruce Evans #include <vm/vm.h> 54efeaf95aSDavid Greenman #include <vm/vm_extern.h> 554cb03b1bSBruce Evans 56a1c995b6SPoul-Henning Kamp static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic"); 5755166637SPoul-Henning Kamp 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 * Initialization of the MIB tree. 73946bb7a2SPoul-Henning Kamp * 74946bb7a2SPoul-Henning Kamp * Order by number in each linker_set. 75946bb7a2SPoul-Henning Kamp */ 764b2af45fSPoul-Henning Kamp 77787d58f2SPoul-Henning Kamp static int 783c8e79ddSBruce Evans sysctl_order_cmp(const void *a, const void *b) 79787d58f2SPoul-Henning Kamp { 803f6a052aSBruce Evans struct sysctl_oid const * const *pa; 813f6a052aSBruce Evans struct sysctl_oid const * const *pb; 823c8e79ddSBruce Evans 833f6a052aSBruce Evans pa = (struct sysctl_oid const * const *)a; 843f6a052aSBruce Evans pb = (struct sysctl_oid const * const *)b; 85aa855a59SPeter Wemm if (*pa == NULL && *pb == NULL) 86aa855a59SPeter Wemm return 0; 873c8e79ddSBruce Evans if (*pa == NULL) 883c8e79ddSBruce Evans return (1); 893c8e79ddSBruce Evans if (*pb == NULL) 903c8e79ddSBruce Evans return (-1); 91787d58f2SPoul-Henning Kamp return ((*pa)->oid_number - (*pb)->oid_number); 92787d58f2SPoul-Henning Kamp } 93787d58f2SPoul-Henning Kamp 94787d58f2SPoul-Henning Kamp static void 95787d58f2SPoul-Henning Kamp sysctl_order(void *arg) 96787d58f2SPoul-Henning Kamp { 97946bb7a2SPoul-Henning Kamp int j, k; 98787d58f2SPoul-Henning Kamp struct linker_set *l = (struct linker_set *) arg; 99787d58f2SPoul-Henning Kamp struct sysctl_oid **oidpp; 100787d58f2SPoul-Henning Kamp 101946bb7a2SPoul-Henning Kamp /* First, find the highest oid we have */ 102946bb7a2SPoul-Henning Kamp j = l->ls_length; 103946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 10461220614SPoul-Henning Kamp for (k = 0; j--; oidpp++) { 105e99ea9ecSBruce Evans if (!*oidpp) 106e99ea9ecSBruce Evans continue; 10761220614SPoul-Henning Kamp if ((*oidpp)->oid_arg1 == arg) { 10861220614SPoul-Henning Kamp *oidpp = 0; 10961220614SPoul-Henning Kamp continue; 11061220614SPoul-Henning Kamp } 111e99ea9ecSBruce Evans if ((*oidpp)->oid_number > k) 112946bb7a2SPoul-Henning Kamp k = (*oidpp)->oid_number; 11361220614SPoul-Henning Kamp } 114946bb7a2SPoul-Henning Kamp 115946bb7a2SPoul-Henning Kamp /* Next, replace all OID_AUTO oids with new numbers */ 116946bb7a2SPoul-Henning Kamp j = l->ls_length; 117946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 118946bb7a2SPoul-Henning Kamp k += 100; 119946bb7a2SPoul-Henning Kamp for (; j--; oidpp++) 120946bb7a2SPoul-Henning Kamp if (*oidpp && (*oidpp)->oid_number == OID_AUTO) 121946bb7a2SPoul-Henning Kamp (*oidpp)->oid_number = k++; 122946bb7a2SPoul-Henning Kamp 123946bb7a2SPoul-Henning Kamp /* Finally: sort by oid */ 124787d58f2SPoul-Henning Kamp j = l->ls_length; 125787d58f2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 126787d58f2SPoul-Henning Kamp for (; j--; oidpp++) { 127787d58f2SPoul-Henning Kamp if (!*oidpp) 128787d58f2SPoul-Henning Kamp continue; 129787d58f2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) 130787d58f2SPoul-Henning Kamp if (!(*oidpp)->oid_handler) 131787d58f2SPoul-Henning Kamp sysctl_order((*oidpp)->oid_arg1); 132787d58f2SPoul-Henning Kamp } 133787d58f2SPoul-Henning Kamp qsort(l->ls_items, l->ls_length, sizeof l->ls_items[0], 134787d58f2SPoul-Henning Kamp sysctl_order_cmp); 135787d58f2SPoul-Henning Kamp } 136787d58f2SPoul-Henning Kamp 137787d58f2SPoul-Henning Kamp SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_order, &sysctl_); 138787d58f2SPoul-Henning Kamp 139e99ea9ecSBruce Evans void 140e99ea9ecSBruce Evans sysctl_order_all(void) 141e99ea9ecSBruce Evans { 142e99ea9ecSBruce Evans sysctl_order(&sysctl_); 143e99ea9ecSBruce Evans } 144e99ea9ecSBruce Evans 145946bb7a2SPoul-Henning Kamp /* 146946bb7a2SPoul-Henning Kamp * "Staff-functions" 147946bb7a2SPoul-Henning Kamp * 14865d0bc13SPoul-Henning Kamp * These functions implement a presently undocumented interface 14965d0bc13SPoul-Henning Kamp * used by the sysctl program to walk the tree, and get the type 15065d0bc13SPoul-Henning Kamp * so it can print the value. 15165d0bc13SPoul-Henning Kamp * This interface is under work and consideration, and should probably 15265d0bc13SPoul-Henning Kamp * be killed with a big axe by the first person who can find the time. 15365d0bc13SPoul-Henning Kamp * (be aware though, that the proper interface isn't as obvious as it 15465d0bc13SPoul-Henning Kamp * may seem, there are various conflicting requirements. 15565d0bc13SPoul-Henning Kamp * 156946bb7a2SPoul-Henning Kamp * {0,0} printf the entire MIB-tree. 157946bb7a2SPoul-Henning Kamp * {0,1,...} return the name of the "..." OID. 158946bb7a2SPoul-Henning Kamp * {0,2,...} return the next OID. 159946bb7a2SPoul-Henning Kamp * {0,3} return the OID of the name in "new" 16065d0bc13SPoul-Henning Kamp * {0,4,...} return the kind & format info for the "..." OID. 161946bb7a2SPoul-Henning Kamp */ 162946bb7a2SPoul-Henning Kamp 163787d58f2SPoul-Henning Kamp static void 164787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node(struct linker_set *l, int i) 165787d58f2SPoul-Henning Kamp { 166787d58f2SPoul-Henning Kamp int j, k; 167787d58f2SPoul-Henning Kamp struct sysctl_oid **oidpp; 168787d58f2SPoul-Henning Kamp 169787d58f2SPoul-Henning Kamp j = l->ls_length; 170787d58f2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 171787d58f2SPoul-Henning Kamp for (; j--; oidpp++) { 172787d58f2SPoul-Henning Kamp 173787d58f2SPoul-Henning Kamp if (!*oidpp) 174787d58f2SPoul-Henning Kamp continue; 175787d58f2SPoul-Henning Kamp 176787d58f2SPoul-Henning Kamp for (k=0; k<i; k++) 177787d58f2SPoul-Henning Kamp printf(" "); 178787d58f2SPoul-Henning Kamp 179787d58f2SPoul-Henning Kamp printf("%d %s ", (*oidpp)->oid_number, (*oidpp)->oid_name); 180787d58f2SPoul-Henning Kamp 181787d58f2SPoul-Henning Kamp printf("%c%c", 182787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind & CTLFLAG_RD ? 'R':' ', 183787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind & CTLFLAG_WR ? 'W':' '); 184787d58f2SPoul-Henning Kamp 18561220614SPoul-Henning Kamp if ((*oidpp)->oid_handler) 18661220614SPoul-Henning Kamp printf(" *Handler"); 18761220614SPoul-Henning Kamp 188787d58f2SPoul-Henning Kamp switch ((*oidpp)->oid_kind & CTLTYPE) { 189787d58f2SPoul-Henning Kamp case CTLTYPE_NODE: 190787d58f2SPoul-Henning Kamp printf(" Node\n"); 19161220614SPoul-Henning Kamp if (!(*oidpp)->oid_handler) { 192787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node( 193787d58f2SPoul-Henning Kamp (*oidpp)->oid_arg1, i+2); 194787d58f2SPoul-Henning Kamp } 195787d58f2SPoul-Henning Kamp break; 196787d58f2SPoul-Henning Kamp case CTLTYPE_INT: printf(" Int\n"); break; 197787d58f2SPoul-Henning Kamp case CTLTYPE_STRING: printf(" String\n"); break; 198787d58f2SPoul-Henning Kamp case CTLTYPE_QUAD: printf(" Quad\n"); break; 199787d58f2SPoul-Henning Kamp case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break; 200787d58f2SPoul-Henning Kamp default: printf("\n"); 201787d58f2SPoul-Henning Kamp } 202787d58f2SPoul-Henning Kamp 203787d58f2SPoul-Henning Kamp } 204787d58f2SPoul-Henning Kamp } 205787d58f2SPoul-Henning Kamp 206787d58f2SPoul-Henning Kamp static int 207787d58f2SPoul-Henning Kamp sysctl_sysctl_debug SYSCTL_HANDLER_ARGS 208787d58f2SPoul-Henning Kamp { 209787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node(&sysctl_, 0); 210787d58f2SPoul-Henning Kamp return ENOENT; 211787d58f2SPoul-Henning Kamp } 212787d58f2SPoul-Henning Kamp 213787d58f2SPoul-Henning Kamp SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD, 214946bb7a2SPoul-Henning Kamp 0, 0, sysctl_sysctl_debug, "-", ""); 2152e210993SPoul-Henning Kamp 216946bb7a2SPoul-Henning Kamp static int 217946bb7a2SPoul-Henning Kamp sysctl_sysctl_name SYSCTL_HANDLER_ARGS 218946bb7a2SPoul-Henning Kamp { 219946bb7a2SPoul-Henning Kamp int *name = (int *) arg1; 220946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 221946bb7a2SPoul-Henning Kamp int i, j, error = 0; 222946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 223946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 224946bb7a2SPoul-Henning Kamp char buf[10]; 2252e210993SPoul-Henning Kamp 226946bb7a2SPoul-Henning Kamp while (namelen) { 227946bb7a2SPoul-Henning Kamp if (!lsp) { 2282127f260SArchie Cobbs snprintf(buf,sizeof(buf),"%d",*name); 229946bb7a2SPoul-Henning Kamp if (req->oldidx) 230946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, ".", 1); 231946bb7a2SPoul-Henning Kamp if (!error) 232946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, buf, strlen(buf)); 233946bb7a2SPoul-Henning Kamp if (error) 234946bb7a2SPoul-Henning Kamp return (error); 235946bb7a2SPoul-Henning Kamp namelen--; 236946bb7a2SPoul-Henning Kamp name++; 237946bb7a2SPoul-Henning Kamp continue; 238946bb7a2SPoul-Henning Kamp } 239946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 240946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 241946bb7a2SPoul-Henning Kamp lsp = 0; 242946bb7a2SPoul-Henning Kamp for (i = 0; i < j; i++, oidpp++) { 243946bb7a2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number != *name)) 244946bb7a2SPoul-Henning Kamp continue; 245946bb7a2SPoul-Henning Kamp 246946bb7a2SPoul-Henning Kamp if (req->oldidx) 247946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, ".", 1); 248946bb7a2SPoul-Henning Kamp if (!error) 249946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, (*oidpp)->oid_name, 250946bb7a2SPoul-Henning Kamp strlen((*oidpp)->oid_name)); 251946bb7a2SPoul-Henning Kamp if (error) 252946bb7a2SPoul-Henning Kamp return (error); 253946bb7a2SPoul-Henning Kamp 254946bb7a2SPoul-Henning Kamp namelen--; 255946bb7a2SPoul-Henning Kamp name++; 256946bb7a2SPoul-Henning Kamp 257946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 258946bb7a2SPoul-Henning Kamp break; 259946bb7a2SPoul-Henning Kamp 260946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 261946bb7a2SPoul-Henning Kamp break; 262946bb7a2SPoul-Henning Kamp 263946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 264946bb7a2SPoul-Henning Kamp break; 265946bb7a2SPoul-Henning Kamp } 266946bb7a2SPoul-Henning Kamp } 267946bb7a2SPoul-Henning Kamp return (SYSCTL_OUT(req, "", 1)); 268946bb7a2SPoul-Henning Kamp } 269946bb7a2SPoul-Henning Kamp 270946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD, sysctl_sysctl_name, ""); 271946bb7a2SPoul-Henning Kamp 272946bb7a2SPoul-Henning Kamp static int 273946bb7a2SPoul-Henning Kamp sysctl_sysctl_next_ls (struct linker_set *lsp, int *name, u_int namelen, 274946bb7a2SPoul-Henning Kamp int *next, int *len, int level, struct sysctl_oid **oidp) 275946bb7a2SPoul-Henning Kamp { 276946bb7a2SPoul-Henning Kamp int i, j; 277946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 278946bb7a2SPoul-Henning Kamp 279946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 280946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 281946bb7a2SPoul-Henning Kamp *len = level; 282946bb7a2SPoul-Henning Kamp for (i = 0; i < j; i++, oidpp++) { 283946bb7a2SPoul-Henning Kamp if (!*oidpp) 284946bb7a2SPoul-Henning Kamp continue; 285946bb7a2SPoul-Henning Kamp 286946bb7a2SPoul-Henning Kamp *next = (*oidpp)->oid_number; 287946bb7a2SPoul-Henning Kamp *oidp = *oidpp; 288946bb7a2SPoul-Henning Kamp 289946bb7a2SPoul-Henning Kamp if (!namelen) { 290946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 291946bb7a2SPoul-Henning Kamp return 0; 292946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 293946bb7a2SPoul-Henning Kamp /* We really should call the handler here...*/ 294946bb7a2SPoul-Henning Kamp return 0; 295946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 29661220614SPoul-Henning Kamp if (!sysctl_sysctl_next_ls (lsp, 0, 0, next+1, 29761220614SPoul-Henning Kamp len, level+1, oidp)) 29861220614SPoul-Henning Kamp return 0; 29961220614SPoul-Henning Kamp goto next; 300946bb7a2SPoul-Henning Kamp } 301946bb7a2SPoul-Henning Kamp 302946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_number < *name) 303946bb7a2SPoul-Henning Kamp continue; 304946bb7a2SPoul-Henning Kamp 305946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_number > *name) { 306946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 307946bb7a2SPoul-Henning Kamp return 0; 308946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 309946bb7a2SPoul-Henning Kamp return 0; 310946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 311946bb7a2SPoul-Henning Kamp if (!sysctl_sysctl_next_ls (lsp, name+1, namelen-1, 312946bb7a2SPoul-Henning Kamp next+1, len, level+1, oidp)) 313946bb7a2SPoul-Henning Kamp return (0); 31461220614SPoul-Henning Kamp goto next; 315946bb7a2SPoul-Henning Kamp } 316946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 317946bb7a2SPoul-Henning Kamp continue; 318946bb7a2SPoul-Henning Kamp 319946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 320946bb7a2SPoul-Henning Kamp continue; 321946bb7a2SPoul-Henning Kamp 322946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 323946bb7a2SPoul-Henning Kamp if (!sysctl_sysctl_next_ls (lsp, name+1, namelen-1, next+1, 324946bb7a2SPoul-Henning Kamp len, level+1, oidp)) 325946bb7a2SPoul-Henning Kamp return (0); 32661220614SPoul-Henning Kamp next: 327946bb7a2SPoul-Henning Kamp namelen = 1; 328946bb7a2SPoul-Henning Kamp *len = level; 329946bb7a2SPoul-Henning Kamp } 330946bb7a2SPoul-Henning Kamp return 1; 331946bb7a2SPoul-Henning Kamp } 332946bb7a2SPoul-Henning Kamp 333946bb7a2SPoul-Henning Kamp static int 334946bb7a2SPoul-Henning Kamp sysctl_sysctl_next SYSCTL_HANDLER_ARGS 335946bb7a2SPoul-Henning Kamp { 336946bb7a2SPoul-Henning Kamp int *name = (int *) arg1; 337946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 338946bb7a2SPoul-Henning Kamp int i, j, error; 339946bb7a2SPoul-Henning Kamp struct sysctl_oid *oid; 340946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 341946bb7a2SPoul-Henning Kamp int newoid[CTL_MAXNAME]; 342946bb7a2SPoul-Henning Kamp 343946bb7a2SPoul-Henning Kamp i = sysctl_sysctl_next_ls (lsp, name, namelen, newoid, &j, 1, &oid); 344946bb7a2SPoul-Henning Kamp if (i) 345946bb7a2SPoul-Henning Kamp return ENOENT; 346946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, newoid, j * sizeof (int)); 347946bb7a2SPoul-Henning Kamp return (error); 348946bb7a2SPoul-Henning Kamp } 349946bb7a2SPoul-Henning Kamp 350946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, ""); 351946bb7a2SPoul-Henning Kamp 352946bb7a2SPoul-Henning Kamp static int 353946bb7a2SPoul-Henning Kamp name2oid (char *name, int *oid, int *len, struct sysctl_oid **oidp) 354946bb7a2SPoul-Henning Kamp { 355946bb7a2SPoul-Henning Kamp int i, j; 356946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 357946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 358946bb7a2SPoul-Henning Kamp char *p; 359946bb7a2SPoul-Henning Kamp 360946bb7a2SPoul-Henning Kamp if (!*name) 361946bb7a2SPoul-Henning Kamp return ENOENT; 362946bb7a2SPoul-Henning Kamp 363946bb7a2SPoul-Henning Kamp p = name + strlen(name) - 1 ; 364946bb7a2SPoul-Henning Kamp if (*p == '.') 365946bb7a2SPoul-Henning Kamp *p = '\0'; 366946bb7a2SPoul-Henning Kamp 367946bb7a2SPoul-Henning Kamp *len = 0; 368946bb7a2SPoul-Henning Kamp 369946bb7a2SPoul-Henning Kamp for (p = name; *p && *p != '.'; p++) 370946bb7a2SPoul-Henning Kamp ; 371946bb7a2SPoul-Henning Kamp i = *p; 372946bb7a2SPoul-Henning Kamp if (i == '.') 373946bb7a2SPoul-Henning Kamp *p = '\0'; 374946bb7a2SPoul-Henning Kamp 375946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 376946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 377946bb7a2SPoul-Henning Kamp 378946bb7a2SPoul-Henning Kamp while (j-- && *len < CTL_MAXNAME) { 379946bb7a2SPoul-Henning Kamp if (!*oidpp) 380946bb7a2SPoul-Henning Kamp continue; 381946bb7a2SPoul-Henning Kamp if (strcmp(name, (*oidpp)->oid_name)) { 382946bb7a2SPoul-Henning Kamp oidpp++; 383946bb7a2SPoul-Henning Kamp continue; 384946bb7a2SPoul-Henning Kamp } 385946bb7a2SPoul-Henning Kamp *oid++ = (*oidpp)->oid_number; 386946bb7a2SPoul-Henning Kamp (*len)++; 387946bb7a2SPoul-Henning Kamp 388946bb7a2SPoul-Henning Kamp if (!i) { 389946bb7a2SPoul-Henning Kamp if (oidp) 390946bb7a2SPoul-Henning Kamp *oidp = *oidpp; 391946bb7a2SPoul-Henning Kamp return (0); 392946bb7a2SPoul-Henning Kamp } 393946bb7a2SPoul-Henning Kamp 394946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 395946bb7a2SPoul-Henning Kamp break; 396946bb7a2SPoul-Henning Kamp 397946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 398946bb7a2SPoul-Henning Kamp break; 399946bb7a2SPoul-Henning Kamp 400946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 401946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 402946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 403946bb7a2SPoul-Henning Kamp name = p+1; 404946bb7a2SPoul-Henning Kamp for (p = name; *p && *p != '.'; p++) 405946bb7a2SPoul-Henning Kamp ; 406946bb7a2SPoul-Henning Kamp i = *p; 407946bb7a2SPoul-Henning Kamp if (i == '.') 408946bb7a2SPoul-Henning Kamp *p = '\0'; 409946bb7a2SPoul-Henning Kamp } 410946bb7a2SPoul-Henning Kamp return ENOENT; 411946bb7a2SPoul-Henning Kamp } 412946bb7a2SPoul-Henning Kamp 413946bb7a2SPoul-Henning Kamp static int 414946bb7a2SPoul-Henning Kamp sysctl_sysctl_name2oid SYSCTL_HANDLER_ARGS 415946bb7a2SPoul-Henning Kamp { 416946bb7a2SPoul-Henning Kamp char *p; 417946bb7a2SPoul-Henning Kamp int error, oid[CTL_MAXNAME], len; 418946bb7a2SPoul-Henning Kamp struct sysctl_oid *op = 0; 419946bb7a2SPoul-Henning Kamp 420946bb7a2SPoul-Henning Kamp if (!req->newlen) 421946bb7a2SPoul-Henning Kamp return ENOENT; 422946bb7a2SPoul-Henning Kamp 423946bb7a2SPoul-Henning Kamp p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK); 424946bb7a2SPoul-Henning Kamp 425946bb7a2SPoul-Henning Kamp error = SYSCTL_IN(req, p, req->newlen); 426946bb7a2SPoul-Henning Kamp if (error) { 427946bb7a2SPoul-Henning Kamp free(p, M_SYSCTL); 428946bb7a2SPoul-Henning Kamp return (error); 429946bb7a2SPoul-Henning Kamp } 430946bb7a2SPoul-Henning Kamp 431946bb7a2SPoul-Henning Kamp p [req->newlen] = '\0'; 432946bb7a2SPoul-Henning Kamp 433946bb7a2SPoul-Henning Kamp error = name2oid(p, oid, &len, &op); 434946bb7a2SPoul-Henning Kamp 435946bb7a2SPoul-Henning Kamp free(p, M_SYSCTL); 436946bb7a2SPoul-Henning Kamp 437946bb7a2SPoul-Henning Kamp if (error) 438946bb7a2SPoul-Henning Kamp return (error); 439946bb7a2SPoul-Henning Kamp 440946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, oid, len * sizeof *oid); 441946bb7a2SPoul-Henning Kamp return (error); 442946bb7a2SPoul-Henning Kamp } 443946bb7a2SPoul-Henning Kamp 4443ac9f819SPoul-Henning Kamp SYSCTL_PROC(_sysctl, 3, name2oid, CTLFLAG_RW|CTLFLAG_ANYBODY, 0, 0, 445946bb7a2SPoul-Henning Kamp sysctl_sysctl_name2oid, "I", ""); 446946bb7a2SPoul-Henning Kamp 447946bb7a2SPoul-Henning Kamp static int 448946bb7a2SPoul-Henning Kamp sysctl_sysctl_oidfmt SYSCTL_HANDLER_ARGS 449946bb7a2SPoul-Henning Kamp { 45065d0bc13SPoul-Henning Kamp int *name = (int *) arg1, error; 451946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 452946bb7a2SPoul-Henning Kamp int indx, j; 453946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 454946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 455946bb7a2SPoul-Henning Kamp 456946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 457946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 458946bb7a2SPoul-Henning Kamp 459946bb7a2SPoul-Henning Kamp indx = 0; 460946bb7a2SPoul-Henning Kamp while (j-- && indx < CTL_MAXNAME) { 461946bb7a2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number == name[indx])) { 462946bb7a2SPoul-Henning Kamp indx++; 463946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 464946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 465946bb7a2SPoul-Henning Kamp goto found; 466946bb7a2SPoul-Henning Kamp if (indx == namelen) 46765d0bc13SPoul-Henning Kamp goto found; 468946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 469946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 470946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 471946bb7a2SPoul-Henning Kamp } else { 472946bb7a2SPoul-Henning Kamp if (indx != namelen) 473946bb7a2SPoul-Henning Kamp return EISDIR; 474946bb7a2SPoul-Henning Kamp goto found; 475946bb7a2SPoul-Henning Kamp } 476946bb7a2SPoul-Henning Kamp } else { 477946bb7a2SPoul-Henning Kamp oidpp++; 478946bb7a2SPoul-Henning Kamp } 479946bb7a2SPoul-Henning Kamp } 480946bb7a2SPoul-Henning Kamp return ENOENT; 481946bb7a2SPoul-Henning Kamp found: 482946bb7a2SPoul-Henning Kamp if (!(*oidpp)->oid_fmt) 483946bb7a2SPoul-Henning Kamp return ENOENT; 48465d0bc13SPoul-Henning Kamp error = SYSCTL_OUT(req, 48565d0bc13SPoul-Henning Kamp &(*oidpp)->oid_kind, sizeof((*oidpp)->oid_kind)); 48665d0bc13SPoul-Henning Kamp if (!error) 48765d0bc13SPoul-Henning Kamp error = SYSCTL_OUT(req, (*oidpp)->oid_fmt, 48865d0bc13SPoul-Henning Kamp strlen((*oidpp)->oid_fmt)+1); 48965d0bc13SPoul-Henning Kamp return (error); 490946bb7a2SPoul-Henning Kamp } 491946bb7a2SPoul-Henning Kamp 492946bb7a2SPoul-Henning Kamp 493946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD, sysctl_sysctl_oidfmt, ""); 494946bb7a2SPoul-Henning Kamp 495946bb7a2SPoul-Henning Kamp /* 496946bb7a2SPoul-Henning Kamp * Default "handler" functions. 497946bb7a2SPoul-Henning Kamp */ 4982e210993SPoul-Henning Kamp 499ae0eb976SPoul-Henning Kamp /* 500ae0eb976SPoul-Henning Kamp * Handle an integer, signed or unsigned. 501ae0eb976SPoul-Henning Kamp * Two cases: 502ae0eb976SPoul-Henning Kamp * a variable: point arg1 at it. 503ae0eb976SPoul-Henning Kamp * a constant: pass it in arg2. 504ae0eb976SPoul-Henning Kamp */ 505ae0eb976SPoul-Henning Kamp 5063a34a5c3SPoul-Henning Kamp int 5073a34a5c3SPoul-Henning Kamp sysctl_handle_int SYSCTL_HANDLER_ARGS 508b396cd83SPoul-Henning Kamp { 509ae0eb976SPoul-Henning Kamp int error = 0; 510b396cd83SPoul-Henning Kamp 511ae0eb976SPoul-Henning Kamp if (arg1) 512ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, sizeof(int)); 5131fbf1f71SBruce Evans else 514ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, &arg2, sizeof(int)); 515b396cd83SPoul-Henning Kamp 516ae0eb976SPoul-Henning Kamp if (error || !req->newptr) 517ae0eb976SPoul-Henning Kamp return (error); 518b396cd83SPoul-Henning Kamp 519ae0eb976SPoul-Henning Kamp if (!arg1) 520ae0eb976SPoul-Henning Kamp error = EPERM; 521ae0eb976SPoul-Henning Kamp else 522ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, sizeof(int)); 523ae0eb976SPoul-Henning Kamp return (error); 524b396cd83SPoul-Henning Kamp } 525b396cd83SPoul-Henning Kamp 526ae0eb976SPoul-Henning Kamp /* 527069e9bc1SDoug Rabson * Handle an integer, signed or unsigned. 528069e9bc1SDoug Rabson * Two cases: 529069e9bc1SDoug Rabson * a variable: point arg1 at it. 530069e9bc1SDoug Rabson * a constant: pass it in arg2. 531069e9bc1SDoug Rabson */ 532069e9bc1SDoug Rabson 533069e9bc1SDoug Rabson int 534069e9bc1SDoug Rabson sysctl_handle_long SYSCTL_HANDLER_ARGS 535069e9bc1SDoug Rabson { 536069e9bc1SDoug Rabson int error = 0; 537069e9bc1SDoug Rabson 538069e9bc1SDoug Rabson if (arg1) 539069e9bc1SDoug Rabson error = SYSCTL_OUT(req, arg1, sizeof(long)); 540069e9bc1SDoug Rabson else 541069e9bc1SDoug Rabson error = SYSCTL_OUT(req, &arg2, sizeof(long)); 542069e9bc1SDoug Rabson 543069e9bc1SDoug Rabson if (error || !req->newptr) 544069e9bc1SDoug Rabson return (error); 545069e9bc1SDoug Rabson 546069e9bc1SDoug Rabson if (!arg1) 547069e9bc1SDoug Rabson error = EPERM; 548069e9bc1SDoug Rabson else 549069e9bc1SDoug Rabson error = SYSCTL_IN(req, arg1, sizeof(long)); 550069e9bc1SDoug Rabson return (error); 551069e9bc1SDoug Rabson } 552069e9bc1SDoug Rabson 553069e9bc1SDoug Rabson /* 554069e9bc1SDoug Rabson * Handle an integer, signed or unsigned. 555069e9bc1SDoug Rabson * Two cases: 556069e9bc1SDoug Rabson * a variable: point arg1 at it. 557069e9bc1SDoug Rabson * a constant: pass it in arg2. 558069e9bc1SDoug Rabson */ 559069e9bc1SDoug Rabson 560069e9bc1SDoug Rabson int 561069e9bc1SDoug Rabson sysctl_handle_intptr SYSCTL_HANDLER_ARGS 562069e9bc1SDoug Rabson { 563069e9bc1SDoug Rabson int error = 0; 564069e9bc1SDoug Rabson 565069e9bc1SDoug Rabson if (arg1) 566069e9bc1SDoug Rabson error = SYSCTL_OUT(req, arg1, sizeof(intptr_t)); 567069e9bc1SDoug Rabson else 568069e9bc1SDoug Rabson error = SYSCTL_OUT(req, &arg2, sizeof(intptr_t)); 569069e9bc1SDoug Rabson 570069e9bc1SDoug Rabson if (error || !req->newptr) 571069e9bc1SDoug Rabson return (error); 572069e9bc1SDoug Rabson 573069e9bc1SDoug Rabson if (!arg1) 574069e9bc1SDoug Rabson error = EPERM; 575069e9bc1SDoug Rabson else 576069e9bc1SDoug Rabson error = SYSCTL_IN(req, arg1, sizeof(intptr_t)); 577069e9bc1SDoug Rabson return (error); 578069e9bc1SDoug Rabson } 579069e9bc1SDoug Rabson 580069e9bc1SDoug Rabson /* 581ae0eb976SPoul-Henning Kamp * Handle our generic '\0' terminated 'C' string. 582ae0eb976SPoul-Henning Kamp * Two cases: 583ae0eb976SPoul-Henning Kamp * a variable string: point arg1 at it, arg2 is max length. 584ae0eb976SPoul-Henning Kamp * a constant string: point arg1 at it, arg2 is zero. 585ae0eb976SPoul-Henning Kamp */ 586ae0eb976SPoul-Henning Kamp 5873a34a5c3SPoul-Henning Kamp int 5883a34a5c3SPoul-Henning Kamp sysctl_handle_string SYSCTL_HANDLER_ARGS 589b396cd83SPoul-Henning Kamp { 590ae0eb976SPoul-Henning Kamp int error=0; 591b396cd83SPoul-Henning Kamp 592ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, strlen((char *)arg1)+1); 593b396cd83SPoul-Henning Kamp 594deae269aSPoul-Henning Kamp if (error || !req->newptr || !arg2) 595ae0eb976SPoul-Henning Kamp return (error); 596ae0eb976SPoul-Henning Kamp 597ae0eb976SPoul-Henning Kamp if ((req->newlen - req->newidx) > arg2) { 598ae0eb976SPoul-Henning Kamp error = E2BIG; 599ae0eb976SPoul-Henning Kamp } else { 600ae0eb976SPoul-Henning Kamp arg2 = (req->newlen - req->newidx); 601ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, arg2); 602ae0eb976SPoul-Henning Kamp ((char *)arg1)[arg2] = '\0'; 603b396cd83SPoul-Henning Kamp } 604b396cd83SPoul-Henning Kamp 6052e210993SPoul-Henning Kamp return (error); 606b396cd83SPoul-Henning Kamp } 607b396cd83SPoul-Henning Kamp 608ae0eb976SPoul-Henning Kamp /* 609ae0eb976SPoul-Henning Kamp * Handle any kind of opaque data. 610ae0eb976SPoul-Henning Kamp * arg1 points to it, arg2 is the size. 611ae0eb976SPoul-Henning Kamp */ 612ae0eb976SPoul-Henning Kamp 6133a34a5c3SPoul-Henning Kamp int 6143a34a5c3SPoul-Henning Kamp sysctl_handle_opaque SYSCTL_HANDLER_ARGS 615b396cd83SPoul-Henning Kamp { 616ae0eb976SPoul-Henning Kamp int error; 617b396cd83SPoul-Henning Kamp 618ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, arg2); 619b396cd83SPoul-Henning Kamp 620ae0eb976SPoul-Henning Kamp if (error || !req->newptr) 621ae0eb976SPoul-Henning Kamp return (error); 622ae0eb976SPoul-Henning Kamp 623ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, arg2); 624ae0eb976SPoul-Henning Kamp 625ae0eb976SPoul-Henning Kamp return (error); 626b396cd83SPoul-Henning Kamp } 627ae0eb976SPoul-Henning Kamp 628deae269aSPoul-Henning Kamp /* 629deae269aSPoul-Henning Kamp * Transfer functions to/from kernel space. 630deae269aSPoul-Henning Kamp * XXX: rather untested at this point 631deae269aSPoul-Henning Kamp */ 632deae269aSPoul-Henning Kamp static int 633069e9bc1SDoug Rabson sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l) 634ae0eb976SPoul-Henning Kamp { 635069e9bc1SDoug Rabson size_t i = 0; 636deae269aSPoul-Henning Kamp 637deae269aSPoul-Henning Kamp if (req->oldptr) { 638069e9bc1SDoug Rabson i = l; 639069e9bc1SDoug Rabson if (i > req->oldlen - req->oldidx) 640069e9bc1SDoug Rabson i = req->oldlen - req->oldidx; 641deae269aSPoul-Henning Kamp if (i > 0) 64209a8dfa2SBruce Evans bcopy(p, (char *)req->oldptr + req->oldidx, i); 643ae0eb976SPoul-Henning Kamp } 644deae269aSPoul-Henning Kamp req->oldidx += l; 6451c346c70SNate Williams if (req->oldptr && i != l) 646ae0eb976SPoul-Henning Kamp return (ENOMEM); 6472e210993SPoul-Henning Kamp return (0); 648ae0eb976SPoul-Henning Kamp } 649ae0eb976SPoul-Henning Kamp 650deae269aSPoul-Henning Kamp static int 651069e9bc1SDoug Rabson sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l) 652ae0eb976SPoul-Henning Kamp { 653deae269aSPoul-Henning Kamp if (!req->newptr) 654deae269aSPoul-Henning Kamp return 0; 655deae269aSPoul-Henning Kamp if (req->newlen - req->newidx < l) 656ae0eb976SPoul-Henning Kamp return (EINVAL); 65709a8dfa2SBruce Evans bcopy((char *)req->newptr + req->newidx, p, l); 658ae0eb976SPoul-Henning Kamp req->newidx += l; 659ae0eb976SPoul-Henning Kamp return (0); 660ae0eb976SPoul-Henning Kamp } 661ae0eb976SPoul-Henning Kamp 6621c346c70SNate Williams int 663069e9bc1SDoug Rabson kernel_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen, size_t *retval) 6641c346c70SNate Williams { 6651c346c70SNate Williams int error = 0; 6661c346c70SNate Williams struct sysctl_req req; 6671c346c70SNate Williams 6681c346c70SNate Williams bzero(&req, sizeof req); 6691c346c70SNate Williams 6701c346c70SNate Williams req.p = p; 6711c346c70SNate Williams 6721c346c70SNate Williams if (oldlenp) { 6731c346c70SNate Williams req.oldlen = *oldlenp; 6741c346c70SNate Williams } 6751c346c70SNate Williams 6761c346c70SNate Williams if (old) { 6771c346c70SNate Williams req.oldptr= old; 6781c346c70SNate Williams } 6791c346c70SNate Williams 6801c346c70SNate Williams if (newlen) { 6811c346c70SNate Williams req.newlen = newlen; 6821c346c70SNate Williams req.newptr = new; 6831c346c70SNate Williams } 6841c346c70SNate Williams 6851c346c70SNate Williams req.oldfunc = sysctl_old_kernel; 6861c346c70SNate Williams req.newfunc = sysctl_new_kernel; 6871c346c70SNate Williams req.lock = 1; 6881c346c70SNate Williams 6891c346c70SNate Williams /* XXX this should probably be done in a general way */ 6901c346c70SNate Williams while (memlock.sl_lock) { 6911c346c70SNate Williams memlock.sl_want = 1; 6921c346c70SNate Williams (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 6931c346c70SNate Williams memlock.sl_locked++; 6941c346c70SNate Williams } 6951c346c70SNate Williams memlock.sl_lock = 1; 6961c346c70SNate Williams 6971c346c70SNate Williams error = sysctl_root(0, name, namelen, &req); 6981c346c70SNate Williams 6991c346c70SNate Williams if (req.lock == 2) 7001c346c70SNate Williams vsunlock(req.oldptr, req.oldlen, B_WRITE); 7011c346c70SNate Williams 7021c346c70SNate Williams memlock.sl_lock = 0; 7031c346c70SNate Williams 7041c346c70SNate Williams if (memlock.sl_want) { 7051c346c70SNate Williams memlock.sl_want = 0; 7061c346c70SNate Williams wakeup((caddr_t)&memlock); 7071c346c70SNate Williams } 7081c346c70SNate Williams 7091c346c70SNate Williams if (error && error != ENOMEM) 7101c346c70SNate Williams return (error); 7111c346c70SNate Williams 7121c346c70SNate Williams if (retval) { 7131c346c70SNate Williams if (req.oldptr && req.oldidx > req.oldlen) 7141c346c70SNate Williams *retval = req.oldlen; 7151c346c70SNate Williams else 7161c346c70SNate Williams *retval = req.oldidx; 7171c346c70SNate Williams } 7181c346c70SNate Williams return (error); 7191c346c70SNate Williams } 7201c346c70SNate Williams 721deae269aSPoul-Henning Kamp /* 722deae269aSPoul-Henning Kamp * Transfer function to/from user space. 723deae269aSPoul-Henning Kamp */ 724deae269aSPoul-Henning Kamp static int 725069e9bc1SDoug Rabson sysctl_old_user(struct sysctl_req *req, const void *p, size_t l) 726ae0eb976SPoul-Henning Kamp { 727069e9bc1SDoug Rabson int error = 0; 728069e9bc1SDoug Rabson size_t i = 0; 729ae0eb976SPoul-Henning Kamp 7304b2af45fSPoul-Henning Kamp if (req->lock == 1 && req->oldptr) { 7314b2af45fSPoul-Henning Kamp vslock(req->oldptr, req->oldlen); 7324b2af45fSPoul-Henning Kamp req->lock = 2; 7334b2af45fSPoul-Henning Kamp } 734deae269aSPoul-Henning Kamp if (req->oldptr) { 735069e9bc1SDoug Rabson i = l; 736069e9bc1SDoug Rabson if (i > req->oldlen - req->oldidx) 737069e9bc1SDoug Rabson i = req->oldlen - req->oldidx; 738deae269aSPoul-Henning Kamp if (i > 0) 73909a8dfa2SBruce Evans error = copyout(p, (char *)req->oldptr + req->oldidx, 74009a8dfa2SBruce Evans i); 741deae269aSPoul-Henning Kamp } 742deae269aSPoul-Henning Kamp req->oldidx += l; 743ae0eb976SPoul-Henning Kamp if (error) 744ae0eb976SPoul-Henning Kamp return (error); 745deae269aSPoul-Henning Kamp if (req->oldptr && i < l) 746ae0eb976SPoul-Henning Kamp return (ENOMEM); 747deae269aSPoul-Henning Kamp return (0); 748ae0eb976SPoul-Henning Kamp } 749ae0eb976SPoul-Henning Kamp 750deae269aSPoul-Henning Kamp static int 751069e9bc1SDoug Rabson sysctl_new_user(struct sysctl_req *req, void *p, size_t l) 752ae0eb976SPoul-Henning Kamp { 75316cd04a3SPoul-Henning Kamp int error; 754deae269aSPoul-Henning Kamp 755deae269aSPoul-Henning Kamp if (!req->newptr) 756deae269aSPoul-Henning Kamp return 0; 757deae269aSPoul-Henning Kamp if (req->newlen - req->newidx < l) 758ae0eb976SPoul-Henning Kamp return (EINVAL); 75909a8dfa2SBruce Evans error = copyin((char *)req->newptr + req->newidx, p, l); 760ae0eb976SPoul-Henning Kamp req->newidx += l; 761ae0eb976SPoul-Henning Kamp return (error); 762b396cd83SPoul-Henning Kamp } 763b396cd83SPoul-Henning Kamp 764df8bae1dSRodney W. Grimes /* 7652e210993SPoul-Henning Kamp * Traverse our tree, and find the right node, execute whatever it points 7662e210993SPoul-Henning Kamp * at, and return the resulting error code. 7672e210993SPoul-Henning Kamp */ 7682e210993SPoul-Henning Kamp 7692e210993SPoul-Henning Kamp int 7702e210993SPoul-Henning Kamp sysctl_root SYSCTL_HANDLER_ARGS 7712e210993SPoul-Henning Kamp { 7722e210993SPoul-Henning Kamp int *name = (int *) arg1; 773946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 7742e210993SPoul-Henning Kamp int indx, i, j; 7752e210993SPoul-Henning Kamp struct sysctl_oid **oidpp; 7762e210993SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 7772e210993SPoul-Henning Kamp 7782e210993SPoul-Henning Kamp j = lsp->ls_length; 7792e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 7802e210993SPoul-Henning Kamp 7812e210993SPoul-Henning Kamp indx = 0; 7822e210993SPoul-Henning Kamp while (j-- && indx < CTL_MAXNAME) { 783787d58f2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number == name[indx])) { 7842e210993SPoul-Henning Kamp indx++; 7854b2af45fSPoul-Henning Kamp if ((*oidpp)->oid_kind & CTLFLAG_NOLOCK) 7864b2af45fSPoul-Henning Kamp req->lock = 0; 7872e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 7882e210993SPoul-Henning Kamp if ((*oidpp)->oid_handler) 7892e210993SPoul-Henning Kamp goto found; 7902e210993SPoul-Henning Kamp if (indx == namelen) 7912e210993SPoul-Henning Kamp return ENOENT; 7922e210993SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 7932e210993SPoul-Henning Kamp j = lsp->ls_length; 7942e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 7952e210993SPoul-Henning Kamp } else { 7962e210993SPoul-Henning Kamp if (indx != namelen) 7972e210993SPoul-Henning Kamp return EISDIR; 7982e210993SPoul-Henning Kamp goto found; 7992e210993SPoul-Henning Kamp } 8002e210993SPoul-Henning Kamp } else { 8012e210993SPoul-Henning Kamp oidpp++; 8022e210993SPoul-Henning Kamp } 8032e210993SPoul-Henning Kamp } 804deae269aSPoul-Henning Kamp return ENOENT; 8052e210993SPoul-Henning Kamp found: 8062e210993SPoul-Henning Kamp /* If writing isn't allowed */ 807ae0eb976SPoul-Henning Kamp if (req->newptr && !((*oidpp)->oid_kind & CTLFLAG_WR)) 8082e210993SPoul-Henning Kamp return (EPERM); 8092e210993SPoul-Henning Kamp 8103ac9f819SPoul-Henning Kamp /* Most likely only root can write */ 8113ac9f819SPoul-Henning Kamp if (!((*oidpp)->oid_kind & CTLFLAG_ANYBODY) && 8123ac9f819SPoul-Henning Kamp req->newptr && req->p && 8133ac9f819SPoul-Henning Kamp (i = suser(req->p->p_ucred, &req->p->p_acflag))) 8143ac9f819SPoul-Henning Kamp return (i); 8153ac9f819SPoul-Henning Kamp 8162e210993SPoul-Henning Kamp if (!(*oidpp)->oid_handler) 8172e210993SPoul-Henning Kamp return EINVAL; 8182e210993SPoul-Henning Kamp 8192e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 8202e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 8212e210993SPoul-Henning Kamp name + indx, namelen - indx, 822ae0eb976SPoul-Henning Kamp req); 8232e210993SPoul-Henning Kamp } else { 8242e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 8252e210993SPoul-Henning Kamp (*oidpp)->oid_arg1, (*oidpp)->oid_arg2, 826ae0eb976SPoul-Henning Kamp req); 8272e210993SPoul-Henning Kamp } 8282e210993SPoul-Henning Kamp return (i); 8292e210993SPoul-Henning Kamp } 8302e210993SPoul-Henning Kamp 831d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 832b8da2396SPoul-Henning Kamp struct sysctl_args { 833b8da2396SPoul-Henning Kamp int *name; 834b8da2396SPoul-Henning Kamp u_int namelen; 835b8da2396SPoul-Henning Kamp void *old; 836b8da2396SPoul-Henning Kamp size_t *oldlenp; 837b8da2396SPoul-Henning Kamp void *new; 838b8da2396SPoul-Henning Kamp size_t newlen; 839b8da2396SPoul-Henning Kamp }; 840d2d3e875SBruce Evans #endif 841b8da2396SPoul-Henning Kamp 842df8bae1dSRodney W. Grimes int 843cb226aaaSPoul-Henning Kamp __sysctl(struct proc *p, struct sysctl_args *uap) 844df8bae1dSRodney W. Grimes { 845069e9bc1SDoug Rabson int error, i, name[CTL_MAXNAME]; 846069e9bc1SDoug Rabson size_t j; 847b396cd83SPoul-Henning Kamp 848df8bae1dSRodney W. Grimes if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 849df8bae1dSRodney W. Grimes return (EINVAL); 850b396cd83SPoul-Henning Kamp 851797f2d22SPoul-Henning Kamp error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 852797f2d22SPoul-Henning Kamp if (error) 853df8bae1dSRodney W. Grimes return (error); 854df8bae1dSRodney W. Grimes 855deae269aSPoul-Henning Kamp error = userland_sysctl(p, name, uap->namelen, 856b8da2396SPoul-Henning Kamp uap->old, uap->oldlenp, 0, 857deae269aSPoul-Henning Kamp uap->new, uap->newlen, &j); 858deae269aSPoul-Henning Kamp if (error && error != ENOMEM) 859deae269aSPoul-Henning Kamp return (error); 860deae269aSPoul-Henning Kamp if (uap->oldlenp) { 861deae269aSPoul-Henning Kamp i = copyout(&j, uap->oldlenp, sizeof(j)); 862deae269aSPoul-Henning Kamp if (i) 863deae269aSPoul-Henning Kamp return (i); 864deae269aSPoul-Henning Kamp } 865deae269aSPoul-Henning Kamp return (error); 866b8da2396SPoul-Henning Kamp } 867b8da2396SPoul-Henning Kamp 868b8da2396SPoul-Henning Kamp /* 869b8da2396SPoul-Henning Kamp * This is used from various compatibility syscalls too. That's why name 870b8da2396SPoul-Henning Kamp * must be in kernel space. 871b8da2396SPoul-Henning Kamp */ 872b8da2396SPoul-Henning Kamp int 873069e9bc1SDoug Rabson userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval) 874b8da2396SPoul-Henning Kamp { 8754b2af45fSPoul-Henning Kamp int error = 0; 8767a69d923SPoul-Henning Kamp struct sysctl_req req, req2; 877ae0eb976SPoul-Henning Kamp 878ae0eb976SPoul-Henning Kamp bzero(&req, sizeof req); 879b8da2396SPoul-Henning Kamp 88016cd04a3SPoul-Henning Kamp req.p = p; 88116cd04a3SPoul-Henning Kamp 882b8da2396SPoul-Henning Kamp if (oldlenp) { 883b8da2396SPoul-Henning Kamp if (inkernel) { 884ae0eb976SPoul-Henning Kamp req.oldlen = *oldlenp; 885b8da2396SPoul-Henning Kamp } else { 886deae269aSPoul-Henning Kamp error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp)); 887b8da2396SPoul-Henning Kamp if (error) 888b8da2396SPoul-Henning Kamp return (error); 889b8da2396SPoul-Henning Kamp } 890b8da2396SPoul-Henning Kamp } 891b8da2396SPoul-Henning Kamp 892ae0eb976SPoul-Henning Kamp if (old) { 893ae0eb976SPoul-Henning Kamp if (!useracc(old, req.oldlen, B_WRITE)) 894ae0eb976SPoul-Henning Kamp return (EFAULT); 895ae0eb976SPoul-Henning Kamp req.oldptr= old; 896ae0eb976SPoul-Henning Kamp } 8972e210993SPoul-Henning Kamp 898b8da2396SPoul-Henning Kamp if (newlen) { 899ae0eb976SPoul-Henning Kamp if (!useracc(new, req.newlen, B_READ)) 900ae0eb976SPoul-Henning Kamp return (EFAULT); 901ae0eb976SPoul-Henning Kamp req.newlen = newlen; 902ae0eb976SPoul-Henning Kamp req.newptr = new; 903b396cd83SPoul-Henning Kamp } 904b396cd83SPoul-Henning Kamp 905ae0eb976SPoul-Henning Kamp req.oldfunc = sysctl_old_user; 906ae0eb976SPoul-Henning Kamp req.newfunc = sysctl_new_user; 9074b2af45fSPoul-Henning Kamp req.lock = 1; 9084b2af45fSPoul-Henning Kamp 9094b2af45fSPoul-Henning Kamp /* XXX this should probably be done in a general way */ 9104b2af45fSPoul-Henning Kamp while (memlock.sl_lock) { 9114b2af45fSPoul-Henning Kamp memlock.sl_want = 1; 9124b2af45fSPoul-Henning Kamp (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 9134b2af45fSPoul-Henning Kamp memlock.sl_locked++; 9144b2af45fSPoul-Henning Kamp } 9154b2af45fSPoul-Henning Kamp memlock.sl_lock = 1; 916ae0eb976SPoul-Henning Kamp 9177a69d923SPoul-Henning Kamp do { 9187a69d923SPoul-Henning Kamp req2 = req; 9197a69d923SPoul-Henning Kamp error = sysctl_root(0, name, namelen, &req2); 9207a69d923SPoul-Henning Kamp } while (error == EAGAIN); 921b396cd83SPoul-Henning Kamp 9227a69d923SPoul-Henning Kamp req = req2; 9234b2af45fSPoul-Henning Kamp if (req.lock == 2) 9244b2af45fSPoul-Henning Kamp vsunlock(req.oldptr, req.oldlen, B_WRITE); 9254b2af45fSPoul-Henning Kamp 9264b2af45fSPoul-Henning Kamp memlock.sl_lock = 0; 9274b2af45fSPoul-Henning Kamp 9284b2af45fSPoul-Henning Kamp if (memlock.sl_want) { 9294b2af45fSPoul-Henning Kamp memlock.sl_want = 0; 9304b2af45fSPoul-Henning Kamp wakeup((caddr_t)&memlock); 9314b2af45fSPoul-Henning Kamp } 9324b2af45fSPoul-Henning Kamp 933deae269aSPoul-Henning Kamp if (error && error != ENOMEM) 934deae269aSPoul-Henning Kamp return (error); 935deae269aSPoul-Henning Kamp 936deae269aSPoul-Henning Kamp if (retval) { 937deae269aSPoul-Henning Kamp if (req.oldptr && req.oldidx > req.oldlen) 938ae0eb976SPoul-Henning Kamp *retval = req.oldlen; 939deae269aSPoul-Henning Kamp else 940deae269aSPoul-Henning Kamp *retval = req.oldidx; 941b8da2396SPoul-Henning Kamp } 9422e210993SPoul-Henning Kamp return (error); 943df8bae1dSRodney W. Grimes } 944df8bae1dSRodney W. Grimes 945df8bae1dSRodney W. Grimes #ifdef COMPAT_43 946df8bae1dSRodney W. Grimes #include <sys/socket.h> 94745ec3b38SPoul-Henning Kamp #include <vm/vm_param.h> 94845ec3b38SPoul-Henning Kamp 949df8bae1dSRodney W. Grimes #define KINFO_PROC (0<<8) 950df8bae1dSRodney W. Grimes #define KINFO_RT (1<<8) 951df8bae1dSRodney W. Grimes #define KINFO_VNODE (2<<8) 952df8bae1dSRodney W. Grimes #define KINFO_FILE (3<<8) 953df8bae1dSRodney W. Grimes #define KINFO_METER (4<<8) 954df8bae1dSRodney W. Grimes #define KINFO_LOADAVG (5<<8) 955df8bae1dSRodney W. Grimes #define KINFO_CLOCKRATE (6<<8) 956df8bae1dSRodney W. Grimes 9576ece4a51SPeter Wemm /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ 9586ece4a51SPeter Wemm #define KINFO_BSDI_SYSINFO (101<<8) 9596ece4a51SPeter Wemm 9606ece4a51SPeter Wemm /* 9616ece4a51SPeter Wemm * XXX this is bloat, but I hope it's better here than on the potentially 9626ece4a51SPeter Wemm * limited kernel stack... -Peter 9636ece4a51SPeter Wemm */ 9646ece4a51SPeter Wemm 96587b6de2bSPoul-Henning Kamp static struct { 9666ece4a51SPeter Wemm int bsdi_machine; /* "i386" on BSD/386 */ 9676ece4a51SPeter Wemm /* ^^^ this is an offset to the string, relative to the struct start */ 9686ece4a51SPeter Wemm char *pad0; 9696ece4a51SPeter Wemm long pad1; 9706ece4a51SPeter Wemm long pad2; 9716ece4a51SPeter Wemm long pad3; 9726ece4a51SPeter Wemm u_long pad4; 9736ece4a51SPeter Wemm u_long pad5; 9746ece4a51SPeter Wemm u_long pad6; 9756ece4a51SPeter Wemm 9766ece4a51SPeter Wemm int bsdi_ostype; /* "BSD/386" on BSD/386 */ 9776ece4a51SPeter Wemm int bsdi_osrelease; /* "1.1" on BSD/386 */ 9786ece4a51SPeter Wemm long pad7; 9796ece4a51SPeter Wemm long pad8; 9806ece4a51SPeter Wemm char *pad9; 9816ece4a51SPeter Wemm 9826ece4a51SPeter Wemm long pad10; 9836ece4a51SPeter Wemm long pad11; 9846ece4a51SPeter Wemm int pad12; 9856ece4a51SPeter Wemm long pad13; 9866ece4a51SPeter Wemm quad_t pad14; 9876ece4a51SPeter Wemm long pad15; 9886ece4a51SPeter Wemm 9896ece4a51SPeter Wemm struct timeval pad16; 9906ece4a51SPeter Wemm /* we dont set this, because BSDI's uname used gethostname() instead */ 9916ece4a51SPeter Wemm int bsdi_hostname; /* hostname on BSD/386 */ 9926ece4a51SPeter Wemm 9936ece4a51SPeter Wemm /* the actual string data is appended here */ 9946ece4a51SPeter Wemm 9956ece4a51SPeter Wemm } bsdi_si; 9966ece4a51SPeter Wemm /* 9976ece4a51SPeter Wemm * this data is appended to the end of the bsdi_si structure during copyout. 9986ece4a51SPeter Wemm * The "char *" offsets are relative to the base of the bsdi_si struct. 9996ece4a51SPeter Wemm * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings 10006ece4a51SPeter Wemm * should not exceed the length of the buffer here... (or else!! :-) 10016ece4a51SPeter Wemm */ 100287b6de2bSPoul-Henning Kamp static char bsdi_strings[80]; /* It had better be less than this! */ 10036ece4a51SPeter Wemm 1004d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 1005df8bae1dSRodney W. Grimes struct getkerninfo_args { 1006df8bae1dSRodney W. Grimes int op; 1007df8bae1dSRodney W. Grimes char *where; 1008134e06feSBruce Evans size_t *size; 1009df8bae1dSRodney W. Grimes int arg; 1010df8bae1dSRodney W. Grimes }; 1011d2d3e875SBruce Evans #endif 1012df8bae1dSRodney W. Grimes 101326f9a767SRodney W. Grimes int 1014cb226aaaSPoul-Henning Kamp ogetkerninfo(struct proc *p, struct getkerninfo_args *uap) 1015df8bae1dSRodney W. Grimes { 1016b8da2396SPoul-Henning Kamp int error, name[6]; 1017069e9bc1SDoug Rabson size_t size; 1018df8bae1dSRodney W. Grimes 1019df8bae1dSRodney W. Grimes switch (uap->op & 0xff00) { 1020df8bae1dSRodney W. Grimes 1021df8bae1dSRodney W. Grimes case KINFO_RT: 1022b8da2396SPoul-Henning Kamp name[0] = CTL_NET; 1023b8da2396SPoul-Henning Kamp name[1] = PF_ROUTE; 1024b8da2396SPoul-Henning Kamp name[2] = 0; 1025b8da2396SPoul-Henning Kamp name[3] = (uap->op & 0xff0000) >> 16; 1026b8da2396SPoul-Henning Kamp name[4] = uap->op & 0xff; 1027b8da2396SPoul-Henning Kamp name[5] = uap->arg; 1028b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 6, uap->where, uap->size, 10294b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1030df8bae1dSRodney W. Grimes break; 1031df8bae1dSRodney W. Grimes 1032df8bae1dSRodney W. Grimes case KINFO_VNODE: 1033b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1034b8da2396SPoul-Henning Kamp name[1] = KERN_VNODE; 1035b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10364b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1037df8bae1dSRodney W. Grimes break; 1038df8bae1dSRodney W. Grimes 1039df8bae1dSRodney W. Grimes case KINFO_PROC: 1040b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1041b8da2396SPoul-Henning Kamp name[1] = KERN_PROC; 1042b8da2396SPoul-Henning Kamp name[2] = uap->op & 0xff; 1043b8da2396SPoul-Henning Kamp name[3] = uap->arg; 1044b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 4, uap->where, uap->size, 10454b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1046df8bae1dSRodney W. Grimes break; 1047df8bae1dSRodney W. Grimes 1048df8bae1dSRodney W. Grimes case KINFO_FILE: 1049b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1050b8da2396SPoul-Henning Kamp name[1] = KERN_FILE; 1051b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10524b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1053df8bae1dSRodney W. Grimes break; 1054df8bae1dSRodney W. Grimes 1055df8bae1dSRodney W. Grimes case KINFO_METER: 1056b8da2396SPoul-Henning Kamp name[0] = CTL_VM; 1057b8da2396SPoul-Henning Kamp name[1] = VM_METER; 1058b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10594b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1060df8bae1dSRodney W. Grimes break; 1061df8bae1dSRodney W. Grimes 1062df8bae1dSRodney W. Grimes case KINFO_LOADAVG: 1063b8da2396SPoul-Henning Kamp name[0] = CTL_VM; 1064b8da2396SPoul-Henning Kamp name[1] = VM_LOADAVG; 1065b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10664b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1067df8bae1dSRodney W. Grimes break; 1068df8bae1dSRodney W. Grimes 1069df8bae1dSRodney W. Grimes case KINFO_CLOCKRATE: 1070b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1071b8da2396SPoul-Henning Kamp name[1] = KERN_CLOCKRATE; 1072b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10734b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1074df8bae1dSRodney W. Grimes break; 1075df8bae1dSRodney W. Grimes 10766ece4a51SPeter Wemm case KINFO_BSDI_SYSINFO: { 10776ece4a51SPeter Wemm /* 10786ece4a51SPeter Wemm * this is pretty crude, but it's just enough for uname() 10796ece4a51SPeter Wemm * from BSDI's 1.x libc to work. 10806ece4a51SPeter Wemm * 10816ece4a51SPeter Wemm * In particular, it doesn't return the same results when 10826ece4a51SPeter Wemm * the supplied buffer is too small. BSDI's version apparently 10836ece4a51SPeter Wemm * will return the amount copied, and set the *size to how 10846ece4a51SPeter Wemm * much was needed. The emulation framework here isn't capable 10856ece4a51SPeter Wemm * of that, so we just set both to the amount copied. 10866ece4a51SPeter Wemm * BSDI's 2.x product apparently fails with ENOMEM in this 10876ece4a51SPeter Wemm * scenario. 10886ece4a51SPeter Wemm */ 10896ece4a51SPeter Wemm 10906ece4a51SPeter Wemm u_int needed; 10916ece4a51SPeter Wemm u_int left; 10926ece4a51SPeter Wemm char *s; 10936ece4a51SPeter Wemm 10946ece4a51SPeter Wemm bzero((char *)&bsdi_si, sizeof(bsdi_si)); 10956ece4a51SPeter Wemm bzero(bsdi_strings, sizeof(bsdi_strings)); 10966ece4a51SPeter Wemm 10976ece4a51SPeter Wemm s = bsdi_strings; 10986ece4a51SPeter Wemm 10996ece4a51SPeter Wemm bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); 11006ece4a51SPeter Wemm strcpy(s, ostype); 11016ece4a51SPeter Wemm s += strlen(s) + 1; 11026ece4a51SPeter Wemm 11036ece4a51SPeter Wemm bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); 11046ece4a51SPeter Wemm strcpy(s, osrelease); 11056ece4a51SPeter Wemm s += strlen(s) + 1; 11066ece4a51SPeter Wemm 11076ece4a51SPeter Wemm bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); 11086ece4a51SPeter Wemm strcpy(s, machine); 11096ece4a51SPeter Wemm s += strlen(s) + 1; 11106ece4a51SPeter Wemm 11116ece4a51SPeter Wemm needed = sizeof(bsdi_si) + (s - bsdi_strings); 11126ece4a51SPeter Wemm 11136ece4a51SPeter Wemm if (uap->where == NULL) { 11146ece4a51SPeter Wemm /* process is asking how much buffer to supply.. */ 11156ece4a51SPeter Wemm size = needed; 11166ece4a51SPeter Wemm error = 0; 11176ece4a51SPeter Wemm break; 11186ece4a51SPeter Wemm } 11196ece4a51SPeter Wemm 11206ece4a51SPeter Wemm 11216ece4a51SPeter Wemm /* if too much buffer supplied, trim it down */ 11226ece4a51SPeter Wemm if (size > needed) 11236ece4a51SPeter Wemm size = needed; 11246ece4a51SPeter Wemm 11256ece4a51SPeter Wemm /* how much of the buffer is remaining */ 11266ece4a51SPeter Wemm left = size; 11276ece4a51SPeter Wemm 11286ece4a51SPeter Wemm if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) 11296ece4a51SPeter Wemm break; 11306ece4a51SPeter Wemm 11316ece4a51SPeter Wemm /* is there any point in continuing? */ 11326ece4a51SPeter Wemm if (left > sizeof(bsdi_si)) { 11336ece4a51SPeter Wemm left -= sizeof(bsdi_si); 11346ece4a51SPeter Wemm error = copyout(&bsdi_strings, 11356ece4a51SPeter Wemm uap->where + sizeof(bsdi_si), left); 11366ece4a51SPeter Wemm } 11376ece4a51SPeter Wemm break; 11386ece4a51SPeter Wemm } 11396ece4a51SPeter Wemm 1140df8bae1dSRodney W. Grimes default: 1141df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 1142df8bae1dSRodney W. Grimes } 1143df8bae1dSRodney W. Grimes if (error) 1144df8bae1dSRodney W. Grimes return (error); 1145cb226aaaSPoul-Henning Kamp p->p_retval[0] = size; 1146df8bae1dSRodney W. Grimes if (uap->size) 1147df8bae1dSRodney W. Grimes error = copyout((caddr_t)&size, (caddr_t)uap->size, 1148df8bae1dSRodney W. Grimes sizeof(size)); 1149df8bae1dSRodney W. Grimes return (error); 1150df8bae1dSRodney W. Grimes } 1151df8bae1dSRodney W. Grimes #endif /* COMPAT_43 */ 1152