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 407f4173ccSPoul-Henning Kamp * $Id: kern_sysctl.c,v 1.84 1999/02/16 10:49:48 dfr 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 69ce02431fSDoug Rabson struct sysctl_oid_list sysctl__children; /* root list */ 70787d58f2SPoul-Henning Kamp 71946bb7a2SPoul-Henning Kamp /* 72946bb7a2SPoul-Henning Kamp * Initialization of the MIB tree. 73946bb7a2SPoul-Henning Kamp * 74ce02431fSDoug Rabson * Order by number in each list. 75946bb7a2SPoul-Henning Kamp */ 764b2af45fSPoul-Henning Kamp 77ce02431fSDoug Rabson void sysctl_register_oid(struct sysctl_oid *oidp) 78787d58f2SPoul-Henning Kamp { 79ce02431fSDoug Rabson struct sysctl_oid_list *parent = oidp->oid_parent; 80ce02431fSDoug Rabson struct sysctl_oid *p; 81ce02431fSDoug Rabson struct sysctl_oid *q; 82ce02431fSDoug Rabson int n; 833c8e79ddSBruce Evans 84ce02431fSDoug Rabson /* 85ce02431fSDoug Rabson * If this oid has a number OID_AUTO, give it a number which 86ce02431fSDoug Rabson * is greater than any current oid. Make sure it is at least 87ce02431fSDoug Rabson * 100 to leave space for pre-assigned oid numbers. 88ce02431fSDoug Rabson */ 89ce02431fSDoug Rabson if (oidp->oid_number == OID_AUTO) { 90ce02431fSDoug Rabson /* First, find the highest oid in the parent list >99 */ 91ce02431fSDoug Rabson n = 99; 92ce02431fSDoug Rabson SLIST_FOREACH(p, parent, oid_link) { 93ce02431fSDoug Rabson if (p->oid_number > n) 94ce02431fSDoug Rabson n = p->oid_number; 95ce02431fSDoug Rabson } 96ce02431fSDoug Rabson oidp->oid_number = n + 1; 97787d58f2SPoul-Henning Kamp } 98787d58f2SPoul-Henning Kamp 99ce02431fSDoug Rabson /* 100ce02431fSDoug Rabson * Insert the oid into the parent's list in order. 101ce02431fSDoug Rabson */ 102ce02431fSDoug Rabson q = NULL; 103ce02431fSDoug Rabson SLIST_FOREACH(p, parent, oid_link) { 104ce02431fSDoug Rabson if (oidp->oid_number < p->oid_number) 105ce02431fSDoug Rabson break; 106ce02431fSDoug Rabson q = p; 107ce02431fSDoug Rabson } 108ce02431fSDoug Rabson if (q) 109ce02431fSDoug Rabson SLIST_INSERT_AFTER(q, oidp, oid_link); 110ce02431fSDoug Rabson else 111ce02431fSDoug Rabson SLIST_INSERT_HEAD(parent, oidp, oid_link); 112ce02431fSDoug Rabson } 113ce02431fSDoug Rabson 114ce02431fSDoug Rabson void sysctl_unregister_oid(struct sysctl_oid *oidp) 115787d58f2SPoul-Henning Kamp { 116ce02431fSDoug Rabson SLIST_REMOVE(oidp->oid_parent, oidp, sysctl_oid, oid_link); 11761220614SPoul-Henning Kamp } 118946bb7a2SPoul-Henning Kamp 119ce02431fSDoug Rabson /* 120ce02431fSDoug Rabson * Bulk-register all the oids in a linker_set. 121ce02431fSDoug Rabson */ 122ce02431fSDoug Rabson void sysctl_register_set(struct linker_set *lsp) 123e99ea9ecSBruce Evans { 124ce02431fSDoug Rabson int count = lsp->ls_length; 125ce02431fSDoug Rabson int i; 126ce02431fSDoug Rabson for (i = 0; i < count; i++) 127ce02431fSDoug Rabson sysctl_register_oid((struct sysctl_oid *) lsp->ls_items[i]); 128e99ea9ecSBruce Evans } 129e99ea9ecSBruce Evans 130ce02431fSDoug Rabson void sysctl_unregister_set(struct linker_set *lsp) 131ce02431fSDoug Rabson { 132ce02431fSDoug Rabson int count = lsp->ls_length; 133ce02431fSDoug Rabson int i; 134ce02431fSDoug Rabson for (i = 0; i < count; i++) 135ce02431fSDoug Rabson sysctl_unregister_oid((struct sysctl_oid *) lsp->ls_items[i]); 136ce02431fSDoug Rabson } 137ce02431fSDoug Rabson 138ce02431fSDoug Rabson /* 139ce02431fSDoug Rabson * Register the kernel's oids on startup. 140ce02431fSDoug Rabson */ 141ce02431fSDoug Rabson extern struct linker_set sysctl_set; 142ce02431fSDoug Rabson 143ce02431fSDoug Rabson static void sysctl_register_all(void *arg) 144ce02431fSDoug Rabson { 145ce02431fSDoug Rabson sysctl_register_set(&sysctl_set); 146ce02431fSDoug Rabson } 147ce02431fSDoug Rabson 148ce02431fSDoug Rabson SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_register_all, 0); 149ce02431fSDoug Rabson 150946bb7a2SPoul-Henning Kamp /* 151946bb7a2SPoul-Henning Kamp * "Staff-functions" 152946bb7a2SPoul-Henning Kamp * 15365d0bc13SPoul-Henning Kamp * These functions implement a presently undocumented interface 15465d0bc13SPoul-Henning Kamp * used by the sysctl program to walk the tree, and get the type 15565d0bc13SPoul-Henning Kamp * so it can print the value. 15665d0bc13SPoul-Henning Kamp * This interface is under work and consideration, and should probably 15765d0bc13SPoul-Henning Kamp * be killed with a big axe by the first person who can find the time. 15865d0bc13SPoul-Henning Kamp * (be aware though, that the proper interface isn't as obvious as it 15965d0bc13SPoul-Henning Kamp * may seem, there are various conflicting requirements. 16065d0bc13SPoul-Henning Kamp * 161946bb7a2SPoul-Henning Kamp * {0,0} printf the entire MIB-tree. 162946bb7a2SPoul-Henning Kamp * {0,1,...} return the name of the "..." OID. 16386415b71SPoul-Henning Kamp * {0,2,...} return the next OID. 164946bb7a2SPoul-Henning Kamp * {0,3} return the OID of the name in "new" 16565d0bc13SPoul-Henning Kamp * {0,4,...} return the kind & format info for the "..." OID. 166946bb7a2SPoul-Henning Kamp */ 167946bb7a2SPoul-Henning Kamp 168787d58f2SPoul-Henning Kamp static void 169ce02431fSDoug Rabson sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i) 170787d58f2SPoul-Henning Kamp { 171ce02431fSDoug Rabson int k; 172ce02431fSDoug Rabson struct sysctl_oid *oidp; 173787d58f2SPoul-Henning Kamp 174ce02431fSDoug Rabson SLIST_FOREACH(oidp, l, oid_link) { 175787d58f2SPoul-Henning Kamp 176787d58f2SPoul-Henning Kamp for (k=0; k<i; k++) 177787d58f2SPoul-Henning Kamp printf(" "); 178787d58f2SPoul-Henning Kamp 179ce02431fSDoug Rabson printf("%d %s ", oidp->oid_number, oidp->oid_name); 180787d58f2SPoul-Henning Kamp 181787d58f2SPoul-Henning Kamp printf("%c%c", 182ce02431fSDoug Rabson oidp->oid_kind & CTLFLAG_RD ? 'R':' ', 183ce02431fSDoug Rabson oidp->oid_kind & CTLFLAG_WR ? 'W':' '); 184787d58f2SPoul-Henning Kamp 185ce02431fSDoug Rabson if (oidp->oid_handler) 18661220614SPoul-Henning Kamp printf(" *Handler"); 18761220614SPoul-Henning Kamp 188ce02431fSDoug Rabson switch (oidp->oid_kind & CTLTYPE) { 189787d58f2SPoul-Henning Kamp case CTLTYPE_NODE: 190787d58f2SPoul-Henning Kamp printf(" Node\n"); 191ce02431fSDoug Rabson if (!oidp->oid_handler) { 192787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node( 193ce02431fSDoug Rabson oidp->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 { 209ce02431fSDoug Rabson sysctl_sysctl_debug_dump_node(&sysctl__children, 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; 221ce02431fSDoug Rabson int error = 0; 222ce02431fSDoug Rabson struct sysctl_oid *oid; 2237f4173ccSPoul-Henning Kamp struct sysctl_oid_list *lsp = &sysctl__children, *lsp2; 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 } 2397f4173ccSPoul-Henning Kamp lsp2 = 0; 240ce02431fSDoug Rabson SLIST_FOREACH(oid, lsp, oid_link) { 241ce02431fSDoug Rabson if (oid->oid_number != *name) 242946bb7a2SPoul-Henning Kamp continue; 243946bb7a2SPoul-Henning Kamp 244946bb7a2SPoul-Henning Kamp if (req->oldidx) 245946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, ".", 1); 246946bb7a2SPoul-Henning Kamp if (!error) 247ce02431fSDoug Rabson error = SYSCTL_OUT(req, oid->oid_name, 248ce02431fSDoug Rabson strlen(oid->oid_name)); 249946bb7a2SPoul-Henning Kamp if (error) 250946bb7a2SPoul-Henning Kamp return (error); 251946bb7a2SPoul-Henning Kamp 252946bb7a2SPoul-Henning Kamp namelen--; 253946bb7a2SPoul-Henning Kamp name++; 254946bb7a2SPoul-Henning Kamp 255ce02431fSDoug Rabson if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE) 256946bb7a2SPoul-Henning Kamp break; 257946bb7a2SPoul-Henning Kamp 258ce02431fSDoug Rabson if (oid->oid_handler) 259946bb7a2SPoul-Henning Kamp break; 260946bb7a2SPoul-Henning Kamp 2617f4173ccSPoul-Henning Kamp lsp2 = (struct sysctl_oid_list *)oid->oid_arg1; 262946bb7a2SPoul-Henning Kamp break; 263946bb7a2SPoul-Henning Kamp } 2647f4173ccSPoul-Henning Kamp lsp = lsp2; 265946bb7a2SPoul-Henning Kamp } 266946bb7a2SPoul-Henning Kamp return (SYSCTL_OUT(req, "", 1)); 267946bb7a2SPoul-Henning Kamp } 268946bb7a2SPoul-Henning Kamp 269946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD, sysctl_sysctl_name, ""); 270946bb7a2SPoul-Henning Kamp 271946bb7a2SPoul-Henning Kamp static int 272ce02431fSDoug Rabson sysctl_sysctl_next_ls (struct sysctl_oid_list *lsp, int *name, u_int namelen, 273ce02431fSDoug Rabson int *next, int *len, int level, struct sysctl_oid **oidpp) 274946bb7a2SPoul-Henning Kamp { 275ce02431fSDoug Rabson struct sysctl_oid *oidp; 276946bb7a2SPoul-Henning Kamp 277946bb7a2SPoul-Henning Kamp *len = level; 278ce02431fSDoug Rabson SLIST_FOREACH(oidp, lsp, oid_link) { 279ce02431fSDoug Rabson *next = oidp->oid_number; 280ce02431fSDoug Rabson *oidpp = oidp; 281946bb7a2SPoul-Henning Kamp 282946bb7a2SPoul-Henning Kamp if (!namelen) { 283ce02431fSDoug Rabson if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 284946bb7a2SPoul-Henning Kamp return 0; 285ce02431fSDoug Rabson if (oidp->oid_handler) 286946bb7a2SPoul-Henning Kamp /* We really should call the handler here...*/ 287946bb7a2SPoul-Henning Kamp return 0; 288ce02431fSDoug Rabson lsp = (struct sysctl_oid_list *)oidp->oid_arg1; 28961220614SPoul-Henning Kamp if (!sysctl_sysctl_next_ls (lsp, 0, 0, next+1, 290ce02431fSDoug Rabson len, level+1, oidpp)) 29161220614SPoul-Henning Kamp return 0; 29261220614SPoul-Henning Kamp goto next; 293946bb7a2SPoul-Henning Kamp } 294946bb7a2SPoul-Henning Kamp 295ce02431fSDoug Rabson if (oidp->oid_number < *name) 296946bb7a2SPoul-Henning Kamp continue; 297946bb7a2SPoul-Henning Kamp 298ce02431fSDoug Rabson if (oidp->oid_number > *name) { 299ce02431fSDoug Rabson if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 300946bb7a2SPoul-Henning Kamp return 0; 301ce02431fSDoug Rabson if (oidp->oid_handler) 302946bb7a2SPoul-Henning Kamp return 0; 303ce02431fSDoug Rabson lsp = (struct sysctl_oid_list *)oidp->oid_arg1; 304946bb7a2SPoul-Henning Kamp if (!sysctl_sysctl_next_ls (lsp, name+1, namelen-1, 305ce02431fSDoug Rabson next+1, len, level+1, oidpp)) 306946bb7a2SPoul-Henning Kamp return (0); 30761220614SPoul-Henning Kamp goto next; 308946bb7a2SPoul-Henning Kamp } 309ce02431fSDoug Rabson if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 310946bb7a2SPoul-Henning Kamp continue; 311946bb7a2SPoul-Henning Kamp 312ce02431fSDoug Rabson if (oidp->oid_handler) 313946bb7a2SPoul-Henning Kamp continue; 314946bb7a2SPoul-Henning Kamp 315ce02431fSDoug Rabson lsp = (struct sysctl_oid_list *)oidp->oid_arg1; 316946bb7a2SPoul-Henning Kamp if (!sysctl_sysctl_next_ls (lsp, name+1, namelen-1, next+1, 317ce02431fSDoug Rabson len, level+1, oidpp)) 318946bb7a2SPoul-Henning Kamp return (0); 31961220614SPoul-Henning Kamp next: 320946bb7a2SPoul-Henning Kamp namelen = 1; 321946bb7a2SPoul-Henning Kamp *len = level; 322946bb7a2SPoul-Henning Kamp } 323946bb7a2SPoul-Henning Kamp return 1; 324946bb7a2SPoul-Henning Kamp } 325946bb7a2SPoul-Henning Kamp 326946bb7a2SPoul-Henning Kamp static int 327946bb7a2SPoul-Henning Kamp sysctl_sysctl_next SYSCTL_HANDLER_ARGS 328946bb7a2SPoul-Henning Kamp { 329946bb7a2SPoul-Henning Kamp int *name = (int *) arg1; 330946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 331946bb7a2SPoul-Henning Kamp int i, j, error; 332946bb7a2SPoul-Henning Kamp struct sysctl_oid *oid; 333ce02431fSDoug Rabson struct sysctl_oid_list *lsp = &sysctl__children; 334946bb7a2SPoul-Henning Kamp int newoid[CTL_MAXNAME]; 335946bb7a2SPoul-Henning Kamp 336946bb7a2SPoul-Henning Kamp i = sysctl_sysctl_next_ls (lsp, name, namelen, newoid, &j, 1, &oid); 337946bb7a2SPoul-Henning Kamp if (i) 338946bb7a2SPoul-Henning Kamp return ENOENT; 339946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, newoid, j * sizeof (int)); 340946bb7a2SPoul-Henning Kamp return (error); 341946bb7a2SPoul-Henning Kamp } 342946bb7a2SPoul-Henning Kamp 343946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, ""); 344946bb7a2SPoul-Henning Kamp 345946bb7a2SPoul-Henning Kamp static int 346ce02431fSDoug Rabson name2oid (char *name, int *oid, int *len, struct sysctl_oid **oidpp) 347946bb7a2SPoul-Henning Kamp { 348ce02431fSDoug Rabson int i; 349ce02431fSDoug Rabson struct sysctl_oid *oidp; 350ce02431fSDoug Rabson struct sysctl_oid_list *lsp = &sysctl__children; 351946bb7a2SPoul-Henning Kamp char *p; 352946bb7a2SPoul-Henning Kamp 353946bb7a2SPoul-Henning Kamp if (!*name) 354946bb7a2SPoul-Henning Kamp return ENOENT; 355946bb7a2SPoul-Henning Kamp 356946bb7a2SPoul-Henning Kamp p = name + strlen(name) - 1 ; 357946bb7a2SPoul-Henning Kamp if (*p == '.') 358946bb7a2SPoul-Henning Kamp *p = '\0'; 359946bb7a2SPoul-Henning Kamp 360946bb7a2SPoul-Henning Kamp *len = 0; 361946bb7a2SPoul-Henning Kamp 362946bb7a2SPoul-Henning Kamp for (p = name; *p && *p != '.'; p++) 363946bb7a2SPoul-Henning Kamp ; 364946bb7a2SPoul-Henning Kamp i = *p; 365946bb7a2SPoul-Henning Kamp if (i == '.') 366946bb7a2SPoul-Henning Kamp *p = '\0'; 367946bb7a2SPoul-Henning Kamp 368ce02431fSDoug Rabson oidp = SLIST_FIRST(lsp); 369946bb7a2SPoul-Henning Kamp 370ce02431fSDoug Rabson while (oidp && *len < CTL_MAXNAME) { 371ce02431fSDoug Rabson if (strcmp(name, oidp->oid_name)) { 372ce02431fSDoug Rabson oidp = SLIST_NEXT(oidp, oid_link); 373946bb7a2SPoul-Henning Kamp continue; 374946bb7a2SPoul-Henning Kamp } 375ce02431fSDoug Rabson *oid++ = oidp->oid_number; 376946bb7a2SPoul-Henning Kamp (*len)++; 377946bb7a2SPoul-Henning Kamp 378946bb7a2SPoul-Henning Kamp if (!i) { 379ce02431fSDoug Rabson if (oidpp) 380ce02431fSDoug Rabson *oidpp = oidp; 381946bb7a2SPoul-Henning Kamp return (0); 382946bb7a2SPoul-Henning Kamp } 383946bb7a2SPoul-Henning Kamp 384ce02431fSDoug Rabson if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 385946bb7a2SPoul-Henning Kamp break; 386946bb7a2SPoul-Henning Kamp 387ce02431fSDoug Rabson if (oidp->oid_handler) 388946bb7a2SPoul-Henning Kamp break; 389946bb7a2SPoul-Henning Kamp 390ce02431fSDoug Rabson lsp = (struct sysctl_oid_list *)oidp->oid_arg1; 391ce02431fSDoug Rabson oidp = SLIST_FIRST(lsp); 392946bb7a2SPoul-Henning Kamp name = p+1; 393946bb7a2SPoul-Henning Kamp for (p = name; *p && *p != '.'; p++) 394946bb7a2SPoul-Henning Kamp ; 395946bb7a2SPoul-Henning Kamp i = *p; 396946bb7a2SPoul-Henning Kamp if (i == '.') 397946bb7a2SPoul-Henning Kamp *p = '\0'; 398946bb7a2SPoul-Henning Kamp } 399946bb7a2SPoul-Henning Kamp return ENOENT; 400946bb7a2SPoul-Henning Kamp } 401946bb7a2SPoul-Henning Kamp 402946bb7a2SPoul-Henning Kamp static int 403946bb7a2SPoul-Henning Kamp sysctl_sysctl_name2oid SYSCTL_HANDLER_ARGS 404946bb7a2SPoul-Henning Kamp { 405946bb7a2SPoul-Henning Kamp char *p; 406946bb7a2SPoul-Henning Kamp int error, oid[CTL_MAXNAME], len; 407946bb7a2SPoul-Henning Kamp struct sysctl_oid *op = 0; 408946bb7a2SPoul-Henning Kamp 409946bb7a2SPoul-Henning Kamp if (!req->newlen) 410946bb7a2SPoul-Henning Kamp return ENOENT; 411946bb7a2SPoul-Henning Kamp 412946bb7a2SPoul-Henning Kamp p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK); 413946bb7a2SPoul-Henning Kamp 414946bb7a2SPoul-Henning Kamp error = SYSCTL_IN(req, p, req->newlen); 415946bb7a2SPoul-Henning Kamp if (error) { 416946bb7a2SPoul-Henning Kamp free(p, M_SYSCTL); 417946bb7a2SPoul-Henning Kamp return (error); 418946bb7a2SPoul-Henning Kamp } 419946bb7a2SPoul-Henning Kamp 420946bb7a2SPoul-Henning Kamp p [req->newlen] = '\0'; 421946bb7a2SPoul-Henning Kamp 422946bb7a2SPoul-Henning Kamp error = name2oid(p, oid, &len, &op); 423946bb7a2SPoul-Henning Kamp 424946bb7a2SPoul-Henning Kamp free(p, M_SYSCTL); 425946bb7a2SPoul-Henning Kamp 426946bb7a2SPoul-Henning Kamp if (error) 427946bb7a2SPoul-Henning Kamp return (error); 428946bb7a2SPoul-Henning Kamp 429946bb7a2SPoul-Henning Kamp error = SYSCTL_OUT(req, oid, len * sizeof *oid); 430946bb7a2SPoul-Henning Kamp return (error); 431946bb7a2SPoul-Henning Kamp } 432946bb7a2SPoul-Henning Kamp 4333ac9f819SPoul-Henning Kamp SYSCTL_PROC(_sysctl, 3, name2oid, CTLFLAG_RW|CTLFLAG_ANYBODY, 0, 0, 434946bb7a2SPoul-Henning Kamp sysctl_sysctl_name2oid, "I", ""); 435946bb7a2SPoul-Henning Kamp 436946bb7a2SPoul-Henning Kamp static int 437946bb7a2SPoul-Henning Kamp sysctl_sysctl_oidfmt SYSCTL_HANDLER_ARGS 438946bb7a2SPoul-Henning Kamp { 43965d0bc13SPoul-Henning Kamp int *name = (int *) arg1, error; 440946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 441ce02431fSDoug Rabson int indx; 442ce02431fSDoug Rabson struct sysctl_oid *oid; 443ce02431fSDoug Rabson struct sysctl_oid_list *lsp = &sysctl__children; 444946bb7a2SPoul-Henning Kamp 445ce02431fSDoug Rabson oid = SLIST_FIRST(lsp); 446946bb7a2SPoul-Henning Kamp 447946bb7a2SPoul-Henning Kamp indx = 0; 448ce02431fSDoug Rabson while (oid && indx < CTL_MAXNAME) { 449ce02431fSDoug Rabson if (oid->oid_number == name[indx]) { 450946bb7a2SPoul-Henning Kamp indx++; 451ce02431fSDoug Rabson if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 452ce02431fSDoug Rabson if (oid->oid_handler) 453946bb7a2SPoul-Henning Kamp goto found; 454946bb7a2SPoul-Henning Kamp if (indx == namelen) 45565d0bc13SPoul-Henning Kamp goto found; 456ce02431fSDoug Rabson lsp = (struct sysctl_oid_list *)oid->oid_arg1; 457ce02431fSDoug Rabson oid = SLIST_FIRST(lsp); 458946bb7a2SPoul-Henning Kamp } else { 459946bb7a2SPoul-Henning Kamp if (indx != namelen) 460946bb7a2SPoul-Henning Kamp return EISDIR; 461946bb7a2SPoul-Henning Kamp goto found; 462946bb7a2SPoul-Henning Kamp } 463946bb7a2SPoul-Henning Kamp } else { 464ce02431fSDoug Rabson oid = SLIST_NEXT(oid, oid_link); 465946bb7a2SPoul-Henning Kamp } 466946bb7a2SPoul-Henning Kamp } 467946bb7a2SPoul-Henning Kamp return ENOENT; 468946bb7a2SPoul-Henning Kamp found: 469ce02431fSDoug Rabson if (!oid->oid_fmt) 470946bb7a2SPoul-Henning Kamp return ENOENT; 47165d0bc13SPoul-Henning Kamp error = SYSCTL_OUT(req, 472ce02431fSDoug Rabson &oid->oid_kind, sizeof(oid->oid_kind)); 47365d0bc13SPoul-Henning Kamp if (!error) 474ce02431fSDoug Rabson error = SYSCTL_OUT(req, oid->oid_fmt, 475ce02431fSDoug Rabson strlen(oid->oid_fmt)+1); 47665d0bc13SPoul-Henning Kamp return (error); 477946bb7a2SPoul-Henning Kamp } 478946bb7a2SPoul-Henning Kamp 47986415b71SPoul-Henning Kamp 480946bb7a2SPoul-Henning Kamp SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD, sysctl_sysctl_oidfmt, ""); 481946bb7a2SPoul-Henning Kamp 482946bb7a2SPoul-Henning Kamp /* 483946bb7a2SPoul-Henning Kamp * Default "handler" functions. 484946bb7a2SPoul-Henning Kamp */ 4852e210993SPoul-Henning Kamp 486ae0eb976SPoul-Henning Kamp /* 487486bddb0SDoug Rabson * Handle an int, signed or unsigned. 488ae0eb976SPoul-Henning Kamp * Two cases: 489ae0eb976SPoul-Henning Kamp * a variable: point arg1 at it. 490ae0eb976SPoul-Henning Kamp * a constant: pass it in arg2. 491ae0eb976SPoul-Henning Kamp */ 492ae0eb976SPoul-Henning Kamp 4933a34a5c3SPoul-Henning Kamp int 4943a34a5c3SPoul-Henning Kamp sysctl_handle_int SYSCTL_HANDLER_ARGS 495b396cd83SPoul-Henning Kamp { 496ae0eb976SPoul-Henning Kamp int error = 0; 497b396cd83SPoul-Henning Kamp 498ae0eb976SPoul-Henning Kamp if (arg1) 499ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, sizeof(int)); 5001fbf1f71SBruce Evans else 501ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, &arg2, sizeof(int)); 502b396cd83SPoul-Henning Kamp 503ae0eb976SPoul-Henning Kamp if (error || !req->newptr) 504ae0eb976SPoul-Henning Kamp return (error); 505b396cd83SPoul-Henning Kamp 506ae0eb976SPoul-Henning Kamp if (!arg1) 507ae0eb976SPoul-Henning Kamp error = EPERM; 508ae0eb976SPoul-Henning Kamp else 509ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, sizeof(int)); 510ae0eb976SPoul-Henning Kamp return (error); 511b396cd83SPoul-Henning Kamp } 512b396cd83SPoul-Henning Kamp 513ae0eb976SPoul-Henning Kamp /* 514486bddb0SDoug Rabson * Handle a long, signed or unsigned. 515069e9bc1SDoug Rabson * Two cases: 516069e9bc1SDoug Rabson * a variable: point arg1 at it. 517069e9bc1SDoug Rabson * a constant: pass it in arg2. 518069e9bc1SDoug Rabson */ 519069e9bc1SDoug Rabson 520069e9bc1SDoug Rabson int 521069e9bc1SDoug Rabson sysctl_handle_long SYSCTL_HANDLER_ARGS 522069e9bc1SDoug Rabson { 523069e9bc1SDoug Rabson int error = 0; 524069e9bc1SDoug Rabson 525069e9bc1SDoug Rabson error = SYSCTL_OUT(req, arg1, sizeof(long)); 526069e9bc1SDoug Rabson 527069e9bc1SDoug Rabson if (error || !req->newptr) 528069e9bc1SDoug Rabson return (error); 529069e9bc1SDoug Rabson 530069e9bc1SDoug Rabson if (!arg1) 531069e9bc1SDoug Rabson error = EPERM; 532069e9bc1SDoug Rabson else 533069e9bc1SDoug Rabson error = SYSCTL_IN(req, arg1, sizeof(long)); 534069e9bc1SDoug Rabson return (error); 535069e9bc1SDoug Rabson } 536069e9bc1SDoug Rabson 537069e9bc1SDoug Rabson /* 538ae0eb976SPoul-Henning Kamp * Handle our generic '\0' terminated 'C' string. 539ae0eb976SPoul-Henning Kamp * Two cases: 540ae0eb976SPoul-Henning Kamp * a variable string: point arg1 at it, arg2 is max length. 541ae0eb976SPoul-Henning Kamp * a constant string: point arg1 at it, arg2 is zero. 542ae0eb976SPoul-Henning Kamp */ 543ae0eb976SPoul-Henning Kamp 5443a34a5c3SPoul-Henning Kamp int 5453a34a5c3SPoul-Henning Kamp sysctl_handle_string SYSCTL_HANDLER_ARGS 546b396cd83SPoul-Henning Kamp { 547ae0eb976SPoul-Henning Kamp int error=0; 548b396cd83SPoul-Henning Kamp 549ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, strlen((char *)arg1)+1); 550b396cd83SPoul-Henning Kamp 551deae269aSPoul-Henning Kamp if (error || !req->newptr || !arg2) 552ae0eb976SPoul-Henning Kamp return (error); 553ae0eb976SPoul-Henning Kamp 554ae0eb976SPoul-Henning Kamp if ((req->newlen - req->newidx) > arg2) { 555ae0eb976SPoul-Henning Kamp error = E2BIG; 556ae0eb976SPoul-Henning Kamp } else { 557ae0eb976SPoul-Henning Kamp arg2 = (req->newlen - req->newidx); 558ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, arg2); 559ae0eb976SPoul-Henning Kamp ((char *)arg1)[arg2] = '\0'; 560b396cd83SPoul-Henning Kamp } 561b396cd83SPoul-Henning Kamp 5622e210993SPoul-Henning Kamp return (error); 563b396cd83SPoul-Henning Kamp } 564b396cd83SPoul-Henning Kamp 565ae0eb976SPoul-Henning Kamp /* 566ae0eb976SPoul-Henning Kamp * Handle any kind of opaque data. 567ae0eb976SPoul-Henning Kamp * arg1 points to it, arg2 is the size. 568ae0eb976SPoul-Henning Kamp */ 569ae0eb976SPoul-Henning Kamp 5703a34a5c3SPoul-Henning Kamp int 5713a34a5c3SPoul-Henning Kamp sysctl_handle_opaque SYSCTL_HANDLER_ARGS 572b396cd83SPoul-Henning Kamp { 573ae0eb976SPoul-Henning Kamp int error; 574b396cd83SPoul-Henning Kamp 575ae0eb976SPoul-Henning Kamp error = SYSCTL_OUT(req, arg1, arg2); 576b396cd83SPoul-Henning Kamp 577ae0eb976SPoul-Henning Kamp if (error || !req->newptr) 578ae0eb976SPoul-Henning Kamp return (error); 579ae0eb976SPoul-Henning Kamp 580ae0eb976SPoul-Henning Kamp error = SYSCTL_IN(req, arg1, arg2); 581ae0eb976SPoul-Henning Kamp 582ae0eb976SPoul-Henning Kamp return (error); 583b396cd83SPoul-Henning Kamp } 584ae0eb976SPoul-Henning Kamp 585deae269aSPoul-Henning Kamp /* 586deae269aSPoul-Henning Kamp * Transfer functions to/from kernel space. 587deae269aSPoul-Henning Kamp * XXX: rather untested at this point 588deae269aSPoul-Henning Kamp */ 589deae269aSPoul-Henning Kamp static int 590069e9bc1SDoug Rabson sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l) 591ae0eb976SPoul-Henning Kamp { 592069e9bc1SDoug Rabson size_t i = 0; 593deae269aSPoul-Henning Kamp 594deae269aSPoul-Henning Kamp if (req->oldptr) { 595069e9bc1SDoug Rabson i = l; 596069e9bc1SDoug Rabson if (i > req->oldlen - req->oldidx) 597069e9bc1SDoug Rabson i = req->oldlen - req->oldidx; 598deae269aSPoul-Henning Kamp if (i > 0) 59909a8dfa2SBruce Evans bcopy(p, (char *)req->oldptr + req->oldidx, i); 600ae0eb976SPoul-Henning Kamp } 601deae269aSPoul-Henning Kamp req->oldidx += l; 6021c346c70SNate Williams if (req->oldptr && i != l) 603ae0eb976SPoul-Henning Kamp return (ENOMEM); 6042e210993SPoul-Henning Kamp return (0); 605ae0eb976SPoul-Henning Kamp } 606ae0eb976SPoul-Henning Kamp 607deae269aSPoul-Henning Kamp static int 608069e9bc1SDoug Rabson sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l) 609ae0eb976SPoul-Henning Kamp { 610deae269aSPoul-Henning Kamp if (!req->newptr) 611deae269aSPoul-Henning Kamp return 0; 612deae269aSPoul-Henning Kamp if (req->newlen - req->newidx < l) 613ae0eb976SPoul-Henning Kamp return (EINVAL); 61409a8dfa2SBruce Evans bcopy((char *)req->newptr + req->newidx, p, l); 615ae0eb976SPoul-Henning Kamp req->newidx += l; 616ae0eb976SPoul-Henning Kamp return (0); 617ae0eb976SPoul-Henning Kamp } 618ae0eb976SPoul-Henning Kamp 6191c346c70SNate Williams int 620069e9bc1SDoug Rabson kernel_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen, size_t *retval) 6211c346c70SNate Williams { 6221c346c70SNate Williams int error = 0; 6231c346c70SNate Williams struct sysctl_req req; 6241c346c70SNate Williams 6251c346c70SNate Williams bzero(&req, sizeof req); 6261c346c70SNate Williams 6271c346c70SNate Williams req.p = p; 6281c346c70SNate Williams 6291c346c70SNate Williams if (oldlenp) { 6301c346c70SNate Williams req.oldlen = *oldlenp; 6311c346c70SNate Williams } 6321c346c70SNate Williams 6331c346c70SNate Williams if (old) { 6341c346c70SNate Williams req.oldptr= old; 6351c346c70SNate Williams } 6361c346c70SNate Williams 6371c346c70SNate Williams if (newlen) { 6381c346c70SNate Williams req.newlen = newlen; 6391c346c70SNate Williams req.newptr = new; 6401c346c70SNate Williams } 6411c346c70SNate Williams 6421c346c70SNate Williams req.oldfunc = sysctl_old_kernel; 6431c346c70SNate Williams req.newfunc = sysctl_new_kernel; 6441c346c70SNate Williams req.lock = 1; 6451c346c70SNate Williams 6461c346c70SNate Williams /* XXX this should probably be done in a general way */ 6471c346c70SNate Williams while (memlock.sl_lock) { 6481c346c70SNate Williams memlock.sl_want = 1; 6491c346c70SNate Williams (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 6501c346c70SNate Williams memlock.sl_locked++; 6511c346c70SNate Williams } 6521c346c70SNate Williams memlock.sl_lock = 1; 6531c346c70SNate Williams 6541c346c70SNate Williams error = sysctl_root(0, name, namelen, &req); 6551c346c70SNate Williams 6561c346c70SNate Williams if (req.lock == 2) 6571c346c70SNate Williams vsunlock(req.oldptr, req.oldlen, B_WRITE); 6581c346c70SNate Williams 6591c346c70SNate Williams memlock.sl_lock = 0; 6601c346c70SNate Williams 6611c346c70SNate Williams if (memlock.sl_want) { 6621c346c70SNate Williams memlock.sl_want = 0; 6631c346c70SNate Williams wakeup((caddr_t)&memlock); 6641c346c70SNate Williams } 6651c346c70SNate Williams 6661c346c70SNate Williams if (error && error != ENOMEM) 6671c346c70SNate Williams return (error); 6681c346c70SNate Williams 6691c346c70SNate Williams if (retval) { 6701c346c70SNate Williams if (req.oldptr && req.oldidx > req.oldlen) 6711c346c70SNate Williams *retval = req.oldlen; 6721c346c70SNate Williams else 6731c346c70SNate Williams *retval = req.oldidx; 6741c346c70SNate Williams } 6751c346c70SNate Williams return (error); 6761c346c70SNate Williams } 6771c346c70SNate Williams 678deae269aSPoul-Henning Kamp /* 679deae269aSPoul-Henning Kamp * Transfer function to/from user space. 680deae269aSPoul-Henning Kamp */ 681deae269aSPoul-Henning Kamp static int 682069e9bc1SDoug Rabson sysctl_old_user(struct sysctl_req *req, const void *p, size_t l) 683ae0eb976SPoul-Henning Kamp { 684069e9bc1SDoug Rabson int error = 0; 685069e9bc1SDoug Rabson size_t i = 0; 686ae0eb976SPoul-Henning Kamp 6874b2af45fSPoul-Henning Kamp if (req->lock == 1 && req->oldptr) { 6884b2af45fSPoul-Henning Kamp vslock(req->oldptr, req->oldlen); 6894b2af45fSPoul-Henning Kamp req->lock = 2; 6904b2af45fSPoul-Henning Kamp } 691deae269aSPoul-Henning Kamp if (req->oldptr) { 692069e9bc1SDoug Rabson i = l; 693069e9bc1SDoug Rabson if (i > req->oldlen - req->oldidx) 694069e9bc1SDoug Rabson i = req->oldlen - req->oldidx; 695deae269aSPoul-Henning Kamp if (i > 0) 69609a8dfa2SBruce Evans error = copyout(p, (char *)req->oldptr + req->oldidx, 69709a8dfa2SBruce Evans i); 698deae269aSPoul-Henning Kamp } 699deae269aSPoul-Henning Kamp req->oldidx += l; 700ae0eb976SPoul-Henning Kamp if (error) 701ae0eb976SPoul-Henning Kamp return (error); 702deae269aSPoul-Henning Kamp if (req->oldptr && i < l) 703ae0eb976SPoul-Henning Kamp return (ENOMEM); 704deae269aSPoul-Henning Kamp return (0); 705ae0eb976SPoul-Henning Kamp } 706ae0eb976SPoul-Henning Kamp 707deae269aSPoul-Henning Kamp static int 708069e9bc1SDoug Rabson sysctl_new_user(struct sysctl_req *req, void *p, size_t l) 709ae0eb976SPoul-Henning Kamp { 71016cd04a3SPoul-Henning Kamp int error; 711deae269aSPoul-Henning Kamp 712deae269aSPoul-Henning Kamp if (!req->newptr) 713deae269aSPoul-Henning Kamp return 0; 714deae269aSPoul-Henning Kamp if (req->newlen - req->newidx < l) 715ae0eb976SPoul-Henning Kamp return (EINVAL); 71609a8dfa2SBruce Evans error = copyin((char *)req->newptr + req->newidx, p, l); 717ae0eb976SPoul-Henning Kamp req->newidx += l; 718ae0eb976SPoul-Henning Kamp return (error); 719b396cd83SPoul-Henning Kamp } 720b396cd83SPoul-Henning Kamp 721df8bae1dSRodney W. Grimes /* 7222e210993SPoul-Henning Kamp * Traverse our tree, and find the right node, execute whatever it points 7232e210993SPoul-Henning Kamp * at, and return the resulting error code. 7242e210993SPoul-Henning Kamp */ 7252e210993SPoul-Henning Kamp 7262e210993SPoul-Henning Kamp int 7272e210993SPoul-Henning Kamp sysctl_root SYSCTL_HANDLER_ARGS 7282e210993SPoul-Henning Kamp { 7292e210993SPoul-Henning Kamp int *name = (int *) arg1; 730946bb7a2SPoul-Henning Kamp u_int namelen = arg2; 731ce02431fSDoug Rabson int indx, i; 732ce02431fSDoug Rabson struct sysctl_oid *oid; 733ce02431fSDoug Rabson struct sysctl_oid_list *lsp = &sysctl__children; 7342e210993SPoul-Henning Kamp 735ce02431fSDoug Rabson oid = SLIST_FIRST(lsp); 7362e210993SPoul-Henning Kamp 7372e210993SPoul-Henning Kamp indx = 0; 738ce02431fSDoug Rabson while (oid && indx < CTL_MAXNAME) { 739ce02431fSDoug Rabson if (oid->oid_number == name[indx]) { 7402e210993SPoul-Henning Kamp indx++; 741ce02431fSDoug Rabson if (oid->oid_kind & CTLFLAG_NOLOCK) 7424b2af45fSPoul-Henning Kamp req->lock = 0; 743ce02431fSDoug Rabson if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 744ce02431fSDoug Rabson if (oid->oid_handler) 7452e210993SPoul-Henning Kamp goto found; 7462e210993SPoul-Henning Kamp if (indx == namelen) 7472e210993SPoul-Henning Kamp return ENOENT; 748ce02431fSDoug Rabson lsp = (struct sysctl_oid_list *)oid->oid_arg1; 749ce02431fSDoug Rabson oid = SLIST_FIRST(lsp); 7502e210993SPoul-Henning Kamp } else { 7512e210993SPoul-Henning Kamp if (indx != namelen) 7522e210993SPoul-Henning Kamp return EISDIR; 7532e210993SPoul-Henning Kamp goto found; 7542e210993SPoul-Henning Kamp } 7552e210993SPoul-Henning Kamp } else { 756ce02431fSDoug Rabson oid = SLIST_NEXT(oid, oid_link); 7572e210993SPoul-Henning Kamp } 7582e210993SPoul-Henning Kamp } 759deae269aSPoul-Henning Kamp return ENOENT; 7602e210993SPoul-Henning Kamp found: 7612e210993SPoul-Henning Kamp /* If writing isn't allowed */ 762ce02431fSDoug Rabson if (req->newptr && (!(oid->oid_kind & CTLFLAG_WR) || 763ce02431fSDoug Rabson ((oid->oid_kind & CTLFLAG_SECURE) && securelevel > 0))) 7642e210993SPoul-Henning Kamp return (EPERM); 7652e210993SPoul-Henning Kamp 7663ac9f819SPoul-Henning Kamp /* Most likely only root can write */ 767ce02431fSDoug Rabson if (!(oid->oid_kind & CTLFLAG_ANYBODY) && 7683ac9f819SPoul-Henning Kamp req->newptr && req->p && 7693ac9f819SPoul-Henning Kamp (i = suser(req->p->p_ucred, &req->p->p_acflag))) 7703ac9f819SPoul-Henning Kamp return (i); 7713ac9f819SPoul-Henning Kamp 772ce02431fSDoug Rabson if (!oid->oid_handler) 7732e210993SPoul-Henning Kamp return EINVAL; 7742e210993SPoul-Henning Kamp 775ce02431fSDoug Rabson if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 776ce02431fSDoug Rabson i = (oid->oid_handler) (oid, 7772e210993SPoul-Henning Kamp name + indx, namelen - indx, 778ae0eb976SPoul-Henning Kamp req); 7792e210993SPoul-Henning Kamp } else { 780ce02431fSDoug Rabson i = (oid->oid_handler) (oid, 781ce02431fSDoug Rabson oid->oid_arg1, oid->oid_arg2, 782ae0eb976SPoul-Henning Kamp req); 7832e210993SPoul-Henning Kamp } 7842e210993SPoul-Henning Kamp return (i); 7852e210993SPoul-Henning Kamp } 7862e210993SPoul-Henning Kamp 787d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 788b8da2396SPoul-Henning Kamp struct sysctl_args { 789b8da2396SPoul-Henning Kamp int *name; 790b8da2396SPoul-Henning Kamp u_int namelen; 791b8da2396SPoul-Henning Kamp void *old; 792b8da2396SPoul-Henning Kamp size_t *oldlenp; 793b8da2396SPoul-Henning Kamp void *new; 794b8da2396SPoul-Henning Kamp size_t newlen; 795b8da2396SPoul-Henning Kamp }; 796d2d3e875SBruce Evans #endif 797b8da2396SPoul-Henning Kamp 798df8bae1dSRodney W. Grimes int 799cb226aaaSPoul-Henning Kamp __sysctl(struct proc *p, struct sysctl_args *uap) 800df8bae1dSRodney W. Grimes { 801069e9bc1SDoug Rabson int error, i, name[CTL_MAXNAME]; 802069e9bc1SDoug Rabson size_t j; 803b396cd83SPoul-Henning Kamp 804df8bae1dSRodney W. Grimes if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 805df8bae1dSRodney W. Grimes return (EINVAL); 806b396cd83SPoul-Henning Kamp 807797f2d22SPoul-Henning Kamp error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 808797f2d22SPoul-Henning Kamp if (error) 809df8bae1dSRodney W. Grimes return (error); 810df8bae1dSRodney W. Grimes 811deae269aSPoul-Henning Kamp error = userland_sysctl(p, name, uap->namelen, 812b8da2396SPoul-Henning Kamp uap->old, uap->oldlenp, 0, 813deae269aSPoul-Henning Kamp uap->new, uap->newlen, &j); 814deae269aSPoul-Henning Kamp if (error && error != ENOMEM) 815deae269aSPoul-Henning Kamp return (error); 816deae269aSPoul-Henning Kamp if (uap->oldlenp) { 817deae269aSPoul-Henning Kamp i = copyout(&j, uap->oldlenp, sizeof(j)); 818deae269aSPoul-Henning Kamp if (i) 819deae269aSPoul-Henning Kamp return (i); 820deae269aSPoul-Henning Kamp } 821deae269aSPoul-Henning Kamp return (error); 822b8da2396SPoul-Henning Kamp } 823b8da2396SPoul-Henning Kamp 824b8da2396SPoul-Henning Kamp /* 825b8da2396SPoul-Henning Kamp * This is used from various compatibility syscalls too. That's why name 826b8da2396SPoul-Henning Kamp * must be in kernel space. 827b8da2396SPoul-Henning Kamp */ 828b8da2396SPoul-Henning Kamp int 829069e9bc1SDoug 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) 830b8da2396SPoul-Henning Kamp { 8314b2af45fSPoul-Henning Kamp int error = 0; 8327a69d923SPoul-Henning Kamp struct sysctl_req req, req2; 833ae0eb976SPoul-Henning Kamp 834ae0eb976SPoul-Henning Kamp bzero(&req, sizeof req); 835b8da2396SPoul-Henning Kamp 83616cd04a3SPoul-Henning Kamp req.p = p; 83716cd04a3SPoul-Henning Kamp 838b8da2396SPoul-Henning Kamp if (oldlenp) { 839b8da2396SPoul-Henning Kamp if (inkernel) { 840ae0eb976SPoul-Henning Kamp req.oldlen = *oldlenp; 841b8da2396SPoul-Henning Kamp } else { 842deae269aSPoul-Henning Kamp error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp)); 843b8da2396SPoul-Henning Kamp if (error) 844b8da2396SPoul-Henning Kamp return (error); 845b8da2396SPoul-Henning Kamp } 846b8da2396SPoul-Henning Kamp } 847b8da2396SPoul-Henning Kamp 848ae0eb976SPoul-Henning Kamp if (old) { 849ae0eb976SPoul-Henning Kamp if (!useracc(old, req.oldlen, B_WRITE)) 850ae0eb976SPoul-Henning Kamp return (EFAULT); 851ae0eb976SPoul-Henning Kamp req.oldptr= old; 852ae0eb976SPoul-Henning Kamp } 8532e210993SPoul-Henning Kamp 854b8da2396SPoul-Henning Kamp if (newlen) { 855ae0eb976SPoul-Henning Kamp if (!useracc(new, req.newlen, B_READ)) 856ae0eb976SPoul-Henning Kamp return (EFAULT); 857ae0eb976SPoul-Henning Kamp req.newlen = newlen; 858ae0eb976SPoul-Henning Kamp req.newptr = new; 859b396cd83SPoul-Henning Kamp } 860b396cd83SPoul-Henning Kamp 861ae0eb976SPoul-Henning Kamp req.oldfunc = sysctl_old_user; 862ae0eb976SPoul-Henning Kamp req.newfunc = sysctl_new_user; 8634b2af45fSPoul-Henning Kamp req.lock = 1; 8644b2af45fSPoul-Henning Kamp 8654b2af45fSPoul-Henning Kamp /* XXX this should probably be done in a general way */ 8664b2af45fSPoul-Henning Kamp while (memlock.sl_lock) { 8674b2af45fSPoul-Henning Kamp memlock.sl_want = 1; 8684b2af45fSPoul-Henning Kamp (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 8694b2af45fSPoul-Henning Kamp memlock.sl_locked++; 8704b2af45fSPoul-Henning Kamp } 8714b2af45fSPoul-Henning Kamp memlock.sl_lock = 1; 872ae0eb976SPoul-Henning Kamp 8737a69d923SPoul-Henning Kamp do { 8747a69d923SPoul-Henning Kamp req2 = req; 8757a69d923SPoul-Henning Kamp error = sysctl_root(0, name, namelen, &req2); 8767a69d923SPoul-Henning Kamp } while (error == EAGAIN); 877b396cd83SPoul-Henning Kamp 8787a69d923SPoul-Henning Kamp req = req2; 8794b2af45fSPoul-Henning Kamp if (req.lock == 2) 8804b2af45fSPoul-Henning Kamp vsunlock(req.oldptr, req.oldlen, B_WRITE); 8814b2af45fSPoul-Henning Kamp 8824b2af45fSPoul-Henning Kamp memlock.sl_lock = 0; 8834b2af45fSPoul-Henning Kamp 8844b2af45fSPoul-Henning Kamp if (memlock.sl_want) { 8854b2af45fSPoul-Henning Kamp memlock.sl_want = 0; 8864b2af45fSPoul-Henning Kamp wakeup((caddr_t)&memlock); 8874b2af45fSPoul-Henning Kamp } 8884b2af45fSPoul-Henning Kamp 889deae269aSPoul-Henning Kamp if (error && error != ENOMEM) 890deae269aSPoul-Henning Kamp return (error); 891deae269aSPoul-Henning Kamp 892deae269aSPoul-Henning Kamp if (retval) { 893deae269aSPoul-Henning Kamp if (req.oldptr && req.oldidx > req.oldlen) 894ae0eb976SPoul-Henning Kamp *retval = req.oldlen; 895deae269aSPoul-Henning Kamp else 896deae269aSPoul-Henning Kamp *retval = req.oldidx; 897b8da2396SPoul-Henning Kamp } 8982e210993SPoul-Henning Kamp return (error); 899df8bae1dSRodney W. Grimes } 900df8bae1dSRodney W. Grimes 901df8bae1dSRodney W. Grimes #ifdef COMPAT_43 902df8bae1dSRodney W. Grimes #include <sys/socket.h> 90345ec3b38SPoul-Henning Kamp #include <vm/vm_param.h> 90445ec3b38SPoul-Henning Kamp 905df8bae1dSRodney W. Grimes #define KINFO_PROC (0<<8) 906df8bae1dSRodney W. Grimes #define KINFO_RT (1<<8) 907df8bae1dSRodney W. Grimes #define KINFO_VNODE (2<<8) 908df8bae1dSRodney W. Grimes #define KINFO_FILE (3<<8) 909df8bae1dSRodney W. Grimes #define KINFO_METER (4<<8) 910df8bae1dSRodney W. Grimes #define KINFO_LOADAVG (5<<8) 911df8bae1dSRodney W. Grimes #define KINFO_CLOCKRATE (6<<8) 912df8bae1dSRodney W. Grimes 9136ece4a51SPeter Wemm /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ 9146ece4a51SPeter Wemm #define KINFO_BSDI_SYSINFO (101<<8) 9156ece4a51SPeter Wemm 9166ece4a51SPeter Wemm /* 9176ece4a51SPeter Wemm * XXX this is bloat, but I hope it's better here than on the potentially 9186ece4a51SPeter Wemm * limited kernel stack... -Peter 9196ece4a51SPeter Wemm */ 9206ece4a51SPeter Wemm 92187b6de2bSPoul-Henning Kamp static struct { 9226ece4a51SPeter Wemm int bsdi_machine; /* "i386" on BSD/386 */ 9236ece4a51SPeter Wemm /* ^^^ this is an offset to the string, relative to the struct start */ 9246ece4a51SPeter Wemm char *pad0; 9256ece4a51SPeter Wemm long pad1; 9266ece4a51SPeter Wemm long pad2; 9276ece4a51SPeter Wemm long pad3; 9286ece4a51SPeter Wemm u_long pad4; 9296ece4a51SPeter Wemm u_long pad5; 9306ece4a51SPeter Wemm u_long pad6; 9316ece4a51SPeter Wemm 9326ece4a51SPeter Wemm int bsdi_ostype; /* "BSD/386" on BSD/386 */ 9336ece4a51SPeter Wemm int bsdi_osrelease; /* "1.1" on BSD/386 */ 9346ece4a51SPeter Wemm long pad7; 9356ece4a51SPeter Wemm long pad8; 9366ece4a51SPeter Wemm char *pad9; 9376ece4a51SPeter Wemm 9386ece4a51SPeter Wemm long pad10; 9396ece4a51SPeter Wemm long pad11; 9406ece4a51SPeter Wemm int pad12; 9416ece4a51SPeter Wemm long pad13; 9426ece4a51SPeter Wemm quad_t pad14; 9436ece4a51SPeter Wemm long pad15; 9446ece4a51SPeter Wemm 9456ece4a51SPeter Wemm struct timeval pad16; 9466ece4a51SPeter Wemm /* we dont set this, because BSDI's uname used gethostname() instead */ 9476ece4a51SPeter Wemm int bsdi_hostname; /* hostname on BSD/386 */ 9486ece4a51SPeter Wemm 9496ece4a51SPeter Wemm /* the actual string data is appended here */ 9506ece4a51SPeter Wemm 9516ece4a51SPeter Wemm } bsdi_si; 9526ece4a51SPeter Wemm /* 9536ece4a51SPeter Wemm * this data is appended to the end of the bsdi_si structure during copyout. 9546ece4a51SPeter Wemm * The "char *" offsets are relative to the base of the bsdi_si struct. 9556ece4a51SPeter Wemm * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings 9566ece4a51SPeter Wemm * should not exceed the length of the buffer here... (or else!! :-) 9576ece4a51SPeter Wemm */ 95887b6de2bSPoul-Henning Kamp static char bsdi_strings[80]; /* It had better be less than this! */ 9596ece4a51SPeter Wemm 960d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 961df8bae1dSRodney W. Grimes struct getkerninfo_args { 962df8bae1dSRodney W. Grimes int op; 963df8bae1dSRodney W. Grimes char *where; 964134e06feSBruce Evans size_t *size; 965df8bae1dSRodney W. Grimes int arg; 966df8bae1dSRodney W. Grimes }; 967d2d3e875SBruce Evans #endif 968df8bae1dSRodney W. Grimes 96926f9a767SRodney W. Grimes int 970cb226aaaSPoul-Henning Kamp ogetkerninfo(struct proc *p, struct getkerninfo_args *uap) 971df8bae1dSRodney W. Grimes { 972b8da2396SPoul-Henning Kamp int error, name[6]; 973069e9bc1SDoug Rabson size_t size; 974df8bae1dSRodney W. Grimes 975df8bae1dSRodney W. Grimes switch (uap->op & 0xff00) { 976df8bae1dSRodney W. Grimes 977df8bae1dSRodney W. Grimes case KINFO_RT: 978b8da2396SPoul-Henning Kamp name[0] = CTL_NET; 979b8da2396SPoul-Henning Kamp name[1] = PF_ROUTE; 980b8da2396SPoul-Henning Kamp name[2] = 0; 981b8da2396SPoul-Henning Kamp name[3] = (uap->op & 0xff0000) >> 16; 982b8da2396SPoul-Henning Kamp name[4] = uap->op & 0xff; 983b8da2396SPoul-Henning Kamp name[5] = uap->arg; 984b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 6, uap->where, uap->size, 9854b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 986df8bae1dSRodney W. Grimes break; 987df8bae1dSRodney W. Grimes 988df8bae1dSRodney W. Grimes case KINFO_VNODE: 989b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 990b8da2396SPoul-Henning Kamp name[1] = KERN_VNODE; 991b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 9924b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 993df8bae1dSRodney W. Grimes break; 994df8bae1dSRodney W. Grimes 995df8bae1dSRodney W. Grimes case KINFO_PROC: 996b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 997b8da2396SPoul-Henning Kamp name[1] = KERN_PROC; 998b8da2396SPoul-Henning Kamp name[2] = uap->op & 0xff; 999b8da2396SPoul-Henning Kamp name[3] = uap->arg; 1000b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 4, uap->where, uap->size, 10014b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1002df8bae1dSRodney W. Grimes break; 1003df8bae1dSRodney W. Grimes 1004df8bae1dSRodney W. Grimes case KINFO_FILE: 1005b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1006b8da2396SPoul-Henning Kamp name[1] = KERN_FILE; 1007b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10084b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1009df8bae1dSRodney W. Grimes break; 1010df8bae1dSRodney W. Grimes 1011df8bae1dSRodney W. Grimes case KINFO_METER: 1012b8da2396SPoul-Henning Kamp name[0] = CTL_VM; 1013b8da2396SPoul-Henning Kamp name[1] = VM_METER; 1014b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10154b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1016df8bae1dSRodney W. Grimes break; 1017df8bae1dSRodney W. Grimes 1018df8bae1dSRodney W. Grimes case KINFO_LOADAVG: 1019b8da2396SPoul-Henning Kamp name[0] = CTL_VM; 1020b8da2396SPoul-Henning Kamp name[1] = VM_LOADAVG; 1021b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10224b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1023df8bae1dSRodney W. Grimes break; 1024df8bae1dSRodney W. Grimes 1025df8bae1dSRodney W. Grimes case KINFO_CLOCKRATE: 1026b8da2396SPoul-Henning Kamp name[0] = CTL_KERN; 1027b8da2396SPoul-Henning Kamp name[1] = KERN_CLOCKRATE; 1028b8da2396SPoul-Henning Kamp error = userland_sysctl(p, name, 2, uap->where, uap->size, 10294b2af45fSPoul-Henning Kamp 0, 0, 0, &size); 1030df8bae1dSRodney W. Grimes break; 1031df8bae1dSRodney W. Grimes 10326ece4a51SPeter Wemm case KINFO_BSDI_SYSINFO: { 10336ece4a51SPeter Wemm /* 10346ece4a51SPeter Wemm * this is pretty crude, but it's just enough for uname() 10356ece4a51SPeter Wemm * from BSDI's 1.x libc to work. 10366ece4a51SPeter Wemm * 10376ece4a51SPeter Wemm * In particular, it doesn't return the same results when 10386ece4a51SPeter Wemm * the supplied buffer is too small. BSDI's version apparently 10396ece4a51SPeter Wemm * will return the amount copied, and set the *size to how 10406ece4a51SPeter Wemm * much was needed. The emulation framework here isn't capable 10416ece4a51SPeter Wemm * of that, so we just set both to the amount copied. 10426ece4a51SPeter Wemm * BSDI's 2.x product apparently fails with ENOMEM in this 10436ece4a51SPeter Wemm * scenario. 10446ece4a51SPeter Wemm */ 10456ece4a51SPeter Wemm 10466ece4a51SPeter Wemm u_int needed; 10476ece4a51SPeter Wemm u_int left; 10486ece4a51SPeter Wemm char *s; 10496ece4a51SPeter Wemm 10506ece4a51SPeter Wemm bzero((char *)&bsdi_si, sizeof(bsdi_si)); 10516ece4a51SPeter Wemm bzero(bsdi_strings, sizeof(bsdi_strings)); 10526ece4a51SPeter Wemm 10536ece4a51SPeter Wemm s = bsdi_strings; 10546ece4a51SPeter Wemm 10556ece4a51SPeter Wemm bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); 10566ece4a51SPeter Wemm strcpy(s, ostype); 10576ece4a51SPeter Wemm s += strlen(s) + 1; 10586ece4a51SPeter Wemm 10596ece4a51SPeter Wemm bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); 10606ece4a51SPeter Wemm strcpy(s, osrelease); 10616ece4a51SPeter Wemm s += strlen(s) + 1; 10626ece4a51SPeter Wemm 10636ece4a51SPeter Wemm bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); 10646ece4a51SPeter Wemm strcpy(s, machine); 10656ece4a51SPeter Wemm s += strlen(s) + 1; 10666ece4a51SPeter Wemm 10676ece4a51SPeter Wemm needed = sizeof(bsdi_si) + (s - bsdi_strings); 10686ece4a51SPeter Wemm 10696ece4a51SPeter Wemm if (uap->where == NULL) { 10706ece4a51SPeter Wemm /* process is asking how much buffer to supply.. */ 10716ece4a51SPeter Wemm size = needed; 10726ece4a51SPeter Wemm error = 0; 10736ece4a51SPeter Wemm break; 10746ece4a51SPeter Wemm } 10756ece4a51SPeter Wemm 10766ece4a51SPeter Wemm 10776ece4a51SPeter Wemm /* if too much buffer supplied, trim it down */ 10786ece4a51SPeter Wemm if (size > needed) 10796ece4a51SPeter Wemm size = needed; 10806ece4a51SPeter Wemm 10816ece4a51SPeter Wemm /* how much of the buffer is remaining */ 10826ece4a51SPeter Wemm left = size; 10836ece4a51SPeter Wemm 10846ece4a51SPeter Wemm if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) 10856ece4a51SPeter Wemm break; 10866ece4a51SPeter Wemm 10876ece4a51SPeter Wemm /* is there any point in continuing? */ 10886ece4a51SPeter Wemm if (left > sizeof(bsdi_si)) { 10896ece4a51SPeter Wemm left -= sizeof(bsdi_si); 10906ece4a51SPeter Wemm error = copyout(&bsdi_strings, 10916ece4a51SPeter Wemm uap->where + sizeof(bsdi_si), left); 10926ece4a51SPeter Wemm } 10936ece4a51SPeter Wemm break; 10946ece4a51SPeter Wemm } 10956ece4a51SPeter Wemm 1096df8bae1dSRodney W. Grimes default: 1097df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 1098df8bae1dSRodney W. Grimes } 1099df8bae1dSRodney W. Grimes if (error) 1100df8bae1dSRodney W. Grimes return (error); 1101cb226aaaSPoul-Henning Kamp p->p_retval[0] = size; 1102df8bae1dSRodney W. Grimes if (uap->size) 1103df8bae1dSRodney W. Grimes error = copyout((caddr_t)&size, (caddr_t)uap->size, 1104df8bae1dSRodney W. Grimes sizeof(size)); 1105df8bae1dSRodney W. Grimes return (error); 1106df8bae1dSRodney W. Grimes } 1107df8bae1dSRodney W. Grimes #endif /* COMPAT_43 */ 1108