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 40a1c995b6SPoul-Henning Kamp * $Id: kern_sysctl.c,v 1.71 1997/10/11 18:31:24 phk Exp $ 41df8bae1dSRodney W. Grimes */ 42df8bae1dSRodney W. Grimes 43df8bae1dSRodney W. Grimes #include <sys/param.h> 444e750649SBruce Evans #include <sys/buf.h> 45df8bae1dSRodney W. Grimes #include <sys/kernel.h> 46df8bae1dSRodney W. Grimes #include <sys/sysctl.h> 47946bb7a2SPoul-Henning Kamp #include <sys/malloc.h> 48efeaf95aSDavid Greenman #include <sys/proc.h> 4945ec3b38SPoul-Henning Kamp #include <sys/systm.h> 5045ec3b38SPoul-Henning Kamp #include <sys/sysproto.h> 514cb03b1bSBruce Evans #include <vm/vm.h> 52efeaf95aSDavid Greenman #include <vm/vm_extern.h> 534cb03b1bSBruce Evans 54a1c995b6SPoul-Henning Kamp static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic"); 5555166637SPoul-Henning Kamp 564b2af45fSPoul-Henning Kamp /* 574b2af45fSPoul-Henning Kamp * Locking and stats 584b2af45fSPoul-Henning Kamp */ 594b2af45fSPoul-Henning Kamp static struct sysctl_lock { 604b2af45fSPoul-Henning Kamp int sl_lock; 614b2af45fSPoul-Henning Kamp int sl_want; 624b2af45fSPoul-Henning Kamp int sl_locked; 634b2af45fSPoul-Henning Kamp } memlock; 644b2af45fSPoul-Henning Kamp 654b2af45fSPoul-Henning Kamp static int sysctl_root SYSCTL_HANDLER_ARGS; 664b2af45fSPoul-Henning Kamp 67787d58f2SPoul-Henning Kamp extern struct linker_set sysctl_; 68787d58f2SPoul-Henning Kamp 69946bb7a2SPoul-Henning Kamp /* 70946bb7a2SPoul-Henning Kamp * Initialization of the MIB tree. 71946bb7a2SPoul-Henning Kamp * 72946bb7a2SPoul-Henning Kamp * Order by number in each linker_set. 73946bb7a2SPoul-Henning Kamp */ 744b2af45fSPoul-Henning Kamp 75787d58f2SPoul-Henning Kamp static int 763c8e79ddSBruce Evans sysctl_order_cmp(const void *a, const void *b) 77787d58f2SPoul-Henning Kamp { 783f6a052aSBruce Evans struct sysctl_oid const * const *pa; 793f6a052aSBruce Evans struct sysctl_oid const * const *pb; 803c8e79ddSBruce Evans 813f6a052aSBruce Evans pa = (struct sysctl_oid const * const *)a; 823f6a052aSBruce Evans pb = (struct sysctl_oid const * const *)b; 833c8e79ddSBruce Evans if (*pa == NULL) 843c8e79ddSBruce Evans return (1); 853c8e79ddSBruce Evans if (*pb == NULL) 863c8e79ddSBruce Evans return (-1); 87787d58f2SPoul-Henning Kamp return ((*pa)->oid_number - (*pb)->oid_number); 88787d58f2SPoul-Henning Kamp } 89787d58f2SPoul-Henning Kamp 90787d58f2SPoul-Henning Kamp static void 91787d58f2SPoul-Henning Kamp sysctl_order(void *arg) 92787d58f2SPoul-Henning Kamp { 93946bb7a2SPoul-Henning Kamp int j, k; 94787d58f2SPoul-Henning Kamp struct linker_set *l = (struct linker_set *) arg; 95787d58f2SPoul-Henning Kamp struct sysctl_oid **oidpp; 96787d58f2SPoul-Henning Kamp 97946bb7a2SPoul-Henning Kamp /* First, find the highest oid we have */ 98946bb7a2SPoul-Henning Kamp j = l->ls_length; 99946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 10061220614SPoul-Henning Kamp for (k = 0; j--; oidpp++) { 10161220614SPoul-Henning Kamp if ((*oidpp)->oid_arg1 == arg) { 10261220614SPoul-Henning Kamp *oidpp = 0; 10361220614SPoul-Henning Kamp continue; 10461220614SPoul-Henning Kamp } 105946bb7a2SPoul-Henning Kamp if (*oidpp && (*oidpp)->oid_number > k) 106946bb7a2SPoul-Henning Kamp k = (*oidpp)->oid_number; 10761220614SPoul-Henning Kamp } 108946bb7a2SPoul-Henning Kamp 109946bb7a2SPoul-Henning Kamp /* Next, replace all OID_AUTO oids with new numbers */ 110946bb7a2SPoul-Henning Kamp j = l->ls_length; 111946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 112946bb7a2SPoul-Henning Kamp k += 100; 113946bb7a2SPoul-Henning Kamp for (; j--; oidpp++) 114946bb7a2SPoul-Henning Kamp if (*oidpp && (*oidpp)->oid_number == OID_AUTO) 115946bb7a2SPoul-Henning Kamp (*oidpp)->oid_number = k++; 116946bb7a2SPoul-Henning Kamp 117946bb7a2SPoul-Henning Kamp /* Finally: sort by oid */ 118787d58f2SPoul-Henning Kamp j = l->ls_length; 119787d58f2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 120787d58f2SPoul-Henning Kamp for (; j--; oidpp++) { 121787d58f2SPoul-Henning Kamp if (!*oidpp) 122787d58f2SPoul-Henning Kamp continue; 123787d58f2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) 124787d58f2SPoul-Henning Kamp if (!(*oidpp)->oid_handler) 125787d58f2SPoul-Henning Kamp sysctl_order((*oidpp)->oid_arg1); 126787d58f2SPoul-Henning Kamp } 127787d58f2SPoul-Henning Kamp qsort(l->ls_items, l->ls_length, sizeof l->ls_items[0], 128787d58f2SPoul-Henning Kamp sysctl_order_cmp); 129787d58f2SPoul-Henning Kamp } 130787d58f2SPoul-Henning Kamp 131787d58f2SPoul-Henning Kamp SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_order, &sysctl_); 132787d58f2SPoul-Henning Kamp 133946bb7a2SPoul-Henning Kamp /* 134946bb7a2SPoul-Henning Kamp * "Staff-functions" 135946bb7a2SPoul-Henning Kamp * 13665d0bc13SPoul-Henning Kamp * These functions implement a presently undocumented interface 13765d0bc13SPoul-Henning Kamp * used by the sysctl program to walk the tree, and get the type 13865d0bc13SPoul-Henning Kamp * so it can print the value. 13965d0bc13SPoul-Henning Kamp * This interface is under work and consideration, and should probably 14065d0bc13SPoul-Henning Kamp * be killed with a big axe by the first person who can find the time. 14165d0bc13SPoul-Henning Kamp * (be aware though, that the proper interface isn't as obvious as it 14265d0bc13SPoul-Henning Kamp * may seem, there are various conflicting requirements. 14365d0bc13SPoul-Henning Kamp * 144946bb7a2SPoul-Henning Kamp * {0,0} printf the entire MIB-tree. 145946bb7a2SPoul-Henning Kamp * {0,1,...} return the name of the "..." OID. 146946bb7a2SPoul-Henning Kamp * {0,2,...} return the next OID. 147946bb7a2SPoul-Henning Kamp * {0,3} return the OID of the name in "new" 14865d0bc13SPoul-Henning Kamp * {0,4,...} return the kind & format info for the "..." OID. 149946bb7a2SPoul-Henning Kamp */ 150946bb7a2SPoul-Henning Kamp 151787d58f2SPoul-Henning Kamp static void 152787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node(struct linker_set *l, int i) 153787d58f2SPoul-Henning Kamp { 154787d58f2SPoul-Henning Kamp int j, k; 155787d58f2SPoul-Henning Kamp struct sysctl_oid **oidpp; 156787d58f2SPoul-Henning Kamp 157787d58f2SPoul-Henning Kamp j = l->ls_length; 158787d58f2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) l->ls_items; 159787d58f2SPoul-Henning Kamp for (; j--; oidpp++) { 160787d58f2SPoul-Henning Kamp 161787d58f2SPoul-Henning Kamp if (!*oidpp) 162787d58f2SPoul-Henning Kamp continue; 163787d58f2SPoul-Henning Kamp 164787d58f2SPoul-Henning Kamp for (k=0; k<i; k++) 165787d58f2SPoul-Henning Kamp printf(" "); 166787d58f2SPoul-Henning Kamp 167787d58f2SPoul-Henning Kamp printf("%d %s ", (*oidpp)->oid_number, (*oidpp)->oid_name); 168787d58f2SPoul-Henning Kamp 169787d58f2SPoul-Henning Kamp printf("%c%c", 170787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind & CTLFLAG_RD ? 'R':' ', 171787d58f2SPoul-Henning Kamp (*oidpp)->oid_kind & CTLFLAG_WR ? 'W':' '); 172787d58f2SPoul-Henning Kamp 17361220614SPoul-Henning Kamp if ((*oidpp)->oid_handler) 17461220614SPoul-Henning Kamp printf(" *Handler"); 17561220614SPoul-Henning Kamp 176787d58f2SPoul-Henning Kamp switch ((*oidpp)->oid_kind & CTLTYPE) { 177787d58f2SPoul-Henning Kamp case CTLTYPE_NODE: 178787d58f2SPoul-Henning Kamp printf(" Node\n"); 17961220614SPoul-Henning Kamp if (!(*oidpp)->oid_handler) { 180787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node( 181787d58f2SPoul-Henning Kamp (*oidpp)->oid_arg1, i+2); 182787d58f2SPoul-Henning Kamp } 183787d58f2SPoul-Henning Kamp break; 184787d58f2SPoul-Henning Kamp case CTLTYPE_INT: printf(" Int\n"); break; 185787d58f2SPoul-Henning Kamp case CTLTYPE_STRING: printf(" String\n"); break; 186787d58f2SPoul-Henning Kamp case CTLTYPE_QUAD: printf(" Quad\n"); break; 187787d58f2SPoul-Henning Kamp case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break; 188787d58f2SPoul-Henning Kamp default: printf("\n"); 189787d58f2SPoul-Henning Kamp } 190787d58f2SPoul-Henning Kamp 191787d58f2SPoul-Henning Kamp } 192787d58f2SPoul-Henning Kamp } 193787d58f2SPoul-Henning Kamp 194787d58f2SPoul-Henning Kamp static int 195787d58f2SPoul-Henning Kamp sysctl_sysctl_debug SYSCTL_HANDLER_ARGS 196787d58f2SPoul-Henning Kamp { 197787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node(&sysctl_, 0); 198787d58f2SPoul-Henning Kamp return ENOENT; 199787d58f2SPoul-Henning Kamp } 200787d58f2SPoul-Henning Kamp 201787d58f2SPoul-Henning Kamp SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD, 202946bb7a2SPoul-Henning Kamp 0, 0, sysctl_sysctl_debug, "-", ""); 2032e210993SPoul-Henning Kamp 204946bb7a2SPoul-Henning Kamp static int 205946bb7a2SPoul-Henning Kamp sysctl_sysctl_name SYSCTL_HANDLER_ARGS 206946bb7a2SPoul-Henning Kamp { 207946bb7a2SPoul-Henning Kamp int *name = (int *) arg1; 208946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 209946bb7a2SPoul-Henning Kamp int i, j, error = 0; 210946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 211946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 212946bb7a2SPoul-Henning Kamp char buf[10]; 2132e210993SPoul-Henning Kamp 214946bb7a2SPoul-Henning Kamp while (namelen) { 215946bb7a2SPoul-Henning Kamp if (!lsp) { 216946bb7a2SPoul-Henning Kamp sprintf(buf,"%d",*name); 217946bb7a2SPoul-Henning Kamp if (req->oldidx) 218946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, ".", 1); 219946bb7a2SPoul-Henning Kamp if (!error) 220946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, buf, strlen(buf)); 221946bb7a2SPoul-Henning Kamp if (error) 222946bb7a2SPoul-Henning Kamp return (error); 223946bb7a2SPoul-Henning Kamp namelen--; 224946bb7a2SPoul-Henning Kamp name++; 225946bb7a2SPoul-Henning Kamp continue; 226946bb7a2SPoul-Henning Kamp } 227946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 228946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 229946bb7a2SPoul-Henning Kamp lsp = 0; 230946bb7a2SPoul-Henning Kamp for (i = 0; i < j; i++, oidpp++) { 231946bb7a2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number != *name)) 232946bb7a2SPoul-Henning Kamp continue; 233946bb7a2SPoul-Henning Kamp 234946bb7a2SPoul-Henning Kamp if (req->oldidx) 235946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, ".", 1); 236946bb7a2SPoul-Henning Kamp if (!error) 237946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, (*oidpp)->oid_name, 238946bb7a2SPoul-Henning Kamp strlen((*oidpp)->oid_name)); 239946bb7a2SPoul-Henning Kamp if (error) 240946bb7a2SPoul-Henning Kamp return (error); 241946bb7a2SPoul-Henning Kamp 242946bb7a2SPoul-Henning Kamp namelen--; 243946bb7a2SPoul-Henning Kamp name++; 244946bb7a2SPoul-Henning Kamp 245946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 246946bb7a2SPoul-Henning Kamp break; 247946bb7a2SPoul-Henning Kamp 248946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 249946bb7a2SPoul-Henning Kamp break; 250946bb7a2SPoul-Henning Kamp 251946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 252946bb7a2SPoul-Henning Kamp break; 253946bb7a2SPoul-Henning Kamp } 254946bb7a2SPoul-Henning Kamp } 255946bb7a2SPoul-Henning Kamp return (SYSCTL_OUT(req, "", 1)); 256946bb7a2SPoul-Henning Kamp } 257946bb7a2SPoul-Henning Kamp 258946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD, sysctl_sysctl_name, ""); 259946bb7a2SPoul-Henning Kamp 260946bb7a2SPoul-Henning Kamp static int 261946bb7a2SPoul-Henning Kamp sysctl_sysctl_next_ls (struct linker_set *lsp, int *name, u_int namelen, 262946bb7a2SPoul-Henning Kamp int *next, int *len, int level, struct sysctl_oid **oidp) 263946bb7a2SPoul-Henning Kamp { 264946bb7a2SPoul-Henning Kamp int i, j; 265946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 266946bb7a2SPoul-Henning Kamp 267946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 268946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 269946bb7a2SPoul-Henning Kamp *len = level; 270946bb7a2SPoul-Henning Kamp for (i = 0; i < j; i++, oidpp++) { 271946bb7a2SPoul-Henning Kamp if (!*oidpp) 272946bb7a2SPoul-Henning Kamp continue; 273946bb7a2SPoul-Henning Kamp 274946bb7a2SPoul-Henning Kamp *next = (*oidpp)->oid_number; 275946bb7a2SPoul-Henning Kamp *oidp = *oidpp; 276946bb7a2SPoul-Henning Kamp 277946bb7a2SPoul-Henning Kamp if (!namelen) { 278946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 279946bb7a2SPoul-Henning Kamp return 0; 280946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 281946bb7a2SPoul-Henning Kamp /* We really should call the handler here...*/ 282946bb7a2SPoul-Henning Kamp return 0; 283946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 28461220614SPoul-Henning Kamp if (!sysctl_sysctl_next_ls (lsp, 0, 0, next+1, 28561220614SPoul-Henning Kamp len, level+1, oidp)) 28661220614SPoul-Henning Kamp return 0; 28761220614SPoul-Henning Kamp goto next; 288946bb7a2SPoul-Henning Kamp } 289946bb7a2SPoul-Henning Kamp 290946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_number < *name) 291946bb7a2SPoul-Henning Kamp continue; 292946bb7a2SPoul-Henning Kamp 293946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_number > *name) { 294946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 295946bb7a2SPoul-Henning Kamp return 0; 296946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 297946bb7a2SPoul-Henning Kamp return 0; 298946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 299946bb7a2SPoul-Henning Kamp if (!sysctl_sysctl_next_ls (lsp, name+1, namelen-1, 300946bb7a2SPoul-Henning Kamp next+1, len, level+1, oidp)) 301946bb7a2SPoul-Henning Kamp return (0); 30261220614SPoul-Henning Kamp goto next; 303946bb7a2SPoul-Henning Kamp } 304946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 305946bb7a2SPoul-Henning Kamp continue; 306946bb7a2SPoul-Henning Kamp 307946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 308946bb7a2SPoul-Henning Kamp continue; 309946bb7a2SPoul-Henning Kamp 310946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 311946bb7a2SPoul-Henning Kamp if (!sysctl_sysctl_next_ls (lsp, name+1, namelen-1, next+1, 312946bb7a2SPoul-Henning Kamp len, level+1, oidp)) 313946bb7a2SPoul-Henning Kamp return (0); 31461220614SPoul-Henning Kamp next: 315946bb7a2SPoul-Henning Kamp namelen = 1; 316946bb7a2SPoul-Henning Kamp *len = level; 317946bb7a2SPoul-Henning Kamp } 318946bb7a2SPoul-Henning Kamp return 1; 319946bb7a2SPoul-Henning Kamp } 320946bb7a2SPoul-Henning Kamp 321946bb7a2SPoul-Henning Kamp static int 322946bb7a2SPoul-Henning Kamp sysctl_sysctl_next SYSCTL_HANDLER_ARGS 323946bb7a2SPoul-Henning Kamp { 324946bb7a2SPoul-Henning Kamp int *name = (int *) arg1; 325946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 326946bb7a2SPoul-Henning Kamp int i, j, error; 327946bb7a2SPoul-Henning Kamp struct sysctl_oid *oid; 328946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 329946bb7a2SPoul-Henning Kamp int newoid[CTL_MAXNAME]; 330946bb7a2SPoul-Henning Kamp 331946bb7a2SPoul-Henning Kamp i = sysctl_sysctl_next_ls (lsp, name, namelen, newoid, &j, 1, &oid); 332946bb7a2SPoul-Henning Kamp if (i) 333946bb7a2SPoul-Henning Kamp return ENOENT; 334946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, newoid, j * sizeof (int)); 335946bb7a2SPoul-Henning Kamp return (error); 336946bb7a2SPoul-Henning Kamp } 337946bb7a2SPoul-Henning Kamp 338946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, ""); 339946bb7a2SPoul-Henning Kamp 340946bb7a2SPoul-Henning Kamp static int 341946bb7a2SPoul-Henning Kamp name2oid (char *name, int *oid, int *len, struct sysctl_oid **oidp) 342946bb7a2SPoul-Henning Kamp { 343946bb7a2SPoul-Henning Kamp int i, j; 344946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 345946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 346946bb7a2SPoul-Henning Kamp char *p; 347946bb7a2SPoul-Henning Kamp 348946bb7a2SPoul-Henning Kamp if (!*name) 349946bb7a2SPoul-Henning Kamp return ENOENT; 350946bb7a2SPoul-Henning Kamp 351946bb7a2SPoul-Henning Kamp p = name + strlen(name) - 1 ; 352946bb7a2SPoul-Henning Kamp if (*p == '.') 353946bb7a2SPoul-Henning Kamp *p = '\0'; 354946bb7a2SPoul-Henning Kamp 355946bb7a2SPoul-Henning Kamp *len = 0; 356946bb7a2SPoul-Henning Kamp 357946bb7a2SPoul-Henning Kamp for (p = name; *p && *p != '.'; p++) 358946bb7a2SPoul-Henning Kamp ; 359946bb7a2SPoul-Henning Kamp i = *p; 360946bb7a2SPoul-Henning Kamp if (i == '.') 361946bb7a2SPoul-Henning Kamp *p = '\0'; 362946bb7a2SPoul-Henning Kamp 363946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 364946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 365946bb7a2SPoul-Henning Kamp 366946bb7a2SPoul-Henning Kamp while (j-- && *len < CTL_MAXNAME) { 367946bb7a2SPoul-Henning Kamp if (!*oidpp) 368946bb7a2SPoul-Henning Kamp continue; 369946bb7a2SPoul-Henning Kamp if (strcmp(name, (*oidpp)->oid_name)) { 370946bb7a2SPoul-Henning Kamp oidpp++; 371946bb7a2SPoul-Henning Kamp continue; 372946bb7a2SPoul-Henning Kamp } 373946bb7a2SPoul-Henning Kamp *oid++ = (*oidpp)->oid_number; 374946bb7a2SPoul-Henning Kamp (*len)++; 375946bb7a2SPoul-Henning Kamp 376946bb7a2SPoul-Henning Kamp if (!i) { 377946bb7a2SPoul-Henning Kamp if (oidp) 378946bb7a2SPoul-Henning Kamp *oidp = *oidpp; 379946bb7a2SPoul-Henning Kamp return (0); 380946bb7a2SPoul-Henning Kamp } 381946bb7a2SPoul-Henning Kamp 382946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) != CTLTYPE_NODE) 383946bb7a2SPoul-Henning Kamp break; 384946bb7a2SPoul-Henning Kamp 385946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 386946bb7a2SPoul-Henning Kamp break; 387946bb7a2SPoul-Henning Kamp 388946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 389946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 390946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 391946bb7a2SPoul-Henning Kamp name = p+1; 392946bb7a2SPoul-Henning Kamp for (p = name; *p && *p != '.'; p++) 393946bb7a2SPoul-Henning Kamp ; 394946bb7a2SPoul-Henning Kamp i = *p; 395946bb7a2SPoul-Henning Kamp if (i == '.') 396946bb7a2SPoul-Henning Kamp *p = '\0'; 397946bb7a2SPoul-Henning Kamp } 398946bb7a2SPoul-Henning Kamp return ENOENT; 399946bb7a2SPoul-Henning Kamp } 400946bb7a2SPoul-Henning Kamp 401946bb7a2SPoul-Henning Kamp static int 402946bb7a2SPoul-Henning Kamp sysctl_sysctl_name2oid SYSCTL_HANDLER_ARGS 403946bb7a2SPoul-Henning Kamp { 404946bb7a2SPoul-Henning Kamp char *p; 405946bb7a2SPoul-Henning Kamp int error, oid[CTL_MAXNAME], len; 406946bb7a2SPoul-Henning Kamp struct sysctl_oid *op = 0; 407946bb7a2SPoul-Henning Kamp 408946bb7a2SPoul-Henning Kamp if (!req->newlen) 409946bb7a2SPoul-Henning Kamp return ENOENT; 410946bb7a2SPoul-Henning Kamp 411946bb7a2SPoul-Henning Kamp p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK); 412946bb7a2SPoul-Henning Kamp 413946bb7a2SPoul-Henning Kamp error = SYSCTL_IN(req, p, req->newlen); 414946bb7a2SPoul-Henning Kamp if (error) { 415946bb7a2SPoul-Henning Kamp free(p, M_SYSCTL); 416946bb7a2SPoul-Henning Kamp return (error); 417946bb7a2SPoul-Henning Kamp } 418946bb7a2SPoul-Henning Kamp 419946bb7a2SPoul-Henning Kamp p [req->newlen] = '\0'; 420946bb7a2SPoul-Henning Kamp 421946bb7a2SPoul-Henning Kamp error = name2oid(p, oid, &len, &op); 422946bb7a2SPoul-Henning Kamp 423946bb7a2SPoul-Henning Kamp free(p, M_SYSCTL); 424946bb7a2SPoul-Henning Kamp 425946bb7a2SPoul-Henning Kamp if (error) 426946bb7a2SPoul-Henning Kamp return (error); 427946bb7a2SPoul-Henning Kamp 428946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, oid, len * sizeof *oid); 429946bb7a2SPoul-Henning Kamp return (error); 430946bb7a2SPoul-Henning Kamp } 431946bb7a2SPoul-Henning Kamp 4323ac9f819SPoul-Henning Kamp SYSCTL_PROC(_sysctl, 3, name2oid, CTLFLAG_RW|CTLFLAG_ANYBODY, 0, 0, 433946bb7a2SPoul-Henning Kamp sysctl_sysctl_name2oid, "I", ""); 434946bb7a2SPoul-Henning Kamp 435946bb7a2SPoul-Henning Kamp static int 436946bb7a2SPoul-Henning Kamp sysctl_sysctl_oidfmt SYSCTL_HANDLER_ARGS 437946bb7a2SPoul-Henning Kamp { 43865d0bc13SPoul-Henning Kamp int *name = (int *) arg1, error; 439946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 440946bb7a2SPoul-Henning Kamp int indx, j; 441946bb7a2SPoul-Henning Kamp struct sysctl_oid **oidpp; 442946bb7a2SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 443946bb7a2SPoul-Henning Kamp 444946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 445946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 446946bb7a2SPoul-Henning Kamp 447946bb7a2SPoul-Henning Kamp indx = 0; 448946bb7a2SPoul-Henning Kamp while (j-- && indx < CTL_MAXNAME) { 449946bb7a2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number == name[indx])) { 450946bb7a2SPoul-Henning Kamp indx++; 451946bb7a2SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 452946bb7a2SPoul-Henning Kamp if ((*oidpp)->oid_handler) 453946bb7a2SPoul-Henning Kamp goto found; 454946bb7a2SPoul-Henning Kamp if (indx == namelen) 45565d0bc13SPoul-Henning Kamp goto found; 456946bb7a2SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 457946bb7a2SPoul-Henning Kamp j = lsp->ls_length; 458946bb7a2SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 459946bb7a2SPoul-Henning Kamp } else { 460946bb7a2SPoul-Henning Kamp if (indx != namelen) 461946bb7a2SPoul-Henning Kamp return EISDIR; 462946bb7a2SPoul-Henning Kamp goto found; 463946bb7a2SPoul-Henning Kamp } 464946bb7a2SPoul-Henning Kamp } else { 465946bb7a2SPoul-Henning Kamp oidpp++; 466946bb7a2SPoul-Henning Kamp } 467946bb7a2SPoul-Henning Kamp } 468946bb7a2SPoul-Henning Kamp return ENOENT; 469946bb7a2SPoul-Henning Kamp found: 470946bb7a2SPoul-Henning Kamp if (!(*oidpp)->oid_fmt) 471946bb7a2SPoul-Henning Kamp return ENOENT; 47265d0bc13SPoul-Henning Kamp error = SYSCTL_OUT(req, 47365d0bc13SPoul-Henning Kamp &(*oidpp)->oid_kind, sizeof((*oidpp)->oid_kind)); 47465d0bc13SPoul-Henning Kamp if (!error) 47565d0bc13SPoul-Henning Kamp error = SYSCTL_OUT(req, (*oidpp)->oid_fmt, 47665d0bc13SPoul-Henning Kamp strlen((*oidpp)->oid_fmt)+1); 47765d0bc13SPoul-Henning Kamp return (error); 478946bb7a2SPoul-Henning Kamp } 479946bb7a2SPoul-Henning Kamp 480946bb7a2SPoul-Henning Kamp 481946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD, sysctl_sysctl_oidfmt, ""); 482946bb7a2SPoul-Henning Kamp 483946bb7a2SPoul-Henning Kamp /* 484946bb7a2SPoul-Henning Kamp * Default "handler" functions. 485946bb7a2SPoul-Henning Kamp */ 4862e210993SPoul-Henning Kamp 487ae0eb976SPoul-Henning Kamp /* 488ae0eb976SPoul-Henning Kamp * Handle an integer, signed or unsigned. 489ae0eb976SPoul-Henning Kamp * Two cases: 490ae0eb976SPoul-Henning Kamp * a variable: point arg1 at it. 491ae0eb976SPoul-Henning Kamp * a constant: pass it in arg2. 492ae0eb976SPoul-Henning Kamp */ 493ae0eb976SPoul-Henning Kamp 4943a34a5c3SPoul-Henning Kamp int 4953a34a5c3SPoul-Henning Kamp sysctl_handle_int SYSCTL_HANDLER_ARGS 496b396cd83SPoul-Henning Kamp { 497ae0eb976SPoul-Henning Kamp int error = 0; 498b396cd83SPoul-Henning Kamp 499ae0eb976SPoul-Henning Kamp if (arg1) 500ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, sizeof(int)); 5011fbf1f71SBruce Evans else 502ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, &arg2, sizeof(int)); 503b396cd83SPoul-Henning Kamp 504ae0eb976SPoul-Henning Kamp if (error || !req->newptr) 505ae0eb976SPoul-Henning Kamp return (error); 506b396cd83SPoul-Henning Kamp 507ae0eb976SPoul-Henning Kamp if (!arg1) 508ae0eb976SPoul-Henning Kamp error = EPERM; 509ae0eb976SPoul-Henning Kamp else 510ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, sizeof(int)); 511ae0eb976SPoul-Henning Kamp return (error); 512b396cd83SPoul-Henning Kamp } 513b396cd83SPoul-Henning Kamp 514ae0eb976SPoul-Henning Kamp /* 515ae0eb976SPoul-Henning Kamp * Handle our generic '\0' terminated 'C' string. 516ae0eb976SPoul-Henning Kamp * Two cases: 517ae0eb976SPoul-Henning Kamp * a variable string: point arg1 at it, arg2 is max length. 518ae0eb976SPoul-Henning Kamp * a constant string: point arg1 at it, arg2 is zero. 519ae0eb976SPoul-Henning Kamp */ 520ae0eb976SPoul-Henning Kamp 5213a34a5c3SPoul-Henning Kamp int 5223a34a5c3SPoul-Henning Kamp sysctl_handle_string SYSCTL_HANDLER_ARGS 523b396cd83SPoul-Henning Kamp { 524ae0eb976SPoul-Henning Kamp int error=0; 525b396cd83SPoul-Henning Kamp 526ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, strlen((char *)arg1)+1); 527b396cd83SPoul-Henning Kamp 528deae269aSPoul-Henning Kamp if (error || !req->newptr || !arg2) 529ae0eb976SPoul-Henning Kamp return (error); 530ae0eb976SPoul-Henning Kamp 531ae0eb976SPoul-Henning Kamp if ((req->newlen - req->newidx) > arg2) { 532ae0eb976SPoul-Henning Kamp error = E2BIG; 533ae0eb976SPoul-Henning Kamp } else { 534ae0eb976SPoul-Henning Kamp arg2 = (req->newlen - req->newidx); 535ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, arg2); 536ae0eb976SPoul-Henning Kamp ((char *)arg1)[arg2] = '\0'; 537b396cd83SPoul-Henning Kamp } 538b396cd83SPoul-Henning Kamp 5392e210993SPoul-Henning Kamp return (error); 540b396cd83SPoul-Henning Kamp } 541b396cd83SPoul-Henning Kamp 542ae0eb976SPoul-Henning Kamp /* 543ae0eb976SPoul-Henning Kamp * Handle any kind of opaque data. 544ae0eb976SPoul-Henning Kamp * arg1 points to it, arg2 is the size. 545ae0eb976SPoul-Henning Kamp */ 546ae0eb976SPoul-Henning Kamp 5473a34a5c3SPoul-Henning Kamp int 5483a34a5c3SPoul-Henning Kamp sysctl_handle_opaque SYSCTL_HANDLER_ARGS 549b396cd83SPoul-Henning Kamp { 550ae0eb976SPoul-Henning Kamp int error; 551b396cd83SPoul-Henning Kamp 552ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, arg2); 553b396cd83SPoul-Henning Kamp 554ae0eb976SPoul-Henning Kamp if (error || !req->newptr) 555ae0eb976SPoul-Henning Kamp return (error); 556ae0eb976SPoul-Henning Kamp 557ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, arg2); 558ae0eb976SPoul-Henning Kamp 559ae0eb976SPoul-Henning Kamp return (error); 560b396cd83SPoul-Henning Kamp } 561ae0eb976SPoul-Henning Kamp 562deae269aSPoul-Henning Kamp /* 563deae269aSPoul-Henning Kamp * Transfer functions to/from kernel space. 564deae269aSPoul-Henning Kamp * XXX: rather untested at this point 565deae269aSPoul-Henning Kamp */ 566deae269aSPoul-Henning Kamp static int 5673ac9f819SPoul-Henning Kamp sysctl_old_kernel(struct sysctl_req *req, const void *p, int l) 568ae0eb976SPoul-Henning Kamp { 569deae269aSPoul-Henning Kamp int i = 0; 570deae269aSPoul-Henning Kamp 571deae269aSPoul-Henning Kamp if (req->oldptr) { 572deae269aSPoul-Henning Kamp i = min(req->oldlen - req->oldidx, l); 573deae269aSPoul-Henning Kamp if (i > 0) 57409a8dfa2SBruce Evans bcopy(p, (char *)req->oldptr + req->oldidx, i); 575ae0eb976SPoul-Henning Kamp } 576deae269aSPoul-Henning Kamp req->oldidx += l; 5771c346c70SNate Williams if (req->oldptr && i != l) 578ae0eb976SPoul-Henning Kamp return (ENOMEM); 5792e210993SPoul-Henning Kamp return (0); 580ae0eb976SPoul-Henning Kamp } 581ae0eb976SPoul-Henning Kamp 582deae269aSPoul-Henning Kamp static int 5831c346c70SNate Williams sysctl_new_kernel(struct sysctl_req *req, void *p, int l) 584ae0eb976SPoul-Henning Kamp { 585deae269aSPoul-Henning Kamp if (!req->newptr) 586deae269aSPoul-Henning Kamp return 0; 587deae269aSPoul-Henning Kamp if (req->newlen - req->newidx < l) 588ae0eb976SPoul-Henning Kamp return (EINVAL); 58909a8dfa2SBruce Evans bcopy((char *)req->newptr + req->newidx, p, l); 590ae0eb976SPoul-Henning Kamp req->newidx += l; 591ae0eb976SPoul-Henning Kamp return (0); 592ae0eb976SPoul-Henning Kamp } 593ae0eb976SPoul-Henning Kamp 5941c346c70SNate Williams int 5951c346c70SNate Williams kernel_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen, int *retval) 5961c346c70SNate Williams { 5971c346c70SNate Williams int error = 0; 5981c346c70SNate Williams struct sysctl_req req; 5991c346c70SNate Williams 6001c346c70SNate Williams bzero(&req, sizeof req); 6011c346c70SNate Williams 6021c346c70SNate Williams req.p = p; 6031c346c70SNate Williams 6041c346c70SNate Williams if (oldlenp) { 6051c346c70SNate Williams req.oldlen = *oldlenp; 6061c346c70SNate Williams } 6071c346c70SNate Williams 6081c346c70SNate Williams if (old) { 6091c346c70SNate Williams req.oldptr= old; 6101c346c70SNate Williams } 6111c346c70SNate Williams 6121c346c70SNate Williams if (newlen) { 6131c346c70SNate Williams req.newlen = newlen; 6141c346c70SNate Williams req.newptr = new; 6151c346c70SNate Williams } 6161c346c70SNate Williams 6171c346c70SNate Williams req.oldfunc = sysctl_old_kernel; 6181c346c70SNate Williams req.newfunc = sysctl_new_kernel; 6191c346c70SNate Williams req.lock = 1; 6201c346c70SNate Williams 6211c346c70SNate Williams /* XXX this should probably be done in a general way */ 6221c346c70SNate Williams while (memlock.sl_lock) { 6231c346c70SNate Williams memlock.sl_want = 1; 6241c346c70SNate Williams (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 6251c346c70SNate Williams memlock.sl_locked++; 6261c346c70SNate Williams } 6271c346c70SNate Williams memlock.sl_lock = 1; 6281c346c70SNate Williams 6291c346c70SNate Williams error = sysctl_root(0, name, namelen, &req); 6301c346c70SNate Williams 6311c346c70SNate Williams if (req.lock == 2) 6321c346c70SNate Williams vsunlock(req.oldptr, req.oldlen, B_WRITE); 6331c346c70SNate Williams 6341c346c70SNate Williams memlock.sl_lock = 0; 6351c346c70SNate Williams 6361c346c70SNate Williams if (memlock.sl_want) { 6371c346c70SNate Williams memlock.sl_want = 0; 6381c346c70SNate Williams wakeup((caddr_t)&memlock); 6391c346c70SNate Williams } 6401c346c70SNate Williams 6411c346c70SNate Williams if (error && error != ENOMEM) 6421c346c70SNate Williams return (error); 6431c346c70SNate Williams 6441c346c70SNate Williams if (retval) { 6451c346c70SNate Williams if (req.oldptr && req.oldidx > req.oldlen) 6461c346c70SNate Williams *retval = req.oldlen; 6471c346c70SNate Williams else 6481c346c70SNate Williams *retval = req.oldidx; 6491c346c70SNate Williams } 6501c346c70SNate Williams return (error); 6511c346c70SNate Williams } 6521c346c70SNate Williams 653deae269aSPoul-Henning Kamp /* 654deae269aSPoul-Henning Kamp * Transfer function to/from user space. 655deae269aSPoul-Henning Kamp */ 656deae269aSPoul-Henning Kamp static int 6573ac9f819SPoul-Henning Kamp sysctl_old_user(struct sysctl_req *req, const void *p, int l) 658ae0eb976SPoul-Henning Kamp { 659deae269aSPoul-Henning Kamp int error = 0, i = 0; 660ae0eb976SPoul-Henning Kamp 6614b2af45fSPoul-Henning Kamp if (req->lock == 1 && req->oldptr) { 6624b2af45fSPoul-Henning Kamp vslock(req->oldptr, req->oldlen); 6634b2af45fSPoul-Henning Kamp req->lock = 2; 6644b2af45fSPoul-Henning Kamp } 665deae269aSPoul-Henning Kamp if (req->oldptr) { 666deae269aSPoul-Henning Kamp i = min(req->oldlen - req->oldidx, l); 667deae269aSPoul-Henning Kamp if (i > 0) 66809a8dfa2SBruce Evans error = copyout(p, (char *)req->oldptr + req->oldidx, 66909a8dfa2SBruce Evans i); 670deae269aSPoul-Henning Kamp } 671deae269aSPoul-Henning Kamp req->oldidx += l; 672ae0eb976SPoul-Henning Kamp if (error) 673ae0eb976SPoul-Henning Kamp return (error); 674deae269aSPoul-Henning Kamp if (req->oldptr && i < l) 675ae0eb976SPoul-Henning Kamp return (ENOMEM); 676deae269aSPoul-Henning Kamp return (0); 677ae0eb976SPoul-Henning Kamp } 678ae0eb976SPoul-Henning Kamp 679deae269aSPoul-Henning Kamp static int 680ae0eb976SPoul-Henning Kamp sysctl_new_user(struct sysctl_req *req, void *p, int l) 681ae0eb976SPoul-Henning Kamp { 68216cd04a3SPoul-Henning Kamp int error; 683deae269aSPoul-Henning Kamp 684deae269aSPoul-Henning Kamp if (!req->newptr) 685deae269aSPoul-Henning Kamp return 0; 686deae269aSPoul-Henning Kamp if (req->newlen - req->newidx < l) 687ae0eb976SPoul-Henning Kamp return (EINVAL); 68809a8dfa2SBruce Evans error = copyin((char *)req->newptr + req->newidx, p, l); 689ae0eb976SPoul-Henning Kamp req->newidx += l; 690ae0eb976SPoul-Henning Kamp return (error); 691b396cd83SPoul-Henning Kamp } 692b396cd83SPoul-Henning Kamp 693df8bae1dSRodney W. Grimes /* 6942e210993SPoul-Henning Kamp * Traverse our tree, and find the right node, execute whatever it points 6952e210993SPoul-Henning Kamp * at, and return the resulting error code. 6962e210993SPoul-Henning Kamp */ 6972e210993SPoul-Henning Kamp 6982e210993SPoul-Henning Kamp int 6992e210993SPoul-Henning Kamp sysctl_root SYSCTL_HANDLER_ARGS 7002e210993SPoul-Henning Kamp { 7012e210993SPoul-Henning Kamp int *name = (int *) arg1; 702946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 7032e210993SPoul-Henning Kamp int indx, i, j; 7042e210993SPoul-Henning Kamp struct sysctl_oid **oidpp; 7052e210993SPoul-Henning Kamp struct linker_set *lsp = &sysctl_; 7062e210993SPoul-Henning Kamp 7072e210993SPoul-Henning Kamp j = lsp->ls_length; 7082e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **) lsp->ls_items; 7092e210993SPoul-Henning Kamp 7102e210993SPoul-Henning Kamp indx = 0; 7112e210993SPoul-Henning Kamp while (j-- && indx < CTL_MAXNAME) { 712787d58f2SPoul-Henning Kamp if (*oidpp && ((*oidpp)->oid_number == name[indx])) { 7132e210993SPoul-Henning Kamp indx++; 7144b2af45fSPoul-Henning Kamp if ((*oidpp)->oid_kind & CTLFLAG_NOLOCK) 7154b2af45fSPoul-Henning Kamp req->lock = 0; 7162e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 7172e210993SPoul-Henning Kamp if ((*oidpp)->oid_handler) 7182e210993SPoul-Henning Kamp goto found; 7192e210993SPoul-Henning Kamp if (indx == namelen) 7202e210993SPoul-Henning Kamp return ENOENT; 7212e210993SPoul-Henning Kamp lsp = (struct linker_set*)(*oidpp)->oid_arg1; 7222e210993SPoul-Henning Kamp j = lsp->ls_length; 7232e210993SPoul-Henning Kamp oidpp = (struct sysctl_oid **)lsp->ls_items; 7242e210993SPoul-Henning Kamp } else { 7252e210993SPoul-Henning Kamp if (indx != namelen) 7262e210993SPoul-Henning Kamp return EISDIR; 7272e210993SPoul-Henning Kamp goto found; 7282e210993SPoul-Henning Kamp } 7292e210993SPoul-Henning Kamp } else { 7302e210993SPoul-Henning Kamp oidpp++; 7312e210993SPoul-Henning Kamp } 7322e210993SPoul-Henning Kamp } 733deae269aSPoul-Henning Kamp return ENOENT; 7342e210993SPoul-Henning Kamp found: 7352e210993SPoul-Henning Kamp /* If writing isn't allowed */ 736ae0eb976SPoul-Henning Kamp if (req->newptr && !((*oidpp)->oid_kind & CTLFLAG_WR)) 7372e210993SPoul-Henning Kamp return (EPERM); 7382e210993SPoul-Henning Kamp 7393ac9f819SPoul-Henning Kamp /* Most likely only root can write */ 7403ac9f819SPoul-Henning Kamp if (!((*oidpp)->oid_kind & CTLFLAG_ANYBODY) && 7413ac9f819SPoul-Henning Kamp req->newptr && req->p && 7423ac9f819SPoul-Henning Kamp (i = suser(req->p->p_ucred, &req->p->p_acflag))) 7433ac9f819SPoul-Henning Kamp return (i); 7443ac9f819SPoul-Henning Kamp 7452e210993SPoul-Henning Kamp if (!(*oidpp)->oid_handler) 7462e210993SPoul-Henning Kamp return EINVAL; 7472e210993SPoul-Henning Kamp 7482e210993SPoul-Henning Kamp if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 7492e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 7502e210993SPoul-Henning Kamp name + indx, namelen - indx, 751ae0eb976SPoul-Henning Kamp req); 7522e210993SPoul-Henning Kamp } else { 7532e210993SPoul-Henning Kamp i = ((*oidpp)->oid_handler) (*oidpp, 7542e210993SPoul-Henning Kamp (*oidpp)->oid_arg1, (*oidpp)->oid_arg2, 755ae0eb976SPoul-Henning Kamp req); 7562e210993SPoul-Henning Kamp } 7572e210993SPoul-Henning Kamp return (i); 7582e210993SPoul-Henning Kamp } 7592e210993SPoul-Henning Kamp 760d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 761b8da2396SPoul-Henning Kamp struct sysctl_args { 762b8da2396SPoul-Henning Kamp int *name; 763b8da2396SPoul-Henning Kamp u_int namelen; 764b8da2396SPoul-Henning Kamp void *old; 765b8da2396SPoul-Henning Kamp size_t *oldlenp; 766b8da2396SPoul-Henning Kamp void *new; 767b8da2396SPoul-Henning Kamp size_t newlen; 768b8da2396SPoul-Henning Kamp }; 769d2d3e875SBruce Evans #endif 770b8da2396SPoul-Henning Kamp 771df8bae1dSRodney W. Grimes int 7724b2af45fSPoul-Henning Kamp __sysctl(struct proc *p, struct sysctl_args *uap, int *retval) 773df8bae1dSRodney W. Grimes { 774deae269aSPoul-Henning Kamp int error, i, j, name[CTL_MAXNAME]; 775b396cd83SPoul-Henning Kamp 776df8bae1dSRodney W. Grimes if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 777df8bae1dSRodney W. Grimes return (EINVAL); 778b396cd83SPoul-Henning Kamp 779797f2d22SPoul-Henning Kamp error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 780797f2d22SPoul-Henning Kamp if (error) 781df8bae1dSRodney W. Grimes return (error); 782df8bae1dSRodney W. Grimes 783deae269aSPoul-Henning Kamp error = userland_sysctl(p, name, uap->namelen, 784b8da2396SPoul-Henning Kamp uap->old, uap->oldlenp, 0, 785deae269aSPoul-Henning Kamp uap->new, uap->newlen, &j); 786deae269aSPoul-Henning Kamp if (error && error != ENOMEM) 787deae269aSPoul-Henning Kamp return (error); 788deae269aSPoul-Henning Kamp if (uap->oldlenp) { 789deae269aSPoul-Henning Kamp i = copyout(&j, uap->oldlenp, sizeof(j)); 790deae269aSPoul-Henning Kamp if (i) 791deae269aSPoul-Henning Kamp return (i); 792deae269aSPoul-Henning Kamp } 793deae269aSPoul-Henning Kamp return (error); 794b8da2396SPoul-Henning Kamp } 795b8da2396SPoul-Henning Kamp 796b8da2396SPoul-Henning Kamp /* 797b8da2396SPoul-Henning Kamp * This is used from various compatibility syscalls too. That's why name 798b8da2396SPoul-Henning Kamp * must be in kernel space. 799b8da2396SPoul-Henning Kamp */ 800b8da2396SPoul-Henning Kamp int 801b8da2396SPoul-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) 802b8da2396SPoul-Henning Kamp { 8034b2af45fSPoul-Henning Kamp int error = 0; 8047a69d923SPoul-Henning Kamp struct sysctl_req req, req2; 805ae0eb976SPoul-Henning Kamp 806ae0eb976SPoul-Henning Kamp bzero(&req, sizeof req); 807b8da2396SPoul-Henning Kamp 80816cd04a3SPoul-Henning Kamp req.p = p; 80916cd04a3SPoul-Henning Kamp 810b8da2396SPoul-Henning Kamp if (oldlenp) { 811b8da2396SPoul-Henning Kamp if (inkernel) { 812ae0eb976SPoul-Henning Kamp req.oldlen = *oldlenp; 813b8da2396SPoul-Henning Kamp } else { 814deae269aSPoul-Henning Kamp error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp)); 815b8da2396SPoul-Henning Kamp if (error) 816b8da2396SPoul-Henning Kamp return (error); 817b8da2396SPoul-Henning Kamp } 818b8da2396SPoul-Henning Kamp } 819b8da2396SPoul-Henning Kamp 820ae0eb976SPoul-Henning Kamp if (old) { 821ae0eb976SPoul-Henning Kamp if (!useracc(old, req.oldlen, B_WRITE)) 822ae0eb976SPoul-Henning Kamp return (EFAULT); 823ae0eb976SPoul-Henning Kamp req.oldptr= old; 824ae0eb976SPoul-Henning Kamp } 8252e210993SPoul-Henning Kamp 826b8da2396SPoul-Henning Kamp if (newlen) { 827ae0eb976SPoul-Henning Kamp if (!useracc(new, req.newlen, B_READ)) 828ae0eb976SPoul-Henning Kamp return (EFAULT); 829ae0eb976SPoul-Henning Kamp req.newlen = newlen; 830ae0eb976SPoul-Henning Kamp req.newptr = new; 831b396cd83SPoul-Henning Kamp } 832b396cd83SPoul-Henning Kamp 833ae0eb976SPoul-Henning Kamp req.oldfunc = sysctl_old_user; 834ae0eb976SPoul-Henning Kamp req.newfunc = sysctl_new_user; 8354b2af45fSPoul-Henning Kamp req.lock = 1; 8364b2af45fSPoul-Henning Kamp 8374b2af45fSPoul-Henning Kamp /* XXX this should probably be done in a general way */ 8384b2af45fSPoul-Henning Kamp while (memlock.sl_lock) { 8394b2af45fSPoul-Henning Kamp memlock.sl_want = 1; 8404b2af45fSPoul-Henning Kamp (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 8414b2af45fSPoul-Henning Kamp memlock.sl_locked++; 8424b2af45fSPoul-Henning Kamp } 8434b2af45fSPoul-Henning Kamp memlock.sl_lock = 1; 844ae0eb976SPoul-Henning Kamp 8457a69d923SPoul-Henning Kamp do { 8467a69d923SPoul-Henning Kamp req2 = req; 8477a69d923SPoul-Henning Kamp error = sysctl_root(0, name, namelen, &req2); 8487a69d923SPoul-Henning Kamp } while (error == EAGAIN); 849b396cd83SPoul-Henning Kamp 8507a69d923SPoul-Henning Kamp req = req2; 8514b2af45fSPoul-Henning Kamp if (req.lock == 2) 8524b2af45fSPoul-Henning Kamp vsunlock(req.oldptr, req.oldlen, B_WRITE); 8534b2af45fSPoul-Henning Kamp 8544b2af45fSPoul-Henning Kamp memlock.sl_lock = 0; 8554b2af45fSPoul-Henning Kamp 8564b2af45fSPoul-Henning Kamp if (memlock.sl_want) { 8574b2af45fSPoul-Henning Kamp memlock.sl_want = 0; 8584b2af45fSPoul-Henning Kamp wakeup((caddr_t)&memlock); 8594b2af45fSPoul-Henning Kamp } 8604b2af45fSPoul-Henning Kamp 861deae269aSPoul-Henning Kamp if (error && error != ENOMEM) 862deae269aSPoul-Henning Kamp return (error); 863deae269aSPoul-Henning Kamp 864deae269aSPoul-Henning Kamp if (retval) { 865deae269aSPoul-Henning Kamp if (req.oldptr && req.oldidx > req.oldlen) 866ae0eb976SPoul-Henning Kamp *retval = req.oldlen; 867deae269aSPoul-Henning Kamp else 868deae269aSPoul-Henning Kamp *retval = req.oldidx; 869b8da2396SPoul-Henning Kamp } 8702e210993SPoul-Henning Kamp return (error); 871df8bae1dSRodney W. Grimes } 872df8bae1dSRodney W. Grimes 873df8bae1dSRodney W. Grimes #ifdef COMPAT_43 874df8bae1dSRodney W. Grimes #include <sys/socket.h> 87545ec3b38SPoul-Henning Kamp #include <vm/vm_param.h> 87645ec3b38SPoul-Henning Kamp 877df8bae1dSRodney W. Grimes #define KINFO_PROC (0<<8) 878df8bae1dSRodney W. Grimes #define KINFO_RT (1<<8) 879df8bae1dSRodney W. Grimes #define KINFO_VNODE (2<<8) 880df8bae1dSRodney W. Grimes #define KINFO_FILE (3<<8) 881df8bae1dSRodney W. Grimes #define KINFO_METER (4<<8) 882df8bae1dSRodney W. Grimes #define KINFO_LOADAVG (5<<8) 883df8bae1dSRodney W. Grimes #define KINFO_CLOCKRATE (6<<8) 884df8bae1dSRodney W. Grimes 8856ece4a51SPeter Wemm /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ 8866ece4a51SPeter Wemm #define KINFO_BSDI_SYSINFO (101<<8) 8876ece4a51SPeter Wemm 8886ece4a51SPeter Wemm /* 8896ece4a51SPeter Wemm * XXX this is bloat, but I hope it's better here than on the potentially 8906ece4a51SPeter Wemm * limited kernel stack... -Peter 8916ece4a51SPeter Wemm */ 8926ece4a51SPeter Wemm 89387b6de2bSPoul-Henning Kamp static struct { 8946ece4a51SPeter Wemm int bsdi_machine; /* "i386" on BSD/386 */ 8956ece4a51SPeter Wemm /* ^^^ this is an offset to the string, relative to the struct start */ 8966ece4a51SPeter Wemm char *pad0; 8976ece4a51SPeter Wemm long pad1; 8986ece4a51SPeter Wemm long pad2; 8996ece4a51SPeter Wemm long pad3; 9006ece4a51SPeter Wemm u_long pad4; 9016ece4a51SPeter Wemm u_long pad5; 9026ece4a51SPeter Wemm u_long pad6; 9036ece4a51SPeter Wemm 9046ece4a51SPeter Wemm int bsdi_ostype; /* "BSD/386" on BSD/386 */ 9056ece4a51SPeter Wemm int bsdi_osrelease; /* "1.1" on BSD/386 */ 9066ece4a51SPeter Wemm long pad7; 9076ece4a51SPeter Wemm long pad8; 9086ece4a51SPeter Wemm char *pad9; 9096ece4a51SPeter Wemm 9106ece4a51SPeter Wemm long pad10; 9116ece4a51SPeter Wemm long pad11; 9126ece4a51SPeter Wemm int pad12; 9136ece4a51SPeter Wemm long pad13; 9146ece4a51SPeter Wemm quad_t pad14; 9156ece4a51SPeter Wemm long pad15; 9166ece4a51SPeter Wemm 9176ece4a51SPeter Wemm struct timeval pad16; 9186ece4a51SPeter Wemm /* we dont set this, because BSDI's uname used gethostname() instead */ 9196ece4a51SPeter Wemm int bsdi_hostname; /* hostname on BSD/386 */ 9206ece4a51SPeter Wemm 9216ece4a51SPeter Wemm /* the actual string data is appended here */ 9226ece4a51SPeter Wemm 9236ece4a51SPeter Wemm } bsdi_si; 9246ece4a51SPeter Wemm /* 9256ece4a51SPeter Wemm * this data is appended to the end of the bsdi_si structure during copyout. 9266ece4a51SPeter Wemm * The "char *" offsets are relative to the base of the bsdi_si struct. 9276ece4a51SPeter Wemm * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings 9286ece4a51SPeter Wemm * should not exceed the length of the buffer here... (or else!! :-) 9296ece4a51SPeter Wemm */ 93087b6de2bSPoul-Henning Kamp static char bsdi_strings[80]; /* It had better be less than this! */ 9316ece4a51SPeter Wemm 932d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 933df8bae1dSRodney W. Grimes struct getkerninfo_args { 934df8bae1dSRodney W. Grimes int op; 935df8bae1dSRodney W. Grimes char *where; 936df8bae1dSRodney W. Grimes int *size; 937df8bae1dSRodney W. Grimes int arg; 938df8bae1dSRodney W. Grimes }; 939d2d3e875SBruce Evans #endif 940df8bae1dSRodney W. Grimes 94126f9a767SRodney W. Grimes int 9424b2af45fSPoul-Henning Kamp ogetkerninfo(struct proc *p, struct getkerninfo_args *uap, int *retval) 943df8bae1dSRodney W. Grimes { 944b8da2396SPoul-Henning Kamp int error, name[6]; 945df8bae1dSRodney W. Grimes u_int size; 946df8bae1dSRodney W. Grimes 947df8bae1dSRodney W. Grimes switch (uap->op & 0xff00) { 948df8bae1dSRodney W. Grimes 949df8bae1dSRodney W. Grimes case KINFO_RT: 950b8da2396SPoul-Henning Kamp name[0] = CTL_NET; 951b8da2396SPoul-Henning Kamp name[1] = PF_ROUTE; 952b8da2396SPoul-Henning Kamp name[2] = 0; 953b8da2396SPoul-Henning Kamp name[3] = (uap->op & 0xff0000) >> 16; 954b8da2396SPoul-Henning Kamp name[4] = uap->op & 0xff; 955b8da2396SPoul-Henning Kamp name[5] = uap->arg; 956b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 6, uap->where, uap->size, 9574b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 958df8bae1dSRodney W. Grimes break; 959df8bae1dSRodney W. Grimes 960df8bae1dSRodney W. Grimes case KINFO_VNODE: 961b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 962b8da2396SPoul-Henning Kamp name[1] = KERN_VNODE; 963b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 9644b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 965df8bae1dSRodney W. Grimes break; 966df8bae1dSRodney W. Grimes 967df8bae1dSRodney W. Grimes case KINFO_PROC: 968b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 969b8da2396SPoul-Henning Kamp name[1] = KERN_PROC; 970b8da2396SPoul-Henning Kamp name[2] = uap->op & 0xff; 971b8da2396SPoul-Henning Kamp name[3] = uap->arg; 972b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 4, uap->where, uap->size, 9734b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 974df8bae1dSRodney W. Grimes break; 975df8bae1dSRodney W. Grimes 976df8bae1dSRodney W. Grimes case KINFO_FILE: 977b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 978b8da2396SPoul-Henning Kamp name[1] = KERN_FILE; 979b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 9804b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 981df8bae1dSRodney W. Grimes break; 982df8bae1dSRodney W. Grimes 983df8bae1dSRodney W. Grimes case KINFO_METER: 984b8da2396SPoul-Henning Kamp name[0] = CTL_VM; 985b8da2396SPoul-Henning Kamp name[1] = VM_METER; 986b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 9874b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 988df8bae1dSRodney W. Grimes break; 989df8bae1dSRodney W. Grimes 990df8bae1dSRodney W. Grimes case KINFO_LOADAVG: 991b8da2396SPoul-Henning Kamp name[0] = CTL_VM; 992b8da2396SPoul-Henning Kamp name[1] = VM_LOADAVG; 993b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 9944b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 995df8bae1dSRodney W. Grimes break; 996df8bae1dSRodney W. Grimes 997df8bae1dSRodney W. Grimes case KINFO_CLOCKRATE: 998b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 999b8da2396SPoul-Henning Kamp name[1] = KERN_CLOCKRATE; 1000b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10014b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1002df8bae1dSRodney W. Grimes break; 1003df8bae1dSRodney W. Grimes 10046ece4a51SPeter Wemm case KINFO_BSDI_SYSINFO: { 10056ece4a51SPeter Wemm /* 10066ece4a51SPeter Wemm * this is pretty crude, but it's just enough for uname() 10076ece4a51SPeter Wemm * from BSDI's 1.x libc to work. 10086ece4a51SPeter Wemm * 10096ece4a51SPeter Wemm * In particular, it doesn't return the same results when 10106ece4a51SPeter Wemm * the supplied buffer is too small. BSDI's version apparently 10116ece4a51SPeter Wemm * will return the amount copied, and set the *size to how 10126ece4a51SPeter Wemm * much was needed. The emulation framework here isn't capable 10136ece4a51SPeter Wemm * of that, so we just set both to the amount copied. 10146ece4a51SPeter Wemm * BSDI's 2.x product apparently fails with ENOMEM in this 10156ece4a51SPeter Wemm * scenario. 10166ece4a51SPeter Wemm */ 10176ece4a51SPeter Wemm 10186ece4a51SPeter Wemm u_int needed; 10196ece4a51SPeter Wemm u_int left; 10206ece4a51SPeter Wemm char *s; 10216ece4a51SPeter Wemm 10226ece4a51SPeter Wemm bzero((char *)&bsdi_si, sizeof(bsdi_si)); 10236ece4a51SPeter Wemm bzero(bsdi_strings, sizeof(bsdi_strings)); 10246ece4a51SPeter Wemm 10256ece4a51SPeter Wemm s = bsdi_strings; 10266ece4a51SPeter Wemm 10276ece4a51SPeter Wemm bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); 10286ece4a51SPeter Wemm strcpy(s, ostype); 10296ece4a51SPeter Wemm s += strlen(s) + 1; 10306ece4a51SPeter Wemm 10316ece4a51SPeter Wemm bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); 10326ece4a51SPeter Wemm strcpy(s, osrelease); 10336ece4a51SPeter Wemm s += strlen(s) + 1; 10346ece4a51SPeter Wemm 10356ece4a51SPeter Wemm bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); 10366ece4a51SPeter Wemm strcpy(s, machine); 10376ece4a51SPeter Wemm s += strlen(s) + 1; 10386ece4a51SPeter Wemm 10396ece4a51SPeter Wemm needed = sizeof(bsdi_si) + (s - bsdi_strings); 10406ece4a51SPeter Wemm 10416ece4a51SPeter Wemm if (uap->where == NULL) { 10426ece4a51SPeter Wemm /* process is asking how much buffer to supply.. */ 10436ece4a51SPeter Wemm size = needed; 10446ece4a51SPeter Wemm error = 0; 10456ece4a51SPeter Wemm break; 10466ece4a51SPeter Wemm } 10476ece4a51SPeter Wemm 10486ece4a51SPeter Wemm 10496ece4a51SPeter Wemm /* if too much buffer supplied, trim it down */ 10506ece4a51SPeter Wemm if (size > needed) 10516ece4a51SPeter Wemm size = needed; 10526ece4a51SPeter Wemm 10536ece4a51SPeter Wemm /* how much of the buffer is remaining */ 10546ece4a51SPeter Wemm left = size; 10556ece4a51SPeter Wemm 10566ece4a51SPeter Wemm if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) 10576ece4a51SPeter Wemm break; 10586ece4a51SPeter Wemm 10596ece4a51SPeter Wemm /* is there any point in continuing? */ 10606ece4a51SPeter Wemm if (left > sizeof(bsdi_si)) { 10616ece4a51SPeter Wemm left -= sizeof(bsdi_si); 10626ece4a51SPeter Wemm error = copyout(&bsdi_strings, 10636ece4a51SPeter Wemm uap->where + sizeof(bsdi_si), left); 10646ece4a51SPeter Wemm } 10656ece4a51SPeter Wemm break; 10666ece4a51SPeter Wemm } 10676ece4a51SPeter Wemm 1068df8bae1dSRodney W. Grimes default: 1069df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 1070df8bae1dSRodney W. Grimes } 1071df8bae1dSRodney W. Grimes if (error) 1072df8bae1dSRodney W. Grimes return (error); 1073df8bae1dSRodney W. Grimes *retval = size; 1074df8bae1dSRodney W. Grimes if (uap->size) 1075df8bae1dSRodney W. Grimes error = copyout((caddr_t)&size, (caddr_t)uap->size, 1076df8bae1dSRodney W. Grimes sizeof(size)); 1077df8bae1dSRodney W. Grimes return (error); 1078df8bae1dSRodney W. Grimes } 1079df8bae1dSRodney W. Grimes #endif /* COMPAT_43 */ 1080