1 1.271 rillig /* $NetBSD: kern_sysctl.c,v 1.271 2024/09/08 09:36:51 rillig Exp $ */ 2 1.153 atatat 3 1.153 atatat /*- 4 1.213 ad * Copyright (c) 2003, 2007, 2008 The NetBSD Foundation, Inc. 5 1.153 atatat * All rights reserved. 6 1.153 atatat * 7 1.153 atatat * This code is derived from software contributed to The NetBSD Foundation 8 1.153 atatat * by Andrew Brown. 9 1.153 atatat * 10 1.153 atatat * Redistribution and use in source and binary forms, with or without 11 1.153 atatat * modification, are permitted provided that the following conditions 12 1.153 atatat * are met: 13 1.153 atatat * 1. Redistributions of source code must retain the above copyright 14 1.153 atatat * notice, this list of conditions and the following disclaimer. 15 1.153 atatat * 2. Redistributions in binary form must reproduce the above copyright 16 1.153 atatat * notice, this list of conditions and the following disclaimer in the 17 1.153 atatat * documentation and/or other materials provided with the distribution. 18 1.153 atatat * 19 1.153 atatat * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.153 atatat * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.153 atatat * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.153 atatat * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.153 atatat * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.153 atatat * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.153 atatat * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.153 atatat * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.153 atatat * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.153 atatat * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.153 atatat * POSSIBILITY OF SUCH DAMAGE. 30 1.153 atatat */ 31 1.2 cgd 32 1.1 cgd /*- 33 1.1 cgd * Copyright (c) 1982, 1986, 1989, 1993 34 1.1 cgd * The Regents of the University of California. All rights reserved. 35 1.1 cgd * 36 1.1 cgd * This code is derived from software contributed to Berkeley by 37 1.1 cgd * Mike Karels at Berkeley Software Design, Inc. 38 1.1 cgd * 39 1.1 cgd * Redistribution and use in source and binary forms, with or without 40 1.1 cgd * modification, are permitted provided that the following conditions 41 1.1 cgd * are met: 42 1.1 cgd * 1. Redistributions of source code must retain the above copyright 43 1.1 cgd * notice, this list of conditions and the following disclaimer. 44 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 45 1.1 cgd * notice, this list of conditions and the following disclaimer in the 46 1.1 cgd * documentation and/or other materials provided with the distribution. 47 1.140 agc * 3. Neither the name of the University nor the names of its contributors 48 1.1 cgd * may be used to endorse or promote products derived from this software 49 1.1 cgd * without specific prior written permission. 50 1.1 cgd * 51 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 1.1 cgd * SUCH DAMAGE. 62 1.1 cgd * 63 1.34 fvdl * @(#)kern_sysctl.c 8.9 (Berkeley) 5/20/95 64 1.1 cgd */ 65 1.1 cgd 66 1.1 cgd /* 67 1.1 cgd * sysctl system call. 68 1.1 cgd */ 69 1.97 lukem 70 1.266 riastrad #define __COMPAT_SYSCTL 71 1.266 riastrad 72 1.97 lukem #include <sys/cdefs.h> 73 1.271 rillig __KERNEL_RCSID(0, "$NetBSD: kern_sysctl.c,v 1.271 2024/09/08 09:36:51 rillig Exp $"); 74 1.30 thorpej 75 1.257 pooka #ifdef _KERNEL_OPT 76 1.52 bouyer #include "opt_defcorename.h" 77 1.257 pooka #endif 78 1.257 pooka 79 1.153 atatat #include "ksyms.h" 80 1.1 cgd 81 1.1 cgd #include <sys/param.h> 82 1.266 riastrad #include <sys/types.h> 83 1.266 riastrad 84 1.62 simonb #include <sys/buf.h> 85 1.266 riastrad #include <sys/cprng.h> 86 1.266 riastrad #include <sys/kauth.h> 87 1.153 atatat #include <sys/ksyms.h> 88 1.266 riastrad #include <sys/ktrace.h> 89 1.1 cgd #include <sys/malloc.h> 90 1.62 simonb #include <sys/mount.h> 91 1.265 riastrad #include <sys/once.h> 92 1.266 riastrad #include <sys/rndsource.h> 93 1.62 simonb #include <sys/syscallargs.h> 94 1.266 riastrad #include <sys/sysctl.h> 95 1.266 riastrad #include <sys/systm.h> 96 1.153 atatat 97 1.265 riastrad #include <crypto/blake2/blake2s.h> 98 1.265 riastrad 99 1.197 christos #define MAXDESCLEN 1024 100 1.153 atatat MALLOC_DEFINE(M_SYSCTLNODE, "sysctlnode", "sysctl node structures"); 101 1.153 atatat MALLOC_DEFINE(M_SYSCTLDATA, "sysctldata", "misc sysctl data"); 102 1.153 atatat 103 1.183 atatat static int sysctl_mmap(SYSCTLFN_PROTO); 104 1.153 atatat static int sysctl_alloc(struct sysctlnode *, int); 105 1.153 atatat static int sysctl_realloc(struct sysctlnode *); 106 1.38 jonathan 107 1.162 atatat static int sysctl_cvt_in(struct lwp *, int *, const void *, size_t, 108 1.162 atatat struct sysctlnode *); 109 1.162 atatat static int sysctl_cvt_out(struct lwp *, int, const struct sysctlnode *, 110 1.162 atatat void *, size_t, size_t *); 111 1.162 atatat 112 1.183 atatat static int sysctl_log_add(struct sysctllog **, const struct sysctlnode *); 113 1.163 atatat static int sysctl_log_realloc(struct sysctllog *); 114 1.163 atatat 115 1.238 para typedef void sysctl_setup_func(struct sysctllog **); 116 1.221 pooka 117 1.241 christos #ifdef SYSCTL_DEBUG 118 1.241 christos #define DPRINTF(a) printf a 119 1.241 christos #else 120 1.241 christos #define DPRINTF(a) 121 1.241 christos #endif 122 1.241 christos 123 1.163 atatat struct sysctllog { 124 1.183 atatat const struct sysctlnode *log_root; 125 1.163 atatat int *log_num; 126 1.163 atatat int log_size, log_left; 127 1.163 atatat }; 128 1.163 atatat 129 1.153 atatat /* 130 1.153 atatat * the "root" of the new sysctl tree 131 1.153 atatat */ 132 1.178 heas struct sysctlnode sysctl_root = { 133 1.161 atatat .sysctl_flags = SYSCTL_VERSION| 134 1.161 atatat CTLFLAG_ROOT|CTLFLAG_READWRITE| 135 1.153 atatat CTLTYPE_NODE, 136 1.153 atatat .sysctl_num = 0, 137 1.250 martin .sysctl_size = sizeof(struct sysctlnode), 138 1.153 atatat .sysctl_name = "(root)", 139 1.153 atatat }; 140 1.69 simonb 141 1.153 atatat /* 142 1.153 atatat * link set of functions that add nodes at boot time (see also 143 1.153 atatat * sysctl_buildtree()) 144 1.153 atatat */ 145 1.153 atatat __link_set_decl(sysctl_funcs, sysctl_setup_func); 146 1.74 simonb 147 1.153 atatat /* 148 1.213 ad * The `sysctl_treelock' is intended to serialize access to the sysctl 149 1.213 ad * tree. XXX This has serious problems; allocating memory and 150 1.213 ad * copying data out with the lock held is insane. 151 1.153 atatat */ 152 1.208 ad krwlock_t sysctl_treelock; 153 1.90 jdolecek 154 1.228 pooka kmutex_t sysctl_file_marker_lock; 155 1.228 pooka 156 1.153 atatat /* 157 1.153 atatat * Attributes stored in the kernel. 158 1.153 atatat */ 159 1.153 atatat char hostname[MAXHOSTNAMELEN]; 160 1.153 atatat int hostnamelen; 161 1.31 mrg 162 1.153 atatat char domainname[MAXHOSTNAMELEN]; 163 1.153 atatat int domainnamelen; 164 1.109 itojun 165 1.153 atatat long hostid; 166 1.62 simonb 167 1.153 atatat #ifndef DEFCORENAME 168 1.153 atatat #define DEFCORENAME "%n.core" 169 1.80 bjh21 #endif 170 1.153 atatat char defcorename[MAXPATHLEN] = DEFCORENAME; 171 1.62 simonb 172 1.75 thorpej /* 173 1.153 atatat * ******************************************************************** 174 1.153 atatat * Section 0: Some simple glue 175 1.153 atatat * ******************************************************************** 176 1.153 atatat * By wrapping copyin(), copyout(), and copyinstr() like this, we can 177 1.153 atatat * stop caring about who's calling us and simplify some code a bunch. 178 1.153 atatat * ******************************************************************** 179 1.75 thorpej */ 180 1.230 pooka int 181 1.203 manu sysctl_copyin(struct lwp *l, const void *uaddr, void *kaddr, size_t len) 182 1.153 atatat { 183 1.203 manu int error; 184 1.203 manu 185 1.203 manu if (l != NULL) { 186 1.203 manu error = copyin(uaddr, kaddr, len); 187 1.210 ad ktrmibio(-1, UIO_WRITE, uaddr, len, error); 188 1.203 manu } else { 189 1.203 manu error = kcopy(uaddr, kaddr, len); 190 1.203 manu } 191 1.153 atatat 192 1.203 manu return error; 193 1.153 atatat } 194 1.153 atatat 195 1.230 pooka int 196 1.203 manu sysctl_copyout(struct lwp *l, const void *kaddr, void *uaddr, size_t len) 197 1.153 atatat { 198 1.203 manu int error; 199 1.153 atatat 200 1.203 manu if (l != NULL) { 201 1.203 manu error = copyout(kaddr, uaddr, len); 202 1.210 ad ktrmibio(-1, UIO_READ, uaddr, len, error); 203 1.203 manu } else { 204 1.203 manu error = kcopy(kaddr, uaddr, len); 205 1.203 manu } 206 1.267 skrll 207 1.203 manu return error; 208 1.153 atatat } 209 1.153 atatat 210 1.230 pooka int 211 1.203 manu sysctl_copyinstr(struct lwp *l, const void *uaddr, void *kaddr, 212 1.153 atatat size_t len, size_t *done) 213 1.153 atatat { 214 1.203 manu int error; 215 1.203 manu 216 1.203 manu if (l != NULL) { 217 1.203 manu error = copyinstr(uaddr, kaddr, len, done); 218 1.210 ad ktrmibio(-1, UIO_WRITE, uaddr, len, error); 219 1.203 manu } else { 220 1.203 manu error = copystr(uaddr, kaddr, len, done); 221 1.203 manu } 222 1.75 thorpej 223 1.203 manu return error; 224 1.153 atatat } 225 1.153 atatat 226 1.153 atatat /* 227 1.153 atatat * ******************************************************************** 228 1.153 atatat * Initialize sysctl subsystem. 229 1.153 atatat * ******************************************************************** 230 1.153 atatat */ 231 1.75 thorpej void 232 1.75 thorpej sysctl_init(void) 233 1.75 thorpej { 234 1.237 christos sysctl_setup_func *const *sysctl_setup; 235 1.153 atatat 236 1.208 ad rw_init(&sysctl_treelock); 237 1.153 atatat 238 1.153 atatat /* 239 1.153 atatat * dynamic mib numbers start here 240 1.153 atatat */ 241 1.153 atatat sysctl_root.sysctl_num = CREATE_BASE; 242 1.246 pooka sysctl_basenode_init(); 243 1.153 atatat 244 1.153 atatat __link_set_foreach(sysctl_setup, sysctl_funcs) { 245 1.237 christos (**sysctl_setup)(NULL); 246 1.153 atatat } 247 1.227 elad 248 1.227 elad mutex_init(&sysctl_file_marker_lock, MUTEX_DEFAULT, IPL_NONE); 249 1.226 pooka } 250 1.226 pooka 251 1.226 pooka /* 252 1.226 pooka * Setting this means no more permanent nodes can be added, 253 1.226 pooka * trees that claim to be readonly at the root now are, and if 254 1.226 pooka * the main tree is readonly, *everything* is. 255 1.226 pooka * 256 1.233 tls * Also starts up the PRNG used for the "random" sysctl: it's 257 1.233 tls * better to start it later than sooner. 258 1.233 tls * 259 1.226 pooka * Call this at the end of kernel init. 260 1.226 pooka */ 261 1.226 pooka void 262 1.226 pooka sysctl_finalize(void) 263 1.226 pooka { 264 1.244 pooka 265 1.161 atatat sysctl_root.sysctl_flags |= CTLFLAG_PERMANENT; 266 1.75 thorpej } 267 1.75 thorpej 268 1.153 atatat /* 269 1.153 atatat * ******************************************************************** 270 1.153 atatat * The main native sysctl system call itself. 271 1.153 atatat * ******************************************************************** 272 1.153 atatat */ 273 1.1 cgd int 274 1.211 dsl sys___sysctl(struct lwp *l, const struct sys___sysctl_args *uap, register_t *retval) 275 1.11 thorpej { 276 1.211 dsl /* { 277 1.189 drochner syscallarg(const int *) name; 278 1.5 cgd syscallarg(u_int) namelen; 279 1.5 cgd syscallarg(void *) old; 280 1.5 cgd syscallarg(size_t *) oldlenp; 281 1.189 drochner syscallarg(const void *) new; 282 1.5 cgd syscallarg(size_t) newlen; 283 1.211 dsl } */ 284 1.153 atatat int error, nerror, name[CTL_MAXNAME]; 285 1.153 atatat size_t oldlen, savelen, *oldlenp; 286 1.153 atatat 287 1.153 atatat /* 288 1.153 atatat * get oldlen 289 1.153 atatat */ 290 1.153 atatat oldlen = 0; 291 1.153 atatat oldlenp = SCARG(uap, oldlenp); 292 1.153 atatat if (oldlenp != NULL) { 293 1.153 atatat error = copyin(oldlenp, &oldlen, sizeof(oldlen)); 294 1.153 atatat if (error) 295 1.153 atatat return (error); 296 1.153 atatat } 297 1.153 atatat savelen = oldlen; 298 1.1 cgd 299 1.1 cgd /* 300 1.153 atatat * top-level sysctl names may or may not be non-terminal, but 301 1.153 atatat * we don't care 302 1.1 cgd */ 303 1.153 atatat if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 1) 304 1.1 cgd return (EINVAL); 305 1.13 christos error = copyin(SCARG(uap, name), &name, 306 1.153 atatat SCARG(uap, namelen) * sizeof(int)); 307 1.13 christos if (error) 308 1.1 cgd return (error); 309 1.1 cgd 310 1.210 ad ktrmib(name, SCARG(uap, namelen)); 311 1.210 ad 312 1.251 joerg sysctl_lock(SCARG(uap, newv) != NULL); 313 1.52 bouyer 314 1.153 atatat /* 315 1.153 atatat * do sysctl work (NULL means main built-in default tree) 316 1.153 atatat */ 317 1.153 atatat error = sysctl_dispatch(&name[0], SCARG(uap, namelen), 318 1.251 joerg SCARG(uap, oldv), &oldlen, 319 1.251 joerg SCARG(uap, newv), SCARG(uap, newlen), 320 1.153 atatat &name[0], l, NULL); 321 1.153 atatat 322 1.153 atatat /* 323 1.153 atatat * release the sysctl lock 324 1.153 atatat */ 325 1.213 ad sysctl_unlock(); 326 1.104 christos 327 1.153 atatat /* 328 1.153 atatat * set caller's oldlen to new value even in the face of an 329 1.153 atatat * error (if this gets an error and they didn't have one, they 330 1.153 atatat * get this one) 331 1.153 atatat */ 332 1.153 atatat if (oldlenp) { 333 1.153 atatat nerror = copyout(&oldlen, oldlenp, sizeof(oldlen)); 334 1.153 atatat if (error == 0) 335 1.153 atatat error = nerror; 336 1.1 cgd } 337 1.1 cgd 338 1.75 thorpej /* 339 1.153 atatat * if the only problem is that we weren't given enough space, 340 1.153 atatat * that's an ENOMEM error 341 1.75 thorpej */ 342 1.251 joerg if (error == 0 && SCARG(uap, oldv) != NULL && savelen < oldlen) 343 1.153 atatat error = ENOMEM; 344 1.179 perry 345 1.153 atatat return (error); 346 1.153 atatat } 347 1.153 atatat 348 1.153 atatat /* 349 1.153 atatat * ******************************************************************** 350 1.153 atatat * Section 1: How the tree is used 351 1.153 atatat * ******************************************************************** 352 1.153 atatat * Implementations of sysctl for emulations should typically need only 353 1.153 atatat * these three functions in this order: lock the tree, dispatch 354 1.153 atatat * request into it, unlock the tree. 355 1.153 atatat * ******************************************************************** 356 1.153 atatat */ 357 1.213 ad void 358 1.213 ad sysctl_lock(bool write) 359 1.153 atatat { 360 1.75 thorpej 361 1.213 ad if (write) { 362 1.213 ad rw_enter(&sysctl_treelock, RW_WRITER); 363 1.213 ad curlwp->l_pflag |= LP_SYSCTLWRITE; 364 1.213 ad } else { 365 1.213 ad rw_enter(&sysctl_treelock, RW_READER); 366 1.213 ad curlwp->l_pflag &= ~LP_SYSCTLWRITE; 367 1.213 ad } 368 1.213 ad } 369 1.153 atatat 370 1.213 ad void 371 1.213 ad sysctl_relock(void) 372 1.213 ad { 373 1.204 chs 374 1.213 ad if ((curlwp->l_pflag & LP_SYSCTLWRITE) != 0) { 375 1.213 ad rw_enter(&sysctl_treelock, RW_WRITER); 376 1.213 ad } else { 377 1.213 ad rw_enter(&sysctl_treelock, RW_READER); 378 1.1 cgd } 379 1.1 cgd } 380 1.1 cgd 381 1.1 cgd /* 382 1.153 atatat * ******************************************************************** 383 1.153 atatat * the main sysctl dispatch routine. scans the given tree and picks a 384 1.153 atatat * function to call based on what it finds. 385 1.153 atatat * ******************************************************************** 386 1.1 cgd */ 387 1.153 atatat int 388 1.183 atatat sysctl_dispatch(SYSCTLFN_ARGS) 389 1.153 atatat { 390 1.153 atatat int error; 391 1.153 atatat sysctlfn fn; 392 1.153 atatat int ni; 393 1.75 thorpej 394 1.213 ad KASSERT(rw_lock_held(&sysctl_treelock)); 395 1.213 ad 396 1.161 atatat if (rnode && SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 397 1.161 atatat printf("sysctl_dispatch: rnode %p wrong version\n", rnode); 398 1.203 manu error = EINVAL; 399 1.203 manu goto out; 400 1.161 atatat } 401 1.161 atatat 402 1.153 atatat fn = NULL; 403 1.153 atatat error = sysctl_locate(l, name, namelen, &rnode, &ni); 404 1.75 thorpej 405 1.188 yamt if (rnode->sysctl_func != NULL) { 406 1.188 yamt /* 407 1.188 yamt * the node we ended up at has a function, so call it. it can 408 1.188 yamt * hand off to query or create if it wants to. 409 1.188 yamt */ 410 1.153 atatat fn = rnode->sysctl_func; 411 1.188 yamt } else if (error == 0) { 412 1.188 yamt /* 413 1.188 yamt * we found the node they were looking for, so do a lookup. 414 1.188 yamt */ 415 1.153 atatat fn = (sysctlfn)sysctl_lookup; /* XXX may write to rnode */ 416 1.188 yamt } else if (error == ENOENT && (ni + 1) == namelen && name[ni] < 0) { 417 1.188 yamt /* 418 1.188 yamt * prospective parent node found, but the terminal node was 419 1.188 yamt * not. generic operations associate with the parent. 420 1.188 yamt */ 421 1.153 atatat switch (name[ni]) { 422 1.153 atatat case CTL_QUERY: 423 1.153 atatat fn = sysctl_query; 424 1.153 atatat break; 425 1.153 atatat case CTL_CREATE: 426 1.153 atatat #if NKSYMS > 0 427 1.153 atatat case CTL_CREATESYM: 428 1.153 atatat #endif /* NKSYMS > 0 */ 429 1.213 ad if (newp == NULL) { 430 1.213 ad error = EINVAL; 431 1.213 ad break; 432 1.213 ad } 433 1.213 ad KASSERT(rw_write_held(&sysctl_treelock)); 434 1.153 atatat fn = (sysctlfn)sysctl_create; /* we own the rnode */ 435 1.153 atatat break; 436 1.153 atatat case CTL_DESTROY: 437 1.213 ad if (newp == NULL) { 438 1.213 ad error = EINVAL; 439 1.213 ad break; 440 1.213 ad } 441 1.213 ad KASSERT(rw_write_held(&sysctl_treelock)); 442 1.153 atatat fn = (sysctlfn)sysctl_destroy; /* we own the rnode */ 443 1.153 atatat break; 444 1.153 atatat case CTL_MMAP: 445 1.153 atatat fn = (sysctlfn)sysctl_mmap; /* we own the rnode */ 446 1.153 atatat break; 447 1.165 atatat case CTL_DESCRIBE: 448 1.165 atatat fn = sysctl_describe; 449 1.165 atatat break; 450 1.153 atatat default: 451 1.153 atatat error = EOPNOTSUPP; 452 1.153 atatat break; 453 1.153 atatat } 454 1.153 atatat } 455 1.75 thorpej 456 1.153 atatat /* 457 1.153 atatat * after all of that, maybe we found someone who knows how to 458 1.153 atatat * get us what we want? 459 1.153 atatat */ 460 1.153 atatat if (fn != NULL) 461 1.153 atatat error = (*fn)(name + ni, namelen - ni, oldp, oldlenp, 462 1.153 atatat newp, newlen, name, l, rnode); 463 1.153 atatat else if (error == 0) 464 1.153 atatat error = EOPNOTSUPP; 465 1.84 sommerfe 466 1.203 manu out: 467 1.153 atatat return (error); 468 1.153 atatat } 469 1.83 sommerfe 470 1.153 atatat /* 471 1.153 atatat * ******************************************************************** 472 1.213 ad * Releases the tree lock. 473 1.153 atatat * ******************************************************************** 474 1.153 atatat */ 475 1.153 atatat void 476 1.213 ad sysctl_unlock(void) 477 1.83 sommerfe { 478 1.84 sommerfe 479 1.213 ad rw_exit(&sysctl_treelock); 480 1.84 sommerfe } 481 1.84 sommerfe 482 1.153 atatat /* 483 1.153 atatat * ******************************************************************** 484 1.153 atatat * Section 2: The main tree interfaces 485 1.153 atatat * ******************************************************************** 486 1.153 atatat * This is how sysctl_dispatch() does its work, and you can too, by 487 1.153 atatat * calling these routines from helpers (though typically only 488 1.153 atatat * sysctl_lookup() will be used). The tree MUST BE LOCKED when these 489 1.153 atatat * are called. 490 1.153 atatat * ******************************************************************** 491 1.153 atatat */ 492 1.83 sommerfe 493 1.1 cgd /* 494 1.153 atatat * sysctl_locate -- Finds the node matching the given mib under the 495 1.153 atatat * given tree (via rv). If no tree is given, we fall back to the 496 1.153 atatat * native tree. The current process (via l) is used for access 497 1.156 atatat * control on the tree (some nodes may be traversable only by root) and 498 1.153 atatat * on return, nip will show how many numbers in the mib were consumed. 499 1.1 cgd */ 500 1.13 christos int 501 1.153 atatat sysctl_locate(struct lwp *l, const int *name, u_int namelen, 502 1.183 atatat const struct sysctlnode **rnode, int *nip) 503 1.1 cgd { 504 1.183 atatat const struct sysctlnode *node, *pnode; 505 1.153 atatat int tn, si, ni, error, alias; 506 1.153 atatat 507 1.213 ad KASSERT(rw_lock_held(&sysctl_treelock)); 508 1.213 ad 509 1.153 atatat /* 510 1.153 atatat * basic checks and setup 511 1.153 atatat */ 512 1.158 atatat if (*rnode == NULL) 513 1.158 atatat *rnode = &sysctl_root; 514 1.153 atatat if (nip) 515 1.153 atatat *nip = 0; 516 1.153 atatat if (namelen == 0) 517 1.153 atatat return (0); 518 1.1 cgd 519 1.153 atatat /* 520 1.153 atatat * search starts from "root" 521 1.153 atatat */ 522 1.158 atatat pnode = *rnode; 523 1.161 atatat if (SYSCTL_VERS(pnode->sysctl_flags) != SYSCTL_VERSION) { 524 1.161 atatat printf("sysctl_locate: pnode %p wrong version\n", pnode); 525 1.161 atatat return (EINVAL); 526 1.161 atatat } 527 1.153 atatat node = pnode->sysctl_child; 528 1.153 atatat error = 0; 529 1.1 cgd 530 1.153 atatat /* 531 1.153 atatat * scan for node to which new node should be attached 532 1.153 atatat */ 533 1.153 atatat for (ni = 0; ni < namelen; ni++) { 534 1.153 atatat /* 535 1.153 atatat * walked off bottom of tree 536 1.153 atatat */ 537 1.153 atatat if (node == NULL) { 538 1.153 atatat if (SYSCTL_TYPE(pnode->sysctl_flags) == CTLTYPE_NODE) 539 1.153 atatat error = ENOENT; 540 1.153 atatat else 541 1.153 atatat error = ENOTDIR; 542 1.153 atatat break; 543 1.153 atatat } 544 1.153 atatat /* 545 1.153 atatat * can anyone traverse this node or only root? 546 1.153 atatat */ 547 1.161 atatat if (l != NULL && (pnode->sysctl_flags & CTLFLAG_PRIVATE) && 548 1.202 elad (error = kauth_authorize_system(l->l_cred, 549 1.202 elad KAUTH_SYSTEM_SYSCTL, KAUTH_REQ_SYSTEM_SYSCTL_PRVT, 550 1.202 elad NULL, NULL, NULL)) != 0) 551 1.153 atatat return (error); 552 1.153 atatat /* 553 1.153 atatat * find a child node with the right number 554 1.153 atatat */ 555 1.153 atatat tn = name[ni]; 556 1.153 atatat alias = 0; 557 1.159 atatat 558 1.159 atatat si = 0; 559 1.159 atatat /* 560 1.159 atatat * Note: ANYNUMBER only matches positive integers. 561 1.159 atatat * Since ANYNUMBER is only permitted on single-node 562 1.159 atatat * sub-trees (eg proc), check before the loop and skip 563 1.159 atatat * it if we can. 564 1.159 atatat */ 565 1.161 atatat if ((node[si].sysctl_flags & CTLFLAG_ANYNUMBER) && (tn >= 0)) 566 1.159 atatat goto foundit; 567 1.159 atatat for (; si < pnode->sysctl_clen; si++) { 568 1.159 atatat if (node[si].sysctl_num == tn) { 569 1.161 atatat if (node[si].sysctl_flags & CTLFLAG_ALIAS) { 570 1.153 atatat if (alias++ == 4) 571 1.159 atatat break; 572 1.153 atatat else { 573 1.153 atatat tn = node[si].sysctl_alias; 574 1.153 atatat si = -1; 575 1.153 atatat } 576 1.188 yamt } else 577 1.159 atatat goto foundit; 578 1.99 lukem } 579 1.29 sommerfe } 580 1.153 atatat /* 581 1.153 atatat * if we ran off the end, it obviously doesn't exist 582 1.153 atatat */ 583 1.159 atatat error = ENOENT; 584 1.159 atatat break; 585 1.159 atatat 586 1.153 atatat /* 587 1.153 atatat * so far so good, move on down the line 588 1.153 atatat */ 589 1.159 atatat foundit: 590 1.153 atatat pnode = &node[si]; 591 1.153 atatat if (SYSCTL_TYPE(pnode->sysctl_flags) == CTLTYPE_NODE) 592 1.153 atatat node = node[si].sysctl_child; 593 1.153 atatat else 594 1.153 atatat node = NULL; 595 1.153 atatat } 596 1.153 atatat 597 1.158 atatat *rnode = pnode; 598 1.153 atatat if (nip) 599 1.153 atatat *nip = ni; 600 1.153 atatat 601 1.153 atatat return (error); 602 1.153 atatat } 603 1.153 atatat 604 1.153 atatat /* 605 1.165 atatat * sysctl_query -- The auto-discovery engine. Copies out the structs 606 1.165 atatat * describing nodes under the given node and handles overlay trees. 607 1.153 atatat */ 608 1.153 atatat int 609 1.153 atatat sysctl_query(SYSCTLFN_ARGS) 610 1.153 atatat { 611 1.162 atatat int error, ni, elim, v; 612 1.153 atatat size_t out, left, t; 613 1.183 atatat const struct sysctlnode *enode, *onode; 614 1.183 atatat struct sysctlnode qnode; 615 1.121 jdolecek 616 1.213 ad KASSERT(rw_lock_held(&sysctl_treelock)); 617 1.213 ad 618 1.161 atatat if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 619 1.161 atatat printf("sysctl_query: rnode %p wrong version\n", rnode); 620 1.161 atatat return (EINVAL); 621 1.161 atatat } 622 1.161 atatat 623 1.153 atatat if (SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE) 624 1.153 atatat return (ENOTDIR); 625 1.153 atatat if (namelen != 1 || name[0] != CTL_QUERY) 626 1.153 atatat return (EINVAL); 627 1.121 jdolecek 628 1.153 atatat error = 0; 629 1.153 atatat out = 0; 630 1.153 atatat left = *oldlenp; 631 1.153 atatat elim = 0; 632 1.153 atatat enode = NULL; 633 1.121 jdolecek 634 1.153 atatat /* 635 1.162 atatat * translate the given request to a current node 636 1.162 atatat */ 637 1.162 atatat error = sysctl_cvt_in(l, &v, newp, newlen, &qnode); 638 1.162 atatat if (error) 639 1.162 atatat return (error); 640 1.162 atatat 641 1.162 atatat /* 642 1.162 atatat * if the request specifies a version, check it 643 1.162 atatat */ 644 1.162 atatat if (qnode.sysctl_ver != 0) { 645 1.183 atatat enode = rnode; 646 1.162 atatat if (qnode.sysctl_ver != enode->sysctl_ver && 647 1.162 atatat qnode.sysctl_ver != sysctl_rootof(enode)->sysctl_ver) 648 1.162 atatat return (EINVAL); 649 1.162 atatat } 650 1.162 atatat 651 1.162 atatat /* 652 1.153 atatat * process has overlay tree 653 1.153 atatat */ 654 1.153 atatat if (l && l->l_proc->p_emul->e_sysctlovly) { 655 1.161 atatat enode = l->l_proc->p_emul->e_sysctlovly; 656 1.153 atatat elim = (name - oname); 657 1.153 atatat error = sysctl_locate(l, oname, elim, &enode, NULL); 658 1.153 atatat if (error == 0) { 659 1.153 atatat /* ah, found parent in overlay */ 660 1.153 atatat elim = enode->sysctl_clen; 661 1.153 atatat enode = enode->sysctl_child; 662 1.188 yamt } else { 663 1.153 atatat error = 0; 664 1.153 atatat elim = 0; 665 1.153 atatat enode = NULL; 666 1.121 jdolecek } 667 1.153 atatat } 668 1.121 jdolecek 669 1.153 atatat for (ni = 0; ni < rnode->sysctl_clen; ni++) { 670 1.153 atatat onode = &rnode->sysctl_child[ni]; 671 1.153 atatat if (enode && enode->sysctl_num == onode->sysctl_num) { 672 1.161 atatat if (SYSCTL_TYPE(enode->sysctl_flags) != CTLTYPE_NODE) 673 1.153 atatat onode = enode; 674 1.153 atatat if (--elim > 0) 675 1.153 atatat enode++; 676 1.153 atatat else 677 1.153 atatat enode = NULL; 678 1.153 atatat } 679 1.162 atatat error = sysctl_cvt_out(l, v, onode, oldp, left, &t); 680 1.153 atatat if (error) 681 1.1 cgd return (error); 682 1.162 atatat if (oldp != NULL) 683 1.162 atatat oldp = (char*)oldp + t; 684 1.162 atatat out += t; 685 1.162 atatat left -= MIN(left, t); 686 1.153 atatat } 687 1.153 atatat 688 1.153 atatat /* 689 1.153 atatat * overlay trees *MUST* be entirely consumed 690 1.153 atatat */ 691 1.153 atatat KASSERT(enode == NULL); 692 1.153 atatat 693 1.153 atatat *oldlenp = out; 694 1.153 atatat 695 1.153 atatat return (error); 696 1.153 atatat } 697 1.153 atatat 698 1.153 atatat /* 699 1.153 atatat * sysctl_create -- Adds a node (the description of which is taken 700 1.153 atatat * from newp) to the tree, returning a copy of it in the space pointed 701 1.153 atatat * to by oldp. In the event that the requested slot is already taken 702 1.153 atatat * (either by name or by number), the offending node is returned 703 1.153 atatat * instead. Yes, this is complex, but we want to make sure everything 704 1.153 atatat * is proper. 705 1.153 atatat */ 706 1.200 christos #ifdef SYSCTL_DEBUG_CREATE 707 1.200 christos int _sysctl_create(SYSCTLFN_ARGS); 708 1.200 christos int 709 1.200 christos _sysctl_create(SYSCTLFN_ARGS) 710 1.200 christos #else 711 1.153 atatat int 712 1.183 atatat sysctl_create(SYSCTLFN_ARGS) 713 1.200 christos #endif 714 1.153 atatat { 715 1.153 atatat struct sysctlnode nnode, *node, *pnode; 716 1.225 dyoung int error, ni, at, nm, type, nsz, sz, flags, anum, v; 717 1.153 atatat void *own; 718 1.153 atatat 719 1.213 ad KASSERT(rw_write_held(&sysctl_treelock)); 720 1.213 ad 721 1.153 atatat error = 0; 722 1.153 atatat own = NULL; 723 1.153 atatat anum = -1; 724 1.153 atatat 725 1.161 atatat if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 726 1.161 atatat printf("sysctl_create: rnode %p wrong version\n", rnode); 727 1.161 atatat return (EINVAL); 728 1.161 atatat } 729 1.161 atatat 730 1.153 atatat if (namelen != 1 || (name[namelen - 1] != CTL_CREATE 731 1.153 atatat #if NKSYMS > 0 732 1.153 atatat && name[namelen - 1] != CTL_CREATESYM 733 1.153 atatat #endif /* NKSYMS > 0 */ 734 1.153 atatat )) 735 1.153 atatat return (EINVAL); 736 1.153 atatat 737 1.153 atatat /* 738 1.153 atatat * processes can only add nodes at securelevel 0, must be 739 1.153 atatat * root, and can't add nodes to a parent that's not writeable 740 1.153 atatat */ 741 1.153 atatat if (l != NULL) { 742 1.156 atatat #ifndef SYSCTL_DISALLOW_CREATE 743 1.202 elad error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SYSCTL, 744 1.202 elad KAUTH_REQ_SYSTEM_SYSCTL_ADD, NULL, NULL, NULL); 745 1.153 atatat if (error) 746 1.153 atatat return (error); 747 1.161 atatat if (!(rnode->sysctl_flags & CTLFLAG_READWRITE)) 748 1.153 atatat #endif /* SYSCTL_DISALLOW_CREATE */ 749 1.1 cgd return (EPERM); 750 1.153 atatat } 751 1.153 atatat 752 1.153 atatat /* 753 1.153 atatat * nothing can add a node if: 754 1.220 pgoyette * we've finished initial set up of this tree and 755 1.220 pgoyette * (the tree itself is not writeable or 756 1.220 pgoyette * the entire sysctl system is not writeable) 757 1.153 atatat */ 758 1.220 pgoyette if ((sysctl_rootof(rnode)->sysctl_flags & CTLFLAG_PERMANENT) && 759 1.161 atatat (!(sysctl_rootof(rnode)->sysctl_flags & CTLFLAG_READWRITE) || 760 1.161 atatat !(sysctl_root.sysctl_flags & CTLFLAG_READWRITE))) 761 1.153 atatat return (EPERM); 762 1.120 jdolecek 763 1.153 atatat /* 764 1.153 atatat * it must be a "node", not a "int" or something 765 1.153 atatat */ 766 1.153 atatat if (SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE) 767 1.153 atatat return (ENOTDIR); 768 1.169 atatat if (rnode->sysctl_flags & CTLFLAG_ALIAS) { 769 1.169 atatat printf("sysctl_create: attempt to add node to aliased " 770 1.169 atatat "node %p\n", rnode); 771 1.169 atatat return (EINVAL); 772 1.169 atatat } 773 1.183 atatat pnode = __UNCONST(rnode); /* we are adding children to this node */ 774 1.120 jdolecek 775 1.162 atatat if (newp == NULL) 776 1.153 atatat return (EINVAL); 777 1.162 atatat error = sysctl_cvt_in(l, &v, newp, newlen, &nnode); 778 1.153 atatat if (error) 779 1.120 jdolecek return (error); 780 1.120 jdolecek 781 1.153 atatat /* 782 1.153 atatat * nodes passed in don't *have* parents 783 1.153 atatat */ 784 1.153 atatat if (nnode.sysctl_parent != NULL) 785 1.153 atatat return (EINVAL); 786 1.145 dsl 787 1.153 atatat /* 788 1.153 atatat * if we are indeed adding it, it should be a "good" name and 789 1.153 atatat * number 790 1.153 atatat */ 791 1.153 atatat nm = nnode.sysctl_num; 792 1.153 atatat #if NKSYMS > 0 793 1.153 atatat if (nm == CTL_CREATESYM) 794 1.153 atatat nm = CTL_CREATE; 795 1.153 atatat #endif /* NKSYMS > 0 */ 796 1.153 atatat if (nm < 0 && nm != CTL_CREATE) 797 1.153 atatat return (EINVAL); 798 1.1 cgd 799 1.153 atatat /* 800 1.153 atatat * the name can't start with a digit 801 1.153 atatat */ 802 1.225 dyoung if (nnode.sysctl_name[0] >= '0' && 803 1.225 dyoung nnode.sysctl_name[0] <= '9') 804 1.153 atatat return (EINVAL); 805 1.1 cgd 806 1.153 atatat /* 807 1.153 atatat * the name must be only alphanumerics or - or _, longer than 808 1.258 pgoyette * 0 bytes and less than SYSCTL_NAMELEN 809 1.153 atatat */ 810 1.225 dyoung nsz = 0; 811 1.225 dyoung while (nsz < SYSCTL_NAMELEN && nnode.sysctl_name[nsz] != '\0') { 812 1.225 dyoung if ((nnode.sysctl_name[nsz] >= '0' && 813 1.225 dyoung nnode.sysctl_name[nsz] <= '9') || 814 1.225 dyoung (nnode.sysctl_name[nsz] >= 'A' && 815 1.225 dyoung nnode.sysctl_name[nsz] <= 'Z') || 816 1.225 dyoung (nnode.sysctl_name[nsz] >= 'a' && 817 1.225 dyoung nnode.sysctl_name[nsz] <= 'z') || 818 1.225 dyoung nnode.sysctl_name[nsz] == '-' || 819 1.225 dyoung nnode.sysctl_name[nsz] == '_') 820 1.225 dyoung nsz++; 821 1.153 atatat else 822 1.153 atatat return (EINVAL); 823 1.98 simonb } 824 1.225 dyoung if (nsz == 0 || nsz == SYSCTL_NAMELEN) 825 1.153 atatat return (EINVAL); 826 1.1 cgd 827 1.153 atatat /* 828 1.153 atatat * various checks revolve around size vs type, etc 829 1.153 atatat */ 830 1.153 atatat type = SYSCTL_TYPE(nnode.sysctl_flags); 831 1.153 atatat flags = SYSCTL_FLAGS(nnode.sysctl_flags); 832 1.153 atatat sz = nnode.sysctl_size; 833 1.131 thorpej 834 1.153 atatat /* 835 1.153 atatat * find out if there's a collision, and if so, let the caller 836 1.153 atatat * know what they collided with 837 1.153 atatat */ 838 1.153 atatat node = pnode->sysctl_child; 839 1.193 dsl at = 0; 840 1.193 dsl if (node) { 841 1.193 dsl if ((flags | node->sysctl_flags) & CTLFLAG_ANYNUMBER) 842 1.193 dsl /* No siblings for a CTLFLAG_ANYNUMBER node */ 843 1.193 dsl return EINVAL; 844 1.193 dsl for (ni = 0; ni < pnode->sysctl_clen; ni++) { 845 1.193 dsl if (nm == node[ni].sysctl_num || 846 1.193 dsl strcmp(nnode.sysctl_name, node[ni].sysctl_name) == 0) { 847 1.193 dsl /* 848 1.193 dsl * ignore error here, since we 849 1.193 dsl * are already fixed on EEXIST 850 1.193 dsl */ 851 1.193 dsl (void)sysctl_cvt_out(l, v, &node[ni], oldp, 852 1.193 dsl *oldlenp, oldlenp); 853 1.193 dsl return (EEXIST); 854 1.193 dsl } 855 1.193 dsl if (nm > node[ni].sysctl_num) 856 1.193 dsl at++; 857 1.82 eeh } 858 1.1 cgd } 859 1.1 cgd 860 1.153 atatat /* 861 1.153 atatat * use sysctl_ver to add to the tree iff it hasn't changed 862 1.153 atatat */ 863 1.153 atatat if (nnode.sysctl_ver != 0) { 864 1.153 atatat /* 865 1.153 atatat * a specified value must match either the parent 866 1.153 atatat * node's version or the root node's version 867 1.153 atatat */ 868 1.153 atatat if (nnode.sysctl_ver != sysctl_rootof(rnode)->sysctl_ver && 869 1.153 atatat nnode.sysctl_ver != rnode->sysctl_ver) { 870 1.153 atatat return (EINVAL); 871 1.153 atatat } 872 1.1 cgd } 873 1.1 cgd 874 1.153 atatat /* 875 1.153 atatat * only the kernel can assign functions to entries 876 1.153 atatat */ 877 1.153 atatat if (l != NULL && nnode.sysctl_func != NULL) 878 1.153 atatat return (EPERM); 879 1.52 bouyer 880 1.153 atatat /* 881 1.153 atatat * only the kernel can create permanent entries, and only then 882 1.153 atatat * before the kernel is finished setting itself up 883 1.153 atatat */ 884 1.153 atatat if (l != NULL && (flags & ~SYSCTL_USERFLAGS)) 885 1.153 atatat return (EPERM); 886 1.161 atatat if ((flags & CTLFLAG_PERMANENT) & 887 1.161 atatat (sysctl_root.sysctl_flags & CTLFLAG_PERMANENT)) 888 1.153 atatat return (EPERM); 889 1.179 perry if ((flags & (CTLFLAG_OWNDATA | CTLFLAG_IMMEDIATE)) == 890 1.161 atatat (CTLFLAG_OWNDATA | CTLFLAG_IMMEDIATE)) 891 1.153 atatat return (EINVAL); 892 1.161 atatat if ((flags & CTLFLAG_IMMEDIATE) && 893 1.215 matt type != CTLTYPE_INT && type != CTLTYPE_QUAD && type != CTLTYPE_BOOL) 894 1.129 enami return (EINVAL); 895 1.52 bouyer 896 1.153 atatat /* 897 1.153 atatat * check size, or set it if unset and we can figure it out. 898 1.153 atatat * kernel created nodes are allowed to have a function instead 899 1.153 atatat * of a size (or a data pointer). 900 1.153 atatat */ 901 1.153 atatat switch (type) { 902 1.153 atatat case CTLTYPE_NODE: 903 1.153 atatat /* 904 1.153 atatat * only *i* can assert the size of a node 905 1.153 atatat */ 906 1.161 atatat if (flags & CTLFLAG_ALIAS) { 907 1.153 atatat anum = nnode.sysctl_alias; 908 1.153 atatat if (anum < 0) 909 1.153 atatat return (EINVAL); 910 1.153 atatat nnode.sysctl_alias = 0; 911 1.52 bouyer } 912 1.153 atatat if (sz != 0 || nnode.sysctl_data != NULL) 913 1.153 atatat return (EINVAL); 914 1.153 atatat if (nnode.sysctl_csize != 0 || 915 1.153 atatat nnode.sysctl_clen != 0 || 916 1.153 atatat nnode.sysctl_child != 0) 917 1.129 enami return (EINVAL); 918 1.161 atatat if (flags & CTLFLAG_OWNDATA) 919 1.129 enami return (EINVAL); 920 1.153 atatat sz = sizeof(struct sysctlnode); 921 1.153 atatat break; 922 1.153 atatat case CTLTYPE_INT: 923 1.153 atatat /* 924 1.153 atatat * since an int is an int, if the size is not given or 925 1.153 atatat * is wrong, we can "int-uit" it. 926 1.153 atatat */ 927 1.153 atatat if (sz != 0 && sz != sizeof(int)) 928 1.129 enami return (EINVAL); 929 1.153 atatat sz = sizeof(int); 930 1.153 atatat break; 931 1.153 atatat case CTLTYPE_STRING: 932 1.52 bouyer /* 933 1.153 atatat * strings are a little more tricky 934 1.52 bouyer */ 935 1.153 atatat if (sz == 0) { 936 1.153 atatat if (l == NULL) { 937 1.153 atatat if (nnode.sysctl_func == NULL) { 938 1.153 atatat if (nnode.sysctl_data == NULL) 939 1.153 atatat return (EINVAL); 940 1.153 atatat else 941 1.153 atatat sz = strlen(nnode.sysctl_data) + 942 1.153 atatat 1; 943 1.52 bouyer } 944 1.188 yamt } else if (nnode.sysctl_data == NULL && 945 1.161 atatat flags & CTLFLAG_OWNDATA) { 946 1.153 atatat return (EINVAL); 947 1.188 yamt } else { 948 1.181 scw char *vp, *e; 949 1.153 atatat size_t s; 950 1.153 atatat 951 1.153 atatat /* 952 1.156 atatat * we want a rough idea of what the 953 1.156 atatat * size is now 954 1.153 atatat */ 955 1.262 jdolecek vp = malloc(PAGE_SIZE, M_SYSCTLDATA, M_WAITOK); 956 1.181 scw if (vp == NULL) 957 1.181 scw return (ENOMEM); 958 1.156 atatat e = nnode.sysctl_data; 959 1.156 atatat do { 960 1.181 scw error = copyinstr(e, vp, PAGE_SIZE, &s); 961 1.156 atatat if (error) { 962 1.181 scw if (error != ENAMETOOLONG) { 963 1.181 scw free(vp, M_SYSCTLDATA); 964 1.156 atatat return (error); 965 1.181 scw } 966 1.156 atatat e += PAGE_SIZE; 967 1.156 atatat if ((e - 32 * PAGE_SIZE) > 968 1.181 scw (char*)nnode.sysctl_data) { 969 1.181 scw free(vp, M_SYSCTLDATA); 970 1.156 atatat return (ERANGE); 971 1.181 scw } 972 1.156 atatat } 973 1.156 atatat } while (error != 0); 974 1.156 atatat sz = s + (e - (char*)nnode.sysctl_data); 975 1.181 scw free(vp, M_SYSCTLDATA); 976 1.96 bouyer } 977 1.52 bouyer } 978 1.153 atatat break; 979 1.153 atatat case CTLTYPE_QUAD: 980 1.153 atatat if (sz != 0 && sz != sizeof(u_quad_t)) 981 1.129 enami return (EINVAL); 982 1.153 atatat sz = sizeof(u_quad_t); 983 1.153 atatat break; 984 1.215 matt case CTLTYPE_BOOL: 985 1.215 matt /* 986 1.271 rillig * since a bool is a bool, if the size is not given or 987 1.215 matt * is wrong, we can "intuit" it. 988 1.215 matt */ 989 1.215 matt if (sz != 0 && sz != sizeof(bool)) 990 1.215 matt return (EINVAL); 991 1.215 matt sz = sizeof(bool); 992 1.215 matt break; 993 1.153 atatat case CTLTYPE_STRUCT: 994 1.153 atatat if (sz == 0) { 995 1.153 atatat if (l != NULL || nnode.sysctl_func == NULL) 996 1.153 atatat return (EINVAL); 997 1.161 atatat if (flags & CTLFLAG_OWNDATA) 998 1.153 atatat return (EINVAL); 999 1.153 atatat } 1000 1.153 atatat break; 1001 1.115 manu default: 1002 1.115 manu return (EINVAL); 1003 1.52 bouyer } 1004 1.52 bouyer 1005 1.153 atatat /* 1006 1.153 atatat * at this point, if sz is zero, we *must* have a 1007 1.153 atatat * function to go with it and we can't own it. 1008 1.153 atatat */ 1009 1.104 christos 1010 1.153 atatat /* 1011 1.153 atatat * l ptr own 1012 1.153 atatat * 0 0 0 -> EINVAL (if no func) 1013 1.153 atatat * 0 0 1 -> own 1014 1.153 atatat * 0 1 0 -> kptr 1015 1.153 atatat * 0 1 1 -> kptr 1016 1.153 atatat * 1 0 0 -> EINVAL 1017 1.153 atatat * 1 0 1 -> own 1018 1.156 atatat * 1 1 0 -> kptr, no own (fault on lookup) 1019 1.153 atatat * 1 1 1 -> uptr, own 1020 1.153 atatat */ 1021 1.153 atatat if (type != CTLTYPE_NODE) { 1022 1.153 atatat if (sz != 0) { 1023 1.161 atatat if (flags & CTLFLAG_OWNDATA) { 1024 1.262 jdolecek own = malloc(sz, M_SYSCTLDATA, M_WAITOK); 1025 1.194 dsl if (own == NULL) 1026 1.194 dsl return ENOMEM; 1027 1.153 atatat if (nnode.sysctl_data == NULL) 1028 1.153 atatat memset(own, 0, sz); 1029 1.153 atatat else { 1030 1.153 atatat error = sysctl_copyin(l, 1031 1.153 atatat nnode.sysctl_data, own, sz); 1032 1.153 atatat if (error != 0) { 1033 1.187 yamt free(own, M_SYSCTLDATA); 1034 1.153 atatat return (error); 1035 1.153 atatat } 1036 1.153 atatat } 1037 1.188 yamt } else if ((nnode.sysctl_data != NULL) && 1038 1.161 atatat !(flags & CTLFLAG_IMMEDIATE)) { 1039 1.153 atatat #if NKSYMS > 0 1040 1.153 atatat if (name[namelen - 1] == CTL_CREATESYM) { 1041 1.153 atatat char symname[128]; /* XXX enough? */ 1042 1.153 atatat u_long symaddr; 1043 1.153 atatat size_t symlen; 1044 1.153 atatat 1045 1.153 atatat error = sysctl_copyinstr(l, 1046 1.153 atatat nnode.sysctl_data, symname, 1047 1.153 atatat sizeof(symname), &symlen); 1048 1.153 atatat if (error) 1049 1.153 atatat return (error); 1050 1.177 elric error = ksyms_getval(NULL, symname, 1051 1.177 elric &symaddr, KSYMS_EXTERN); 1052 1.153 atatat if (error) 1053 1.153 atatat return (error); /* EINVAL? */ 1054 1.153 atatat nnode.sysctl_data = (void*)symaddr; 1055 1.153 atatat } 1056 1.153 atatat #endif /* NKSYMS > 0 */ 1057 1.156 atatat /* 1058 1.156 atatat * Ideally, we'd like to verify here 1059 1.156 atatat * that this address is acceptable, 1060 1.156 atatat * but... 1061 1.156 atatat * 1062 1.156 atatat * - it might be valid now, only to 1063 1.156 atatat * become invalid later 1064 1.156 atatat * 1065 1.156 atatat * - it might be invalid only for the 1066 1.156 atatat * moment and valid later 1067 1.156 atatat * 1068 1.156 atatat * - or something else. 1069 1.156 atatat * 1070 1.156 atatat * Since we can't get a good answer, 1071 1.156 atatat * we'll just accept the address as 1072 1.156 atatat * given, and fault on individual 1073 1.156 atatat * lookups. 1074 1.156 atatat */ 1075 1.153 atatat } 1076 1.188 yamt } else if (nnode.sysctl_func == NULL) 1077 1.153 atatat return (EINVAL); 1078 1.153 atatat } 1079 1.104 christos 1080 1.153 atatat /* 1081 1.153 atatat * a process can't assign a function to a node, and the kernel 1082 1.153 atatat * can't create a node that has no function or data. 1083 1.153 atatat * (XXX somewhat redundant check) 1084 1.153 atatat */ 1085 1.153 atatat if (l != NULL || nnode.sysctl_func == NULL) { 1086 1.153 atatat if (type != CTLTYPE_NODE && 1087 1.264 maxv !(flags & CTLFLAG_IMMEDIATE) && 1088 1.153 atatat nnode.sysctl_data == NULL && 1089 1.153 atatat own == NULL) 1090 1.153 atatat return (EINVAL); 1091 1.153 atatat } 1092 1.104 christos 1093 1.153 atatat #ifdef SYSCTL_DISALLOW_KWRITE 1094 1.153 atatat /* 1095 1.153 atatat * a process can't create a writable node unless it refers to 1096 1.153 atatat * new data. 1097 1.153 atatat */ 1098 1.153 atatat if (l != NULL && own == NULL && type != CTLTYPE_NODE && 1099 1.161 atatat (flags & CTLFLAG_READWRITE) != CTLFLAG_READONLY && 1100 1.161 atatat !(flags & CTLFLAG_IMMEDIATE)) 1101 1.153 atatat return (EPERM); 1102 1.153 atatat #endif /* SYSCTL_DISALLOW_KWRITE */ 1103 1.104 christos 1104 1.153 atatat /* 1105 1.153 atatat * make sure there's somewhere to put the new stuff. 1106 1.153 atatat */ 1107 1.153 atatat if (pnode->sysctl_child == NULL) { 1108 1.161 atatat if (flags & CTLFLAG_ANYNUMBER) 1109 1.153 atatat error = sysctl_alloc(pnode, 1); 1110 1.153 atatat else 1111 1.153 atatat error = sysctl_alloc(pnode, 0); 1112 1.194 dsl if (error) { 1113 1.194 dsl if (own != NULL) 1114 1.194 dsl free(own, M_SYSCTLDATA); 1115 1.153 atatat return (error); 1116 1.194 dsl } 1117 1.153 atatat } 1118 1.153 atatat node = pnode->sysctl_child; 1119 1.105 jdolecek 1120 1.153 atatat /* 1121 1.153 atatat * no collisions, so pick a good dynamic number if we need to. 1122 1.153 atatat */ 1123 1.153 atatat if (nm == CTL_CREATE) { 1124 1.153 atatat nm = ++sysctl_root.sysctl_num; 1125 1.153 atatat for (ni = 0; ni < pnode->sysctl_clen; ni++) { 1126 1.153 atatat if (nm == node[ni].sysctl_num) { 1127 1.153 atatat nm++; 1128 1.153 atatat ni = -1; 1129 1.188 yamt } else if (nm > node[ni].sysctl_num) 1130 1.153 atatat at = ni + 1; 1131 1.153 atatat } 1132 1.104 christos } 1133 1.104 christos 1134 1.153 atatat /* 1135 1.153 atatat * oops...ran out of space 1136 1.153 atatat */ 1137 1.153 atatat if (pnode->sysctl_clen == pnode->sysctl_csize) { 1138 1.153 atatat error = sysctl_realloc(pnode); 1139 1.194 dsl if (error) { 1140 1.194 dsl if (own != NULL) 1141 1.194 dsl free(own, M_SYSCTLDATA); 1142 1.153 atatat return (error); 1143 1.194 dsl } 1144 1.153 atatat node = pnode->sysctl_child; 1145 1.55 is } 1146 1.55 is 1147 1.153 atatat /* 1148 1.153 atatat * insert new node data 1149 1.153 atatat */ 1150 1.153 atatat if (at < pnode->sysctl_clen) { 1151 1.153 atatat int t; 1152 1.179 perry 1153 1.153 atatat /* 1154 1.153 atatat * move the nodes that should come after the new one 1155 1.153 atatat */ 1156 1.153 atatat memmove(&node[at + 1], &node[at], 1157 1.153 atatat (pnode->sysctl_clen - at) * sizeof(struct sysctlnode)); 1158 1.153 atatat memset(&node[at], 0, sizeof(struct sysctlnode)); 1159 1.153 atatat node[at].sysctl_parent = pnode; 1160 1.153 atatat /* 1161 1.153 atatat * and...reparent any children of any moved nodes 1162 1.153 atatat */ 1163 1.153 atatat for (ni = at; ni <= pnode->sysctl_clen; ni++) 1164 1.223 dyoung if (node[ni].sysctl_child != NULL) 1165 1.223 dyoung for (t = 0; t < node[ni].sysctl_csize; t++) 1166 1.153 atatat node[ni].sysctl_child[t].sysctl_parent = 1167 1.153 atatat &node[ni]; 1168 1.153 atatat } 1169 1.153 atatat node = &node[at]; 1170 1.153 atatat pnode->sysctl_clen++; 1171 1.153 atatat 1172 1.153 atatat strlcpy(node->sysctl_name, nnode.sysctl_name, 1173 1.153 atatat sizeof(node->sysctl_name)); 1174 1.153 atatat node->sysctl_num = nm; 1175 1.153 atatat node->sysctl_size = sz; 1176 1.161 atatat node->sysctl_flags = SYSCTL_VERSION|type|flags; /* XXX other trees */ 1177 1.153 atatat node->sysctl_csize = 0; 1178 1.153 atatat node->sysctl_clen = 0; 1179 1.153 atatat if (own) { 1180 1.153 atatat node->sysctl_data = own; 1181 1.161 atatat node->sysctl_flags |= CTLFLAG_OWNDATA; 1182 1.188 yamt } else if (flags & CTLFLAG_ALIAS) { 1183 1.153 atatat node->sysctl_alias = anum; 1184 1.188 yamt } else if (flags & CTLFLAG_IMMEDIATE) { 1185 1.153 atatat switch (type) { 1186 1.215 matt case CTLTYPE_BOOL: 1187 1.234 martin node->sysctl_bdata = nnode.sysctl_bdata; 1188 1.215 matt break; 1189 1.153 atatat case CTLTYPE_INT: 1190 1.153 atatat node->sysctl_idata = nnode.sysctl_idata; 1191 1.153 atatat break; 1192 1.153 atatat case CTLTYPE_QUAD: 1193 1.153 atatat node->sysctl_qdata = nnode.sysctl_qdata; 1194 1.153 atatat break; 1195 1.153 atatat } 1196 1.188 yamt } else { 1197 1.153 atatat node->sysctl_data = nnode.sysctl_data; 1198 1.161 atatat node->sysctl_flags &= ~CTLFLAG_OWNDATA; 1199 1.153 atatat } 1200 1.153 atatat node->sysctl_func = nnode.sysctl_func; 1201 1.153 atatat node->sysctl_child = NULL; 1202 1.153 atatat /* node->sysctl_parent should already be done */ 1203 1.55 is 1204 1.153 atatat /* 1205 1.153 atatat * update "version" on path to "root" 1206 1.153 atatat */ 1207 1.153 atatat for (; rnode->sysctl_parent != NULL; rnode = rnode->sysctl_parent) 1208 1.153 atatat ; 1209 1.153 atatat pnode = node; 1210 1.153 atatat for (nm = rnode->sysctl_ver + 1; pnode != NULL; 1211 1.153 atatat pnode = pnode->sysctl_parent) 1212 1.153 atatat pnode->sysctl_ver = nm; 1213 1.153 atatat 1214 1.194 dsl /* If this fails, the node is already added - the user won't know! */ 1215 1.162 atatat error = sysctl_cvt_out(l, v, node, oldp, *oldlenp, oldlenp); 1216 1.55 is 1217 1.1 cgd return (error); 1218 1.1 cgd } 1219 1.1 cgd 1220 1.1 cgd /* 1221 1.153 atatat * ******************************************************************** 1222 1.153 atatat * A wrapper around sysctl_create() that prints the thing we're trying 1223 1.153 atatat * to add. 1224 1.153 atatat * ******************************************************************** 1225 1.1 cgd */ 1226 1.153 atatat #ifdef SYSCTL_DEBUG_CREATE 1227 1.13 christos int 1228 1.200 christos sysctl_create(SYSCTLFN_ARGS) 1229 1.1 cgd { 1230 1.153 atatat const struct sysctlnode *node; 1231 1.268 skrll int k, v, rc, ni, nl = namelen + (name - oname); 1232 1.268 skrll struct sysctlnode nnode; 1233 1.268 skrll 1234 1.268 skrll if (newp == NULL) 1235 1.268 skrll return EINVAL; 1236 1.268 skrll int error = sysctl_cvt_in(l, &v, newp, newlen, &nnode); 1237 1.268 skrll if (error) 1238 1.268 skrll return error; 1239 1.153 atatat 1240 1.268 skrll node = &nnode; 1241 1.153 atatat 1242 1.153 atatat printf("namelen %d (", nl); 1243 1.153 atatat for (ni = 0; ni < nl - 1; ni++) 1244 1.153 atatat printf(" %d", oname[ni]); 1245 1.153 atatat printf(" %d )\t[%s]\tflags %08x (%08x %d %zu)\n", 1246 1.153 atatat k = node->sysctl_num, 1247 1.153 atatat node->sysctl_name, 1248 1.153 atatat node->sysctl_flags, 1249 1.153 atatat SYSCTL_FLAGS(node->sysctl_flags), 1250 1.153 atatat SYSCTL_TYPE(node->sysctl_flags), 1251 1.153 atatat node->sysctl_size); 1252 1.1 cgd 1253 1.153 atatat node = rnode; 1254 1.200 christos rc = _sysctl_create(SYSCTLFN_CALL(rnode)); 1255 1.55 is 1256 1.153 atatat printf("sysctl_create("); 1257 1.153 atatat for (ni = 0; ni < nl - 1; ni++) 1258 1.153 atatat printf(" %d", oname[ni]); 1259 1.153 atatat printf(" %d ) returned %d\n", k, rc); 1260 1.55 is 1261 1.153 atatat return (rc); 1262 1.1 cgd } 1263 1.153 atatat #endif /* SYSCTL_DEBUG_CREATE */ 1264 1.1 cgd 1265 1.1 cgd /* 1266 1.153 atatat * sysctl_destroy -- Removes a node (as described by newp) from the 1267 1.153 atatat * given tree, returning (if successful) a copy of the dead node in 1268 1.153 atatat * oldp. Since we're removing stuff, there's not much to check. 1269 1.52 bouyer */ 1270 1.52 bouyer int 1271 1.183 atatat sysctl_destroy(SYSCTLFN_ARGS) 1272 1.52 bouyer { 1273 1.153 atatat struct sysctlnode *node, *pnode, onode, nnode; 1274 1.162 atatat int ni, error, v; 1275 1.52 bouyer 1276 1.213 ad KASSERT(rw_write_held(&sysctl_treelock)); 1277 1.213 ad 1278 1.161 atatat if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 1279 1.161 atatat printf("sysctl_destroy: rnode %p wrong version\n", rnode); 1280 1.161 atatat return (EINVAL); 1281 1.161 atatat } 1282 1.161 atatat 1283 1.153 atatat error = 0; 1284 1.55 is 1285 1.153 atatat if (namelen != 1 || name[namelen - 1] != CTL_DESTROY) 1286 1.153 atatat return (EINVAL); 1287 1.52 bouyer 1288 1.153 atatat /* 1289 1.153 atatat * processes can only destroy nodes at securelevel 0, must be 1290 1.153 atatat * root, and can't remove nodes from a parent that's not 1291 1.153 atatat * writeable 1292 1.153 atatat */ 1293 1.153 atatat if (l != NULL) { 1294 1.156 atatat #ifndef SYSCTL_DISALLOW_CREATE 1295 1.202 elad error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SYSCTL, 1296 1.202 elad KAUTH_REQ_SYSTEM_SYSCTL_DELETE, NULL, NULL, NULL); 1297 1.153 atatat if (error) 1298 1.153 atatat return (error); 1299 1.161 atatat if (!(rnode->sysctl_flags & CTLFLAG_READWRITE)) 1300 1.156 atatat #endif /* SYSCTL_DISALLOW_CREATE */ 1301 1.153 atatat return (EPERM); 1302 1.153 atatat } 1303 1.52 bouyer 1304 1.153 atatat /* 1305 1.153 atatat * nothing can remove a node if: 1306 1.153 atatat * the node is permanent (checked later) or 1307 1.153 atatat * the tree itself is not writeable or 1308 1.153 atatat * the entire sysctl system is not writeable 1309 1.170 atatat * 1310 1.170 atatat * note that we ignore whether setup is complete or not, 1311 1.170 atatat * because these rules always apply. 1312 1.153 atatat */ 1313 1.161 atatat if (!(sysctl_rootof(rnode)->sysctl_flags & CTLFLAG_READWRITE) || 1314 1.161 atatat !(sysctl_root.sysctl_flags & CTLFLAG_READWRITE)) 1315 1.52 bouyer return (EPERM); 1316 1.55 is 1317 1.161 atatat if (newp == NULL) 1318 1.153 atatat return (EINVAL); 1319 1.162 atatat error = sysctl_cvt_in(l, &v, newp, newlen, &nnode); 1320 1.153 atatat if (error) 1321 1.153 atatat return (error); 1322 1.153 atatat memset(&onode, 0, sizeof(struct sysctlnode)); 1323 1.55 is 1324 1.153 atatat node = rnode->sysctl_child; 1325 1.153 atatat for (ni = 0; ni < rnode->sysctl_clen; ni++) { 1326 1.153 atatat if (nnode.sysctl_num == node[ni].sysctl_num) { 1327 1.153 atatat /* 1328 1.153 atatat * if name specified, must match 1329 1.153 atatat */ 1330 1.153 atatat if (nnode.sysctl_name[0] != '\0' && 1331 1.153 atatat strcmp(nnode.sysctl_name, node[ni].sysctl_name)) 1332 1.153 atatat continue; 1333 1.153 atatat /* 1334 1.153 atatat * if version specified, must match 1335 1.153 atatat */ 1336 1.153 atatat if (nnode.sysctl_ver != 0 && 1337 1.153 atatat nnode.sysctl_ver != node[ni].sysctl_ver) 1338 1.153 atatat continue; 1339 1.153 atatat /* 1340 1.153 atatat * this must be the one 1341 1.153 atatat */ 1342 1.153 atatat break; 1343 1.153 atatat } 1344 1.153 atatat } 1345 1.153 atatat if (ni == rnode->sysctl_clen) 1346 1.153 atatat return (ENOENT); 1347 1.153 atatat node = &node[ni]; 1348 1.153 atatat pnode = node->sysctl_parent; 1349 1.52 bouyer 1350 1.153 atatat /* 1351 1.153 atatat * if the kernel says permanent, it is, so there. nyah. 1352 1.153 atatat */ 1353 1.161 atatat if (SYSCTL_FLAGS(node->sysctl_flags) & CTLFLAG_PERMANENT) 1354 1.153 atatat return (EPERM); 1355 1.1 cgd 1356 1.153 atatat /* 1357 1.153 atatat * can't delete non-empty nodes 1358 1.153 atatat */ 1359 1.153 atatat if (SYSCTL_TYPE(node->sysctl_flags) == CTLTYPE_NODE && 1360 1.153 atatat node->sysctl_clen != 0) 1361 1.153 atatat return (ENOTEMPTY); 1362 1.55 is 1363 1.153 atatat /* 1364 1.153 atatat * if the node "owns" data, release it now 1365 1.153 atatat */ 1366 1.161 atatat if (node->sysctl_flags & CTLFLAG_OWNDATA) { 1367 1.153 atatat if (node->sysctl_data != NULL) 1368 1.187 yamt free(node->sysctl_data, M_SYSCTLDATA); 1369 1.153 atatat node->sysctl_data = NULL; 1370 1.153 atatat } 1371 1.166 atatat if (node->sysctl_flags & CTLFLAG_OWNDESC) { 1372 1.166 atatat if (node->sysctl_desc != NULL) 1373 1.180 christos /*XXXUNCONST*/ 1374 1.187 yamt free(__UNCONST(node->sysctl_desc), M_SYSCTLDATA); 1375 1.166 atatat node->sysctl_desc = NULL; 1376 1.166 atatat } 1377 1.55 is 1378 1.153 atatat /* 1379 1.153 atatat * if the node to be removed is not the last one on the list, 1380 1.153 atatat * move the remaining nodes up, and reparent any grandchildren 1381 1.153 atatat */ 1382 1.153 atatat onode = *node; 1383 1.153 atatat if (ni < pnode->sysctl_clen - 1) { 1384 1.153 atatat int t; 1385 1.153 atatat 1386 1.153 atatat memmove(&pnode->sysctl_child[ni], &pnode->sysctl_child[ni + 1], 1387 1.153 atatat (pnode->sysctl_clen - ni - 1) * 1388 1.153 atatat sizeof(struct sysctlnode)); 1389 1.153 atatat for (; ni < pnode->sysctl_clen - 1; ni++) 1390 1.153 atatat if (SYSCTL_TYPE(pnode->sysctl_child[ni].sysctl_flags) == 1391 1.153 atatat CTLTYPE_NODE) 1392 1.161 atatat for (t = 0; 1393 1.161 atatat t < pnode->sysctl_child[ni].sysctl_clen; 1394 1.153 atatat t++) 1395 1.153 atatat pnode->sysctl_child[ni].sysctl_child[t]. 1396 1.153 atatat sysctl_parent = 1397 1.153 atatat &pnode->sysctl_child[ni]; 1398 1.153 atatat ni = pnode->sysctl_clen - 1; 1399 1.153 atatat node = &pnode->sysctl_child[ni]; 1400 1.1 cgd } 1401 1.1 cgd 1402 1.153 atatat /* 1403 1.153 atatat * reset the space we just vacated 1404 1.153 atatat */ 1405 1.153 atatat memset(node, 0, sizeof(struct sysctlnode)); 1406 1.153 atatat node->sysctl_parent = pnode; 1407 1.153 atatat pnode->sysctl_clen--; 1408 1.1 cgd 1409 1.153 atatat /* 1410 1.153 atatat * if this parent just lost its last child, nuke the creche 1411 1.153 atatat */ 1412 1.153 atatat if (pnode->sysctl_clen == 0) { 1413 1.187 yamt free(pnode->sysctl_child, M_SYSCTLNODE); 1414 1.153 atatat pnode->sysctl_csize = 0; 1415 1.153 atatat pnode->sysctl_child = NULL; 1416 1.153 atatat } 1417 1.55 is 1418 1.153 atatat /* 1419 1.153 atatat * update "version" on path to "root" 1420 1.153 atatat */ 1421 1.153 atatat for (; rnode->sysctl_parent != NULL; rnode = rnode->sysctl_parent) 1422 1.153 atatat ; 1423 1.153 atatat for (ni = rnode->sysctl_ver + 1; pnode != NULL; 1424 1.153 atatat pnode = pnode->sysctl_parent) 1425 1.153 atatat pnode->sysctl_ver = ni; 1426 1.153 atatat 1427 1.162 atatat error = sysctl_cvt_out(l, v, &onode, oldp, *oldlenp, oldlenp); 1428 1.55 is 1429 1.1 cgd return (error); 1430 1.1 cgd } 1431 1.1 cgd 1432 1.1 cgd /* 1433 1.153 atatat * sysctl_lookup -- Handles copyin/copyout of new and old values. 1434 1.153 atatat * Partial reads are globally allowed. Only root can write to things 1435 1.153 atatat * unless the node says otherwise. 1436 1.1 cgd */ 1437 1.13 christos int 1438 1.183 atatat sysctl_lookup(SYSCTLFN_ARGS) 1439 1.1 cgd { 1440 1.153 atatat int error, rw; 1441 1.153 atatat size_t sz, len; 1442 1.252 gson void *d; 1443 1.153 atatat 1444 1.213 ad KASSERT(rw_lock_held(&sysctl_treelock)); 1445 1.213 ad 1446 1.161 atatat if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 1447 1.241 christos printf("%s: rnode %p wrong version\n", __func__, rnode); 1448 1.241 christos return EINVAL; 1449 1.161 atatat } 1450 1.161 atatat 1451 1.247 dsl if (newlen == 0) 1452 1.247 dsl newp = NULL; 1453 1.247 dsl 1454 1.153 atatat error = 0; 1455 1.153 atatat 1456 1.153 atatat /* 1457 1.153 atatat * you can't "look up" a node. you can "query" it, but you 1458 1.153 atatat * can't "look it up". 1459 1.153 atatat */ 1460 1.241 christos if (SYSCTL_TYPE(rnode->sysctl_flags) == CTLTYPE_NODE || namelen != 0) { 1461 1.241 christos DPRINTF(("%s: can't lookup a node\n", __func__)); 1462 1.241 christos return EINVAL; 1463 1.241 christos } 1464 1.1 cgd 1465 1.153 atatat /* 1466 1.153 atatat * some nodes are private, so only root can look into them. 1467 1.153 atatat */ 1468 1.161 atatat if (l != NULL && (rnode->sysctl_flags & CTLFLAG_PRIVATE) && 1469 1.202 elad (error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SYSCTL, 1470 1.241 christos KAUTH_REQ_SYSTEM_SYSCTL_PRVT, NULL, NULL, NULL)) != 0) { 1471 1.241 christos DPRINTF(("%s: private node\n", __func__)); 1472 1.241 christos return error; 1473 1.241 christos } 1474 1.55 is 1475 1.153 atatat /* 1476 1.153 atatat * if a node wants to be writable according to different rules 1477 1.153 atatat * other than "only root can write to stuff unless a flag is 1478 1.153 atatat * set", then it needs its own function which should have been 1479 1.153 atatat * called and not us. 1480 1.153 atatat */ 1481 1.153 atatat if (l != NULL && newp != NULL && 1482 1.161 atatat !(rnode->sysctl_flags & CTLFLAG_ANYWRITE) && 1483 1.222 elad (error = kauth_authorize_system(l->l_cred, 1484 1.222 elad KAUTH_SYSTEM_SYSCTL, KAUTH_REQ_SYSTEM_SYSCTL_MODIFY, NULL, NULL, 1485 1.241 christos NULL)) != 0) { 1486 1.241 christos DPRINTF(("%s: can't modify\n", __func__)); 1487 1.241 christos return error; 1488 1.241 christos } 1489 1.1 cgd 1490 1.153 atatat /* 1491 1.153 atatat * is this node supposedly writable? 1492 1.153 atatat */ 1493 1.199 elad rw = (rnode->sysctl_flags & CTLFLAG_READWRITE) ? 1 : 0; 1494 1.1 cgd 1495 1.153 atatat /* 1496 1.153 atatat * it appears not to be writable at this time, so if someone 1497 1.153 atatat * tried to write to it, we must tell them to go away 1498 1.153 atatat */ 1499 1.241 christos if (!rw && newp != NULL) { 1500 1.241 christos DPRINTF(("%s: not writable\n", __func__)); 1501 1.241 christos return EPERM; 1502 1.241 christos } 1503 1.55 is 1504 1.153 atatat /* 1505 1.153 atatat * step one, copy out the stuff we have presently 1506 1.153 atatat */ 1507 1.161 atatat if (rnode->sysctl_flags & CTLFLAG_IMMEDIATE) { 1508 1.183 atatat /* 1509 1.183 atatat * note that we discard const here because we are 1510 1.183 atatat * modifying the contents of the node (which is okay 1511 1.183 atatat * because it's ours) 1512 1.247 dsl * 1513 1.247 dsl * It also doesn't matter which field of the union we pick. 1514 1.183 atatat */ 1515 1.247 dsl d = __UNCONST(&rnode->sysctl_qdata); 1516 1.188 yamt } else 1517 1.153 atatat d = rnode->sysctl_data; 1518 1.247 dsl 1519 1.252 gson if (SYSCTL_TYPE(rnode->sysctl_flags) == CTLTYPE_STRING) 1520 1.157 atatat sz = strlen(d) + 1; /* XXX@@@ possible fault here */ 1521 1.252 gson else 1522 1.252 gson sz = rnode->sysctl_size; 1523 1.241 christos if (oldp != NULL) { 1524 1.252 gson error = sysctl_copyout(l, d, oldp, MIN(sz, *oldlenp)); 1525 1.241 christos if (error) { 1526 1.241 christos DPRINTF(("%s: bad copyout %d\n", __func__, error)); 1527 1.241 christos return error; 1528 1.241 christos } 1529 1.241 christos } 1530 1.153 atatat *oldlenp = sz; 1531 1.153 atatat 1532 1.153 atatat /* 1533 1.153 atatat * are we done? 1534 1.153 atatat */ 1535 1.247 dsl if (newp == NULL) 1536 1.241 christos return 0; 1537 1.153 atatat 1538 1.153 atatat /* 1539 1.153 atatat * hmm...not done. must now "copy in" new value. re-adjust 1540 1.153 atatat * sz to maximum value (strings are "weird"). 1541 1.153 atatat */ 1542 1.153 atatat sz = rnode->sysctl_size; 1543 1.153 atatat switch (SYSCTL_TYPE(rnode->sysctl_flags)) { 1544 1.215 matt case CTLTYPE_BOOL: { 1545 1.229 mrg bool tmp; 1546 1.215 matt /* 1547 1.215 matt * these data must be *exactly* the same size coming 1548 1.215 matt * in. bool may only be true or false. 1549 1.215 matt */ 1550 1.241 christos if (newlen != sz) { 1551 1.241 christos DPRINTF(("%s: bad size %zu != %zu\n", __func__, newlen, 1552 1.241 christos sz)); 1553 1.241 christos return EINVAL; 1554 1.241 christos } 1555 1.215 matt error = sysctl_copyin(l, newp, &tmp, sz); 1556 1.245 maxv if (error) 1557 1.245 maxv break; 1558 1.241 christos if (tmp != true && tmp != false) { 1559 1.241 christos DPRINTF(("%s: tmp %d\n", __func__, tmp)); 1560 1.229 mrg return EINVAL; 1561 1.241 christos } 1562 1.215 matt *(bool *)d = tmp; 1563 1.215 matt break; 1564 1.215 matt } 1565 1.153 atatat case CTLTYPE_INT: 1566 1.153 atatat case CTLTYPE_QUAD: 1567 1.153 atatat case CTLTYPE_STRUCT: 1568 1.153 atatat /* 1569 1.153 atatat * these data must be *exactly* the same size coming 1570 1.153 atatat * in. 1571 1.153 atatat */ 1572 1.247 dsl if (newlen != sz) 1573 1.247 dsl goto bad_size; 1574 1.153 atatat error = sysctl_copyin(l, newp, d, sz); 1575 1.253 tls rnd_add_data(NULL, d, sz, 0); 1576 1.153 atatat break; 1577 1.153 atatat case CTLTYPE_STRING: { 1578 1.153 atatat /* 1579 1.153 atatat * strings, on the other hand, can be shorter, and we 1580 1.153 atatat * let userland be sloppy about the trailing nul. 1581 1.153 atatat */ 1582 1.153 atatat char *newbuf; 1583 1.85 simonb 1584 1.153 atatat /* 1585 1.153 atatat * too much new string? 1586 1.153 atatat */ 1587 1.247 dsl if (newlen > sz) 1588 1.247 dsl goto bad_size; 1589 1.85 simonb 1590 1.153 atatat /* 1591 1.153 atatat * temporary copy of new inbound string 1592 1.153 atatat */ 1593 1.153 atatat len = MIN(sz, newlen); 1594 1.262 jdolecek newbuf = malloc(len, M_SYSCTLDATA, M_WAITOK); 1595 1.241 christos if (newbuf == NULL) { 1596 1.241 christos DPRINTF(("%s: oomem %zu\n", __func__, len)); 1597 1.241 christos return ENOMEM; 1598 1.241 christos } 1599 1.153 atatat error = sysctl_copyin(l, newp, newbuf, len); 1600 1.153 atatat if (error) { 1601 1.187 yamt free(newbuf, M_SYSCTLDATA); 1602 1.241 christos DPRINTF(("%s: copyin %d\n", __func__, error)); 1603 1.241 christos return error; 1604 1.153 atatat } 1605 1.85 simonb 1606 1.153 atatat /* 1607 1.232 apb * did they NUL terminate it, or do we have space 1608 1.153 atatat * left to do it ourselves? 1609 1.153 atatat */ 1610 1.153 atatat if (newbuf[len - 1] != '\0' && len == sz) { 1611 1.187 yamt free(newbuf, M_SYSCTLDATA); 1612 1.241 christos DPRINTF(("%s: string too long\n", __func__)); 1613 1.241 christos return EINVAL; 1614 1.153 atatat } 1615 1.85 simonb 1616 1.153 atatat /* 1617 1.153 atatat * looks good, so pop it into place and zero the rest. 1618 1.153 atatat */ 1619 1.253 tls if (len > 0) { 1620 1.190 yamt memcpy(d, newbuf, len); 1621 1.253 tls rnd_add_data(NULL, d, len, 0); 1622 1.253 tls } 1623 1.153 atatat if (sz != len) 1624 1.190 yamt memset((char*)d + len, 0, sz - len); 1625 1.187 yamt free(newbuf, M_SYSCTLDATA); 1626 1.153 atatat break; 1627 1.153 atatat } 1628 1.153 atatat default: 1629 1.241 christos DPRINTF(("%s: bad type\n", __func__)); 1630 1.241 christos return EINVAL; 1631 1.153 atatat } 1632 1.243 christos if (error) { 1633 1.241 christos DPRINTF(("%s: copyin %d\n", __func__, error)); 1634 1.243 christos } 1635 1.55 is 1636 1.241 christos return error; 1637 1.247 dsl 1638 1.247 dsl bad_size: 1639 1.247 dsl DPRINTF(("%s: bad size %zu > %zu\n", __func__, newlen, sz)); 1640 1.247 dsl return EINVAL; 1641 1.1 cgd } 1642 1.1 cgd 1643 1.1 cgd /* 1644 1.153 atatat * sysctl_mmap -- Dispatches sysctl mmap requests to those nodes that 1645 1.153 atatat * purport to handle it. This interface isn't fully fleshed out yet, 1646 1.153 atatat * unfortunately. 1647 1.1 cgd */ 1648 1.69 simonb static int 1649 1.183 atatat sysctl_mmap(SYSCTLFN_ARGS) 1650 1.1 cgd { 1651 1.183 atatat const struct sysctlnode *node; 1652 1.183 atatat struct sysctlnode nnode; 1653 1.111 thorpej int error; 1654 1.254 justin int sysctl_num; 1655 1.1 cgd 1656 1.161 atatat if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 1657 1.161 atatat printf("sysctl_mmap: rnode %p wrong version\n", rnode); 1658 1.161 atatat return (EINVAL); 1659 1.161 atatat } 1660 1.161 atatat 1661 1.153 atatat /* 1662 1.153 atatat * let's just pretend that didn't happen, m'kay? 1663 1.153 atatat */ 1664 1.153 atatat if (l == NULL) 1665 1.153 atatat return (EPERM); 1666 1.153 atatat 1667 1.153 atatat /* 1668 1.153 atatat * is this a sysctlnode description of an mmap request? 1669 1.153 atatat */ 1670 1.153 atatat if (newp == NULL || newlen != sizeof(struct sysctlnode)) 1671 1.153 atatat return (EINVAL); 1672 1.161 atatat error = sysctl_copyin(l, newp, &nnode, sizeof(nnode)); 1673 1.153 atatat if (error) 1674 1.153 atatat return (error); 1675 1.1 cgd 1676 1.1 cgd /* 1677 1.153 atatat * does the node they asked for exist? 1678 1.1 cgd */ 1679 1.153 atatat if (namelen != 1) 1680 1.153 atatat return (EOPNOTSUPP); 1681 1.153 atatat node = rnode; 1682 1.254 justin sysctl_num = nnode.sysctl_num; 1683 1.254 justin error = sysctl_locate(l, &sysctl_num, 1, &node, NULL); 1684 1.13 christos if (error) 1685 1.1 cgd return (error); 1686 1.1 cgd 1687 1.1 cgd /* 1688 1.153 atatat * does this node that we have found purport to handle mmap? 1689 1.153 atatat */ 1690 1.153 atatat if (node->sysctl_func == NULL || 1691 1.161 atatat !(node->sysctl_flags & CTLFLAG_MMAP)) 1692 1.153 atatat return (EOPNOTSUPP); 1693 1.153 atatat 1694 1.153 atatat /* 1695 1.153 atatat * well...okay, they asked for it. 1696 1.1 cgd */ 1697 1.153 atatat return ((*node->sysctl_func)(SYSCTLFN_CALL(node))); 1698 1.1 cgd } 1699 1.1 cgd 1700 1.165 atatat int 1701 1.165 atatat sysctl_describe(SYSCTLFN_ARGS) 1702 1.165 atatat { 1703 1.166 atatat struct sysctldesc *d; 1704 1.197 christos void *bf; 1705 1.166 atatat size_t sz, left, tot; 1706 1.166 atatat int i, error, v = -1; 1707 1.166 atatat struct sysctlnode *node; 1708 1.166 atatat struct sysctlnode dnode; 1709 1.165 atatat 1710 1.165 atatat if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 1711 1.165 atatat printf("sysctl_query: rnode %p wrong version\n", rnode); 1712 1.165 atatat return (EINVAL); 1713 1.165 atatat } 1714 1.165 atatat 1715 1.165 atatat if (SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE) 1716 1.165 atatat return (ENOTDIR); 1717 1.165 atatat if (namelen != 1 || name[0] != CTL_DESCRIBE) 1718 1.165 atatat return (EINVAL); 1719 1.165 atatat 1720 1.165 atatat /* 1721 1.166 atatat * get ready... 1722 1.166 atatat */ 1723 1.166 atatat error = 0; 1724 1.262 jdolecek d = bf = malloc(MAXDESCLEN, M_TEMP, M_WAITOK); 1725 1.197 christos if (bf == NULL) 1726 1.197 christos return ENOMEM; 1727 1.166 atatat tot = 0; 1728 1.166 atatat node = rnode->sysctl_child; 1729 1.166 atatat left = *oldlenp; 1730 1.166 atatat 1731 1.166 atatat /* 1732 1.166 atatat * no request -> all descriptions at this level 1733 1.166 atatat * request with desc unset -> just this node 1734 1.166 atatat * request with desc set -> set descr for this node 1735 1.165 atatat */ 1736 1.166 atatat if (newp != NULL) { 1737 1.166 atatat error = sysctl_cvt_in(l, &v, newp, newlen, &dnode); 1738 1.166 atatat if (error) 1739 1.197 christos goto out; 1740 1.166 atatat if (dnode.sysctl_desc != NULL) { 1741 1.166 atatat /* 1742 1.166 atatat * processes cannot set descriptions above 1743 1.166 atatat * securelevel 0. and must be root. blah 1744 1.166 atatat * blah blah. a couple more checks are made 1745 1.166 atatat * once we find the node we want. 1746 1.166 atatat */ 1747 1.166 atatat if (l != NULL) { 1748 1.166 atatat #ifndef SYSCTL_DISALLOW_CREATE 1749 1.202 elad error = kauth_authorize_system(l->l_cred, 1750 1.202 elad KAUTH_SYSTEM_SYSCTL, 1751 1.202 elad KAUTH_REQ_SYSTEM_SYSCTL_DESC, NULL, 1752 1.202 elad NULL, NULL); 1753 1.166 atatat if (error) 1754 1.197 christos goto out; 1755 1.166 atatat #else /* SYSCTL_DISALLOW_CREATE */ 1756 1.197 christos error = EPERM; 1757 1.197 christos goto out; 1758 1.166 atatat #endif /* SYSCTL_DISALLOW_CREATE */ 1759 1.166 atatat } 1760 1.166 atatat 1761 1.166 atatat /* 1762 1.166 atatat * find node and try to set the description on it 1763 1.166 atatat */ 1764 1.166 atatat for (i = 0; i < rnode->sysctl_clen; i++) 1765 1.166 atatat if (node[i].sysctl_num == dnode.sysctl_num) 1766 1.166 atatat break; 1767 1.197 christos if (i == rnode->sysctl_clen) { 1768 1.197 christos error = ENOENT; 1769 1.197 christos goto out; 1770 1.197 christos } 1771 1.166 atatat node = &node[i]; 1772 1.166 atatat 1773 1.166 atatat /* 1774 1.166 atatat * did the caller specify a node version? 1775 1.166 atatat */ 1776 1.166 atatat if (dnode.sysctl_ver != 0 && 1777 1.197 christos dnode.sysctl_ver != node->sysctl_ver) { 1778 1.197 christos error = EINVAL; 1779 1.197 christos goto out; 1780 1.197 christos } 1781 1.166 atatat 1782 1.166 atatat /* 1783 1.166 atatat * okay...some rules: 1784 1.170 atatat * (1) if setup is done and the tree is 1785 1.170 atatat * read-only or the whole system is 1786 1.170 atatat * read-only 1787 1.170 atatat * (2) no one can set a description on a 1788 1.166 atatat * permanent node (it must be set when 1789 1.166 atatat * using createv) 1790 1.170 atatat * (3) processes cannot *change* a description 1791 1.170 atatat * (4) processes *can*, however, set a 1792 1.166 atatat * description on a read-only node so that 1793 1.166 atatat * one can be created and then described 1794 1.166 atatat * in two steps 1795 1.166 atatat * anything else come to mind? 1796 1.166 atatat */ 1797 1.170 atatat if ((sysctl_root.sysctl_flags & CTLFLAG_PERMANENT) && 1798 1.170 atatat (!(sysctl_rootof(node)->sysctl_flags & 1799 1.170 atatat CTLFLAG_READWRITE) || 1800 1.197 christos !(sysctl_root.sysctl_flags & CTLFLAG_READWRITE))) { 1801 1.197 christos error = EPERM; 1802 1.197 christos goto out; 1803 1.197 christos } 1804 1.197 christos if (node->sysctl_flags & CTLFLAG_PERMANENT) { 1805 1.197 christos error = EPERM; 1806 1.197 christos goto out; 1807 1.197 christos } 1808 1.197 christos if (l != NULL && node->sysctl_desc != NULL) { 1809 1.197 christos error = EPERM; 1810 1.197 christos goto out; 1811 1.197 christos } 1812 1.166 atatat 1813 1.166 atatat /* 1814 1.166 atatat * right, let's go ahead. the first step is 1815 1.166 atatat * making the description into something the 1816 1.166 atatat * node can "own", if need be. 1817 1.166 atatat */ 1818 1.166 atatat if (l != NULL || 1819 1.166 atatat dnode.sysctl_flags & CTLFLAG_OWNDESC) { 1820 1.197 christos char *nd, *k; 1821 1.166 atatat 1822 1.262 jdolecek k = malloc(MAXDESCLEN, M_TEMP, M_WAITOK); 1823 1.197 christos if (k == NULL) { 1824 1.197 christos error = ENOMEM; 1825 1.197 christos goto out; 1826 1.197 christos } 1827 1.166 atatat error = sysctl_copyinstr(l, dnode.sysctl_desc, 1828 1.197 christos k, MAXDESCLEN, &sz); 1829 1.197 christos if (error) { 1830 1.197 christos free(k, M_TEMP); 1831 1.197 christos goto out; 1832 1.197 christos } 1833 1.262 jdolecek nd = malloc(sz, M_SYSCTLDATA, M_WAITOK); 1834 1.197 christos if (nd == NULL) { 1835 1.197 christos free(k, M_TEMP); 1836 1.197 christos error = ENOMEM; 1837 1.197 christos goto out; 1838 1.197 christos } 1839 1.166 atatat memcpy(nd, k, sz); 1840 1.166 atatat dnode.sysctl_flags |= CTLFLAG_OWNDESC; 1841 1.166 atatat dnode.sysctl_desc = nd; 1842 1.197 christos free(k, M_TEMP); 1843 1.166 atatat } 1844 1.166 atatat 1845 1.166 atatat /* 1846 1.166 atatat * now "release" the old description and 1847 1.166 atatat * attach the new one. ta-da. 1848 1.166 atatat */ 1849 1.166 atatat if ((node->sysctl_flags & CTLFLAG_OWNDESC) && 1850 1.166 atatat node->sysctl_desc != NULL) 1851 1.180 christos /*XXXUNCONST*/ 1852 1.180 christos free(__UNCONST(node->sysctl_desc), M_SYSCTLDATA); 1853 1.166 atatat node->sysctl_desc = dnode.sysctl_desc; 1854 1.166 atatat node->sysctl_flags |= 1855 1.166 atatat (dnode.sysctl_flags & CTLFLAG_OWNDESC); 1856 1.166 atatat 1857 1.166 atatat /* 1858 1.166 atatat * now we "fall out" and into the loop which 1859 1.166 atatat * will copy the new description back out for 1860 1.166 atatat * those interested parties 1861 1.166 atatat */ 1862 1.166 atatat } 1863 1.166 atatat } 1864 1.166 atatat 1865 1.166 atatat /* 1866 1.166 atatat * scan for one description or just retrieve all descriptions 1867 1.166 atatat */ 1868 1.166 atatat for (i = 0; i < rnode->sysctl_clen; i++) { 1869 1.166 atatat /* 1870 1.166 atatat * did they ask for the description of only one node? 1871 1.166 atatat */ 1872 1.166 atatat if (v != -1 && node[i].sysctl_num != dnode.sysctl_num) 1873 1.166 atatat continue; 1874 1.166 atatat 1875 1.166 atatat /* 1876 1.166 atatat * don't describe "private" nodes to non-suser users 1877 1.166 atatat */ 1878 1.166 atatat if ((node[i].sysctl_flags & CTLFLAG_PRIVATE) && (l != NULL) && 1879 1.202 elad !(kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SYSCTL, 1880 1.202 elad KAUTH_REQ_SYSTEM_SYSCTL_PRVT, NULL, NULL, NULL))) 1881 1.166 atatat continue; 1882 1.166 atatat 1883 1.166 atatat /* 1884 1.166 atatat * is this description "valid"? 1885 1.166 atatat */ 1886 1.197 christos memset(bf, 0, MAXDESCLEN); 1887 1.179 perry if (node[i].sysctl_desc == NULL) 1888 1.166 atatat sz = 1; 1889 1.166 atatat else if (copystr(node[i].sysctl_desc, &d->descr_str[0], 1890 1.197 christos MAXDESCLEN - sizeof(*d), &sz) != 0) { 1891 1.166 atatat /* 1892 1.166 atatat * erase possible partial description 1893 1.166 atatat */ 1894 1.197 christos memset(bf, 0, MAXDESCLEN); 1895 1.166 atatat sz = 1; 1896 1.166 atatat } 1897 1.166 atatat 1898 1.166 atatat /* 1899 1.166 atatat * we've got it, stuff it into the caller's buffer 1900 1.166 atatat */ 1901 1.166 atatat d->descr_num = node[i].sysctl_num; 1902 1.166 atatat d->descr_ver = node[i].sysctl_ver; 1903 1.166 atatat d->descr_len = sz; /* includes trailing nul */ 1904 1.209 christos sz = (char *)NEXT_DESCR(d) - (char *)d; 1905 1.166 atatat if (oldp != NULL && left >= sz) { 1906 1.166 atatat error = sysctl_copyout(l, d, oldp, sz); 1907 1.166 atatat if (error) 1908 1.197 christos goto out; 1909 1.166 atatat left -= sz; 1910 1.180 christos oldp = (void *)__sysc_desc_adv(oldp, d->descr_len); 1911 1.166 atatat } 1912 1.166 atatat tot += sz; 1913 1.165 atatat 1914 1.166 atatat /* 1915 1.166 atatat * if we get this far with v not "unset", they asked 1916 1.166 atatat * for a specific node and we found it 1917 1.166 atatat */ 1918 1.166 atatat if (v != -1) 1919 1.166 atatat break; 1920 1.166 atatat } 1921 1.166 atatat 1922 1.166 atatat /* 1923 1.166 atatat * did we find it after all? 1924 1.166 atatat */ 1925 1.166 atatat if (v != -1 && tot == 0) 1926 1.166 atatat error = ENOENT; 1927 1.166 atatat else 1928 1.166 atatat *oldlenp = tot; 1929 1.165 atatat 1930 1.197 christos out: 1931 1.197 christos free(bf, M_TEMP); 1932 1.166 atatat return (error); 1933 1.165 atatat } 1934 1.165 atatat 1935 1.145 dsl /* 1936 1.153 atatat * ******************************************************************** 1937 1.153 atatat * Section 3: Create and destroy from inside the kernel 1938 1.153 atatat * ******************************************************************** 1939 1.153 atatat * sysctl_createv() and sysctl_destroyv() are simpler-to-use 1940 1.153 atatat * interfaces for the kernel to fling new entries into the mib and rip 1941 1.153 atatat * them out later. In the case of sysctl_createv(), the returned copy 1942 1.153 atatat * of the node (see sysctl_create()) will be translated back into a 1943 1.153 atatat * pointer to the actual node. 1944 1.153 atatat * 1945 1.153 atatat * Note that sysctl_createv() will return 0 if the create request 1946 1.153 atatat * matches an existing node (ala mkdir -p), and that sysctl_destroyv() 1947 1.153 atatat * will return 0 if the node to be destroyed already does not exist 1948 1.153 atatat * (aka rm -f) or if it is a parent of other nodes. 1949 1.153 atatat * 1950 1.153 atatat * This allows two (or more) different subsystems to assert sub-tree 1951 1.153 atatat * existence before populating their own nodes, and to remove their 1952 1.153 atatat * own nodes without orphaning the others when they are done. 1953 1.153 atatat * ******************************************************************** 1954 1.145 dsl */ 1955 1.235 dsl #undef sysctl_createv 1956 1.153 atatat int 1957 1.161 atatat sysctl_createv(struct sysctllog **log, int cflags, 1958 1.183 atatat const struct sysctlnode **rnode, const struct sysctlnode **cnode, 1959 1.161 atatat int flags, int type, const char *namep, const char *descr, 1960 1.153 atatat sysctlfn func, u_quad_t qv, void *newp, size_t newlen, 1961 1.153 atatat ...) 1962 1.153 atatat { 1963 1.153 atatat va_list ap; 1964 1.153 atatat int error, ni, namelen, name[CTL_MAXNAME]; 1965 1.183 atatat const struct sysctlnode *root, *pnode; 1966 1.183 atatat struct sysctlnode nnode, onode, *dnode; 1967 1.153 atatat size_t sz; 1968 1.259 pgoyette const struct sysctlnode *snode __diagused; 1969 1.145 dsl 1970 1.161 atatat /* 1971 1.161 atatat * where are we putting this? 1972 1.161 atatat */ 1973 1.161 atatat if (rnode != NULL && *rnode == NULL) { 1974 1.161 atatat printf("sysctl_createv: rnode NULL\n"); 1975 1.161 atatat return (EINVAL); 1976 1.161 atatat } 1977 1.169 atatat root = rnode ? *rnode : NULL; 1978 1.169 atatat if (cnode != NULL) 1979 1.169 atatat *cnode = NULL; 1980 1.169 atatat if (cflags != 0) 1981 1.169 atatat return (EINVAL); 1982 1.161 atatat 1983 1.153 atatat /* 1984 1.153 atatat * what is it? 1985 1.153 atatat */ 1986 1.161 atatat flags = SYSCTL_VERSION|SYSCTL_TYPE(type)|SYSCTL_FLAGS(flags); 1987 1.163 atatat if (log != NULL) 1988 1.163 atatat flags &= ~CTLFLAG_PERMANENT; 1989 1.145 dsl 1990 1.145 dsl /* 1991 1.153 atatat * where do we put it? 1992 1.145 dsl */ 1993 1.153 atatat va_start(ap, newlen); 1994 1.153 atatat namelen = 0; 1995 1.236 matt error = 0; 1996 1.153 atatat ni = -1; 1997 1.153 atatat do { 1998 1.236 matt if (++ni == CTL_MAXNAME) { 1999 1.236 matt error = ENAMETOOLONG; 2000 1.236 matt break; 2001 1.236 matt } 2002 1.153 atatat name[ni] = va_arg(ap, int); 2003 1.153 atatat /* 2004 1.153 atatat * sorry, this is not supported from here 2005 1.153 atatat */ 2006 1.236 matt if (name[ni] == CTL_CREATESYM) { 2007 1.236 matt error = EINVAL; 2008 1.236 matt break; 2009 1.236 matt } 2010 1.153 atatat } while (name[ni] != CTL_EOL && name[ni] != CTL_CREATE); 2011 1.236 matt va_end(ap); 2012 1.236 matt if (error) 2013 1.236 matt return error; 2014 1.153 atatat namelen = ni + (name[ni] == CTL_CREATE ? 1 : 0); 2015 1.69 simonb 2016 1.69 simonb /* 2017 1.153 atatat * what's it called 2018 1.69 simonb */ 2019 1.184 peter if (strlcpy(nnode.sysctl_name, namep, sizeof(nnode.sysctl_name)) >= 2020 1.153 atatat sizeof(nnode.sysctl_name)) 2021 1.153 atatat return (ENAMETOOLONG); 2022 1.69 simonb 2023 1.153 atatat /* 2024 1.153 atatat * cons up the description of the new node 2025 1.153 atatat */ 2026 1.153 atatat nnode.sysctl_num = name[namelen - 1]; 2027 1.153 atatat name[namelen - 1] = CTL_CREATE; 2028 1.153 atatat nnode.sysctl_size = newlen; 2029 1.153 atatat nnode.sysctl_flags = flags; 2030 1.153 atatat if (type == CTLTYPE_NODE) { 2031 1.153 atatat nnode.sysctl_csize = 0; 2032 1.153 atatat nnode.sysctl_clen = 0; 2033 1.153 atatat nnode.sysctl_child = NULL; 2034 1.161 atatat if (flags & CTLFLAG_ALIAS) 2035 1.153 atatat nnode.sysctl_alias = qv; 2036 1.188 yamt } else if (flags & CTLFLAG_IMMEDIATE) { 2037 1.153 atatat switch (type) { 2038 1.215 matt case CTLTYPE_BOOL: 2039 1.215 matt nnode.sysctl_bdata = qv; 2040 1.215 matt break; 2041 1.153 atatat case CTLTYPE_INT: 2042 1.153 atatat nnode.sysctl_idata = qv; 2043 1.153 atatat break; 2044 1.153 atatat case CTLTYPE_QUAD: 2045 1.153 atatat nnode.sysctl_qdata = qv; 2046 1.153 atatat break; 2047 1.153 atatat default: 2048 1.153 atatat return (EINVAL); 2049 1.153 atatat } 2050 1.188 yamt } else { 2051 1.153 atatat nnode.sysctl_data = newp; 2052 1.69 simonb } 2053 1.153 atatat nnode.sysctl_func = func; 2054 1.153 atatat nnode.sysctl_parent = NULL; 2055 1.153 atatat nnode.sysctl_ver = 0; 2056 1.69 simonb 2057 1.153 atatat /* 2058 1.153 atatat * initialize lock state -- we need locks if the main tree has 2059 1.153 atatat * been marked as complete, but since we could be called from 2060 1.153 atatat * either there, or from a device driver (say, at device 2061 1.219 ad * insertion), or from a module (at module load time, say), we 2062 1.153 atatat * don't really want to "wait"... 2063 1.153 atatat */ 2064 1.213 ad sysctl_lock(true); 2065 1.179 perry 2066 1.153 atatat /* 2067 1.153 atatat * locate the prospective parent of the new node, and if we 2068 1.153 atatat * find it, add the new node. 2069 1.153 atatat */ 2070 1.153 atatat sz = sizeof(onode); 2071 1.169 atatat pnode = root; 2072 1.153 atatat error = sysctl_locate(NULL, &name[0], namelen - 1, &pnode, &ni); 2073 1.161 atatat if (error) { 2074 1.249 christos /* 2075 1.249 christos * XXX: If you are seeing this printf in early bringup 2076 1.249 christos * stages, perhaps your setfault is not functioning and 2077 1.249 christos * thus kcopy() is mis-behaving. 2078 1.249 christos */ 2079 1.175 atatat printf("sysctl_createv: sysctl_locate(%s) returned %d\n", 2080 1.175 atatat nnode.sysctl_name, error); 2081 1.213 ad sysctl_unlock(); 2082 1.161 atatat return (error); 2083 1.161 atatat } 2084 1.161 atatat error = sysctl_create(&name[ni], namelen - ni, &onode, &sz, 2085 1.161 atatat &nnode, sizeof(nnode), &name[0], NULL, 2086 1.161 atatat pnode); 2087 1.72 simonb 2088 1.72 simonb /* 2089 1.153 atatat * unfortunately the node we wanted to create is already 2090 1.153 atatat * there. if the node that's already there is a reasonable 2091 1.153 atatat * facsimile of the node we wanted to create, just pretend 2092 1.153 atatat * (for the caller's benefit) that we managed to create the 2093 1.153 atatat * node they wanted. 2094 1.72 simonb */ 2095 1.153 atatat if (error == EEXIST) { 2096 1.153 atatat /* name is the same as requested... */ 2097 1.153 atatat if (strcmp(nnode.sysctl_name, onode.sysctl_name) == 0 && 2098 1.153 atatat /* they want the same function... */ 2099 1.153 atatat nnode.sysctl_func == onode.sysctl_func && 2100 1.153 atatat /* number is the same as requested, or... */ 2101 1.153 atatat (nnode.sysctl_num == onode.sysctl_num || 2102 1.153 atatat /* they didn't pick a number... */ 2103 1.153 atatat nnode.sysctl_num == CTL_CREATE)) { 2104 1.153 atatat /* 2105 1.153 atatat * collision here from trying to create 2106 1.153 atatat * something that already existed; let's give 2107 1.153 atatat * our customers a hand and tell them they got 2108 1.153 atatat * what they wanted. 2109 1.153 atatat */ 2110 1.153 atatat #ifdef SYSCTL_DEBUG_CREATE 2111 1.153 atatat printf("cleared\n"); 2112 1.153 atatat #endif /* SYSCTL_DEBUG_CREATE */ 2113 1.153 atatat error = 0; 2114 1.153 atatat } 2115 1.72 simonb } 2116 1.72 simonb 2117 1.163 atatat if (error == 0 && 2118 1.166 atatat (cnode != NULL || log != NULL || descr != NULL)) { 2119 1.153 atatat /* 2120 1.153 atatat * sysctl_create() gave us back a copy of the node, 2121 1.153 atatat * but we need to know where it actually is... 2122 1.153 atatat */ 2123 1.169 atatat pnode = root; 2124 1.160 atatat error = sysctl_locate(NULL, &name[0], namelen - 1, &pnode, &ni); 2125 1.259 pgoyette snode = pnode; 2126 1.160 atatat 2127 1.160 atatat /* 2128 1.160 atatat * manual scan of last layer so that aliased nodes 2129 1.160 atatat * aren't followed. 2130 1.160 atatat */ 2131 1.160 atatat if (error == 0) { 2132 1.160 atatat for (ni = 0; ni < pnode->sysctl_clen; ni++) 2133 1.160 atatat if (pnode->sysctl_child[ni].sysctl_num == 2134 1.160 atatat onode.sysctl_num) 2135 1.160 atatat break; 2136 1.160 atatat if (ni < pnode->sysctl_clen) 2137 1.160 atatat pnode = &pnode->sysctl_child[ni]; 2138 1.160 atatat else 2139 1.160 atatat error = ENOENT; 2140 1.160 atatat } 2141 1.160 atatat 2142 1.153 atatat /* 2143 1.153 atatat * not expecting an error here, but... 2144 1.153 atatat */ 2145 1.161 atatat if (error == 0) { 2146 1.259 pgoyette KASSERTMSG(pnode->sysctl_parent == snode, 2147 1.263 christos "sysctl parent mis-match pnode %s, snode %s", 2148 1.263 christos pnode->sysctl_name, snode->sysctl_name); 2149 1.163 atatat if (log != NULL) 2150 1.163 atatat sysctl_log_add(log, pnode); 2151 1.161 atatat if (cnode != NULL) 2152 1.161 atatat *cnode = pnode; 2153 1.166 atatat if (descr != NULL) { 2154 1.171 atatat /* 2155 1.171 atatat * allow first caller to *set* a 2156 1.171 atatat * description actually to set it 2157 1.267 skrll * 2158 1.183 atatat * discard const here so we can attach 2159 1.183 atatat * the description 2160 1.171 atatat */ 2161 1.183 atatat dnode = __UNCONST(pnode); 2162 1.171 atatat if (pnode->sysctl_desc != NULL) 2163 1.171 atatat /* skip it...we've got one */; 2164 1.171 atatat else if (flags & CTLFLAG_OWNDESC) { 2165 1.166 atatat size_t l = strlen(descr) + 1; 2166 1.166 atatat char *d = malloc(l, M_SYSCTLDATA, 2167 1.262 jdolecek M_WAITOK); 2168 1.166 atatat if (d != NULL) { 2169 1.166 atatat memcpy(d, descr, l); 2170 1.183 atatat dnode->sysctl_desc = d; 2171 1.183 atatat dnode->sysctl_flags |= 2172 1.171 atatat CTLFLAG_OWNDESC; 2173 1.166 atatat } 2174 1.188 yamt } else 2175 1.183 atatat dnode->sysctl_desc = descr; 2176 1.166 atatat } 2177 1.188 yamt } else { 2178 1.161 atatat printf("sysctl_create succeeded but node not found?!\n"); 2179 1.161 atatat /* 2180 1.161 atatat * confusing, but the create said it 2181 1.161 atatat * succeeded, so... 2182 1.161 atatat */ 2183 1.161 atatat error = 0; 2184 1.161 atatat } 2185 1.72 simonb } 2186 1.72 simonb 2187 1.88 enami /* 2188 1.161 atatat * now it should be safe to release the lock state. note that 2189 1.161 atatat * the pointer to the newly created node being passed back may 2190 1.161 atatat * not be "good" for very long. 2191 1.88 enami */ 2192 1.213 ad sysctl_unlock(); 2193 1.88 enami 2194 1.153 atatat if (error != 0) { 2195 1.153 atatat printf("sysctl_createv: sysctl_create(%s) returned %d\n", 2196 1.153 atatat nnode.sysctl_name, error); 2197 1.153 atatat #if 0 2198 1.153 atatat if (error != ENOENT) 2199 1.153 atatat sysctl_dump(&onode); 2200 1.153 atatat #endif 2201 1.72 simonb } 2202 1.153 atatat 2203 1.72 simonb return (error); 2204 1.72 simonb } 2205 1.69 simonb 2206 1.153 atatat int 2207 1.153 atatat sysctl_destroyv(struct sysctlnode *rnode, ...) 2208 1.1 cgd { 2209 1.153 atatat va_list ap; 2210 1.153 atatat int error, name[CTL_MAXNAME], namelen, ni; 2211 1.183 atatat const struct sysctlnode *pnode, *node; 2212 1.183 atatat struct sysctlnode dnode, *onode; 2213 1.158 atatat size_t sz; 2214 1.153 atatat 2215 1.153 atatat va_start(ap, rnode); 2216 1.153 atatat namelen = 0; 2217 1.153 atatat ni = 0; 2218 1.153 atatat do { 2219 1.240 christos if (ni == CTL_MAXNAME) { 2220 1.240 christos va_end(ap); 2221 1.153 atatat return (ENAMETOOLONG); 2222 1.240 christos } 2223 1.153 atatat name[ni] = va_arg(ap, int); 2224 1.153 atatat } while (name[ni++] != CTL_EOL); 2225 1.153 atatat namelen = ni - 1; 2226 1.153 atatat va_end(ap); 2227 1.62 simonb 2228 1.153 atatat /* 2229 1.153 atatat * i can't imagine why we'd be destroying a node when the tree 2230 1.153 atatat * wasn't complete, but who knows? 2231 1.153 atatat */ 2232 1.213 ad sysctl_lock(true); 2233 1.1 cgd 2234 1.153 atatat /* 2235 1.153 atatat * where is it? 2236 1.153 atatat */ 2237 1.153 atatat node = rnode; 2238 1.160 atatat error = sysctl_locate(NULL, &name[0], namelen - 1, &node, &ni); 2239 1.153 atatat if (error) { 2240 1.153 atatat /* they want it gone and it's not there, so... */ 2241 1.213 ad sysctl_unlock(); 2242 1.153 atatat return (error == ENOENT ? 0 : error); 2243 1.62 simonb } 2244 1.41 thorpej 2245 1.153 atatat /* 2246 1.160 atatat * set up the deletion 2247 1.158 atatat */ 2248 1.160 atatat pnode = node; 2249 1.160 atatat node = &dnode; 2250 1.160 atatat memset(&dnode, 0, sizeof(dnode)); 2251 1.176 cube dnode.sysctl_flags = SYSCTL_VERSION; 2252 1.160 atatat dnode.sysctl_num = name[namelen - 1]; 2253 1.158 atatat 2254 1.158 atatat /* 2255 1.153 atatat * we found it, now let's nuke it 2256 1.153 atatat */ 2257 1.153 atatat name[namelen - 1] = CTL_DESTROY; 2258 1.158 atatat sz = 0; 2259 1.158 atatat error = sysctl_destroy(&name[namelen - 1], 1, NULL, &sz, 2260 1.153 atatat node, sizeof(*node), &name[0], NULL, 2261 1.153 atatat pnode); 2262 1.166 atatat if (error == ENOTEMPTY) { 2263 1.1 cgd /* 2264 1.153 atatat * think of trying to delete "foo" when "foo.bar" 2265 1.153 atatat * (which someone else put there) is still in 2266 1.153 atatat * existence 2267 1.1 cgd */ 2268 1.153 atatat error = 0; 2269 1.1 cgd 2270 1.166 atatat /* 2271 1.166 atatat * dunno who put the description there, but if this 2272 1.166 atatat * node can ever be removed, we need to make sure the 2273 1.166 atatat * string doesn't go out of context. that means we 2274 1.166 atatat * need to find the node that's still there (don't use 2275 1.166 atatat * sysctl_locate() because that follows aliasing). 2276 1.166 atatat */ 2277 1.166 atatat node = pnode->sysctl_child; 2278 1.166 atatat for (ni = 0; ni < pnode->sysctl_clen; ni++) 2279 1.166 atatat if (node[ni].sysctl_num == dnode.sysctl_num) 2280 1.166 atatat break; 2281 1.166 atatat node = (ni < pnode->sysctl_clen) ? &node[ni] : NULL; 2282 1.166 atatat 2283 1.166 atatat /* 2284 1.166 atatat * if we found it, and this node has a description, 2285 1.166 atatat * and this node can be released, and it doesn't 2286 1.166 atatat * already own its own description...sigh. :) 2287 1.166 atatat */ 2288 1.166 atatat if (node != NULL && node->sysctl_desc != NULL && 2289 1.166 atatat !(node->sysctl_flags & CTLFLAG_PERMANENT) && 2290 1.166 atatat !(node->sysctl_flags & CTLFLAG_OWNDESC)) { 2291 1.166 atatat char *d; 2292 1.166 atatat 2293 1.166 atatat sz = strlen(node->sysctl_desc) + 1; 2294 1.262 jdolecek d = malloc(sz, M_SYSCTLDATA, M_WAITOK); 2295 1.166 atatat if (d != NULL) { 2296 1.183 atatat /* 2297 1.183 atatat * discard const so that we can 2298 1.183 atatat * re-attach the description 2299 1.183 atatat */ 2300 1.166 atatat memcpy(d, node->sysctl_desc, sz); 2301 1.183 atatat onode = __UNCONST(node); 2302 1.183 atatat onode->sysctl_desc = d; 2303 1.183 atatat onode->sysctl_flags |= CTLFLAG_OWNDESC; 2304 1.188 yamt } else { 2305 1.166 atatat /* 2306 1.166 atatat * XXX drop the description? be 2307 1.166 atatat * afraid? don't care? 2308 1.166 atatat */ 2309 1.166 atatat } 2310 1.166 atatat } 2311 1.166 atatat } 2312 1.166 atatat 2313 1.213 ad sysctl_unlock(); 2314 1.1 cgd 2315 1.153 atatat return (error); 2316 1.153 atatat } 2317 1.1 cgd 2318 1.123 thorpej /* 2319 1.153 atatat * ******************************************************************** 2320 1.153 atatat * Deletes an entire n-ary tree. Not recommended unless you know why 2321 1.153 atatat * you're doing it. Personally, I don't know why you'd even think 2322 1.153 atatat * about it. 2323 1.153 atatat * ******************************************************************** 2324 1.123 thorpej */ 2325 1.153 atatat void 2326 1.153 atatat sysctl_free(struct sysctlnode *rnode) 2327 1.123 thorpej { 2328 1.153 atatat struct sysctlnode *node, *pnode; 2329 1.123 thorpej 2330 1.214 ad rw_enter(&sysctl_treelock, RW_WRITER); 2331 1.213 ad 2332 1.192 chris if (rnode == NULL) 2333 1.192 chris rnode = &sysctl_root; 2334 1.192 chris 2335 1.161 atatat if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 2336 1.161 atatat printf("sysctl_free: rnode %p wrong version\n", rnode); 2337 1.214 ad rw_exit(&sysctl_treelock); 2338 1.161 atatat return; 2339 1.161 atatat } 2340 1.161 atatat 2341 1.153 atatat pnode = rnode; 2342 1.153 atatat 2343 1.153 atatat node = pnode->sysctl_child; 2344 1.153 atatat do { 2345 1.153 atatat while (node != NULL && pnode->sysctl_csize > 0) { 2346 1.153 atatat while (node < 2347 1.153 atatat &pnode->sysctl_child[pnode->sysctl_clen] && 2348 1.153 atatat (SYSCTL_TYPE(node->sysctl_flags) != 2349 1.153 atatat CTLTYPE_NODE || 2350 1.153 atatat node->sysctl_csize == 0)) { 2351 1.153 atatat if (SYSCTL_FLAGS(node->sysctl_flags) & 2352 1.161 atatat CTLFLAG_OWNDATA) { 2353 1.153 atatat if (node->sysctl_data != NULL) { 2354 1.187 yamt free(node->sysctl_data, 2355 1.153 atatat M_SYSCTLDATA); 2356 1.153 atatat node->sysctl_data = NULL; 2357 1.153 atatat } 2358 1.153 atatat } 2359 1.166 atatat if (SYSCTL_FLAGS(node->sysctl_flags) & 2360 1.166 atatat CTLFLAG_OWNDESC) { 2361 1.166 atatat if (node->sysctl_desc != NULL) { 2362 1.180 christos /*XXXUNCONST*/ 2363 1.187 yamt free(__UNCONST(node->sysctl_desc), 2364 1.166 atatat M_SYSCTLDATA); 2365 1.166 atatat node->sysctl_desc = NULL; 2366 1.166 atatat } 2367 1.166 atatat } 2368 1.153 atatat node++; 2369 1.153 atatat } 2370 1.153 atatat if (node < &pnode->sysctl_child[pnode->sysctl_clen]) { 2371 1.153 atatat pnode = node; 2372 1.153 atatat node = node->sysctl_child; 2373 1.188 yamt } else 2374 1.153 atatat break; 2375 1.153 atatat } 2376 1.153 atatat if (pnode->sysctl_child != NULL) 2377 1.187 yamt free(pnode->sysctl_child, M_SYSCTLNODE); 2378 1.153 atatat pnode->sysctl_clen = 0; 2379 1.153 atatat pnode->sysctl_csize = 0; 2380 1.153 atatat pnode->sysctl_child = NULL; 2381 1.153 atatat node = pnode; 2382 1.153 atatat pnode = node->sysctl_parent; 2383 1.158 atatat } while (pnode != NULL && node != rnode); 2384 1.214 ad 2385 1.214 ad rw_exit(&sysctl_treelock); 2386 1.123 thorpej } 2387 1.123 thorpej 2388 1.224 dyoung void 2389 1.224 dyoung sysctl_log_print(const struct sysctllog *slog) 2390 1.224 dyoung { 2391 1.224 dyoung int i, len; 2392 1.224 dyoung 2393 1.224 dyoung printf("root %p left %d size %d content", (const void *)slog->log_root, 2394 1.224 dyoung slog->log_left, slog->log_size); 2395 1.224 dyoung 2396 1.224 dyoung for (len = 0, i = slog->log_left; i < slog->log_size; i++) { 2397 1.224 dyoung switch (len) { 2398 1.224 dyoung case 0: 2399 1.224 dyoung len = -1; 2400 1.224 dyoung printf(" version %d", slog->log_num[i]); 2401 1.224 dyoung break; 2402 1.224 dyoung case -1: 2403 1.224 dyoung len = -2; 2404 1.224 dyoung printf(" type %d", slog->log_num[i]); 2405 1.224 dyoung break; 2406 1.224 dyoung case -2: 2407 1.224 dyoung len = slog->log_num[i]; 2408 1.224 dyoung printf(" len %d:", slog->log_num[i]); 2409 1.224 dyoung if (len <= 0) 2410 1.224 dyoung len = -1; 2411 1.224 dyoung break; 2412 1.224 dyoung default: 2413 1.224 dyoung len--; 2414 1.224 dyoung printf(" %d", slog->log_num[i]); 2415 1.224 dyoung break; 2416 1.224 dyoung } 2417 1.224 dyoung } 2418 1.224 dyoung printf(" end\n"); 2419 1.224 dyoung } 2420 1.224 dyoung 2421 1.163 atatat int 2422 1.183 atatat sysctl_log_add(struct sysctllog **logp, const struct sysctlnode *node) 2423 1.163 atatat { 2424 1.224 dyoung const int size0 = 16; 2425 1.163 atatat int name[CTL_MAXNAME], namelen, i; 2426 1.183 atatat const struct sysctlnode *pnode; 2427 1.163 atatat struct sysctllog *log; 2428 1.163 atatat 2429 1.163 atatat if (node->sysctl_flags & CTLFLAG_PERMANENT) 2430 1.163 atatat return (0); 2431 1.163 atatat 2432 1.163 atatat if (logp == NULL) 2433 1.163 atatat return (0); 2434 1.163 atatat 2435 1.163 atatat if (*logp == NULL) { 2436 1.187 yamt log = malloc(sizeof(struct sysctllog), 2437 1.262 jdolecek M_SYSCTLDATA, M_WAITOK); 2438 1.163 atatat if (log == NULL) { 2439 1.163 atatat /* XXX print error message? */ 2440 1.163 atatat return (-1); 2441 1.163 atatat } 2442 1.224 dyoung log->log_num = malloc(size0 * sizeof(int), 2443 1.262 jdolecek M_SYSCTLDATA, M_WAITOK); 2444 1.163 atatat if (log->log_num == NULL) { 2445 1.163 atatat /* XXX print error message? */ 2446 1.163 atatat free(log, M_SYSCTLDATA); 2447 1.163 atatat return (-1); 2448 1.163 atatat } 2449 1.224 dyoung memset(log->log_num, 0, size0 * sizeof(int)); 2450 1.163 atatat log->log_root = NULL; 2451 1.224 dyoung log->log_size = size0; 2452 1.224 dyoung log->log_left = size0; 2453 1.163 atatat *logp = log; 2454 1.188 yamt } else 2455 1.163 atatat log = *logp; 2456 1.163 atatat 2457 1.163 atatat /* 2458 1.163 atatat * check that the root is proper. it's okay to record the 2459 1.163 atatat * address of the root of a tree. it's the only thing that's 2460 1.163 atatat * guaranteed not to shift around as nodes come and go. 2461 1.163 atatat */ 2462 1.163 atatat if (log->log_root == NULL) 2463 1.163 atatat log->log_root = sysctl_rootof(node); 2464 1.163 atatat else if (log->log_root != sysctl_rootof(node)) { 2465 1.163 atatat printf("sysctl: log %p root mismatch (%p)\n", 2466 1.163 atatat log->log_root, sysctl_rootof(node)); 2467 1.163 atatat return (-1); 2468 1.163 atatat } 2469 1.163 atatat 2470 1.163 atatat /* 2471 1.163 atatat * we will copy out name in reverse order 2472 1.163 atatat */ 2473 1.163 atatat for (pnode = node, namelen = 0; 2474 1.163 atatat pnode != NULL && !(pnode->sysctl_flags & CTLFLAG_ROOT); 2475 1.163 atatat pnode = pnode->sysctl_parent) 2476 1.163 atatat name[namelen++] = pnode->sysctl_num; 2477 1.163 atatat 2478 1.163 atatat /* 2479 1.163 atatat * do we have space? 2480 1.163 atatat */ 2481 1.163 atatat if (log->log_left < (namelen + 3)) 2482 1.163 atatat sysctl_log_realloc(log); 2483 1.163 atatat if (log->log_left < (namelen + 3)) 2484 1.163 atatat return (-1); 2485 1.163 atatat 2486 1.163 atatat /* 2487 1.163 atatat * stuff name in, then namelen, then node type, and finally, 2488 1.163 atatat * the version for non-node nodes. 2489 1.163 atatat */ 2490 1.260 pgoyette for (i = 0; i < namelen && i < CTL_MAXNAME; i++) 2491 1.163 atatat log->log_num[--log->log_left] = name[i]; 2492 1.163 atatat log->log_num[--log->log_left] = namelen; 2493 1.163 atatat log->log_num[--log->log_left] = SYSCTL_TYPE(node->sysctl_flags); 2494 1.163 atatat if (log->log_num[log->log_left] != CTLTYPE_NODE) 2495 1.163 atatat log->log_num[--log->log_left] = node->sysctl_ver; 2496 1.163 atatat else 2497 1.163 atatat log->log_num[--log->log_left] = 0; 2498 1.163 atatat 2499 1.163 atatat return (0); 2500 1.163 atatat } 2501 1.163 atatat 2502 1.163 atatat void 2503 1.163 atatat sysctl_teardown(struct sysctllog **logp) 2504 1.163 atatat { 2505 1.183 atatat const struct sysctlnode *rnode; 2506 1.183 atatat struct sysctlnode node; 2507 1.163 atatat struct sysctllog *log; 2508 1.163 atatat uint namelen; 2509 1.163 atatat int *name, t, v, error, ni; 2510 1.163 atatat size_t sz; 2511 1.163 atatat 2512 1.163 atatat if (logp == NULL || *logp == NULL) 2513 1.163 atatat return; 2514 1.163 atatat log = *logp; 2515 1.163 atatat 2516 1.213 ad rw_enter(&sysctl_treelock, RW_WRITER); 2517 1.163 atatat memset(&node, 0, sizeof(node)); 2518 1.163 atatat 2519 1.163 atatat while (log->log_left < log->log_size) { 2520 1.269 riastrad KASSERT(log->log_left + 3 < log->log_size); 2521 1.269 riastrad KASSERT(log->log_left + log->log_num[log->log_left + 2] <= 2522 1.269 riastrad log->log_size); 2523 1.163 atatat v = log->log_num[log->log_left++]; 2524 1.163 atatat t = log->log_num[log->log_left++]; 2525 1.163 atatat namelen = log->log_num[log->log_left++]; 2526 1.163 atatat name = &log->log_num[log->log_left]; 2527 1.163 atatat 2528 1.163 atatat node.sysctl_num = name[namelen - 1]; 2529 1.168 atatat node.sysctl_flags = SYSCTL_VERSION|t; 2530 1.163 atatat node.sysctl_ver = v; 2531 1.163 atatat 2532 1.163 atatat rnode = log->log_root; 2533 1.163 atatat error = sysctl_locate(NULL, &name[0], namelen, &rnode, &ni); 2534 1.163 atatat if (error == 0) { 2535 1.163 atatat name[namelen - 1] = CTL_DESTROY; 2536 1.163 atatat rnode = rnode->sysctl_parent; 2537 1.163 atatat sz = 0; 2538 1.163 atatat (void)sysctl_destroy(&name[namelen - 1], 1, NULL, 2539 1.163 atatat &sz, &node, sizeof(node), 2540 1.163 atatat &name[0], NULL, rnode); 2541 1.163 atatat } 2542 1.163 atatat 2543 1.163 atatat log->log_left += namelen; 2544 1.163 atatat } 2545 1.163 atatat 2546 1.163 atatat KASSERT(log->log_size == log->log_left); 2547 1.163 atatat free(log->log_num, M_SYSCTLDATA); 2548 1.163 atatat free(log, M_SYSCTLDATA); 2549 1.163 atatat *logp = NULL; 2550 1.163 atatat 2551 1.213 ad rw_exit(&sysctl_treelock); 2552 1.163 atatat } 2553 1.163 atatat 2554 1.1 cgd /* 2555 1.153 atatat * ******************************************************************** 2556 1.153 atatat * old_sysctl -- A routine to bridge old-style internal calls to the 2557 1.153 atatat * new infrastructure. 2558 1.153 atatat * ******************************************************************** 2559 1.1 cgd */ 2560 1.153 atatat int 2561 1.153 atatat old_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2562 1.153 atatat void *newp, size_t newlen, struct lwp *l) 2563 1.1 cgd { 2564 1.153 atatat int error; 2565 1.186 yamt size_t oldlen = 0; 2566 1.186 yamt size_t savelen; 2567 1.186 yamt 2568 1.186 yamt if (oldlenp) { 2569 1.186 yamt oldlen = *oldlenp; 2570 1.186 yamt } 2571 1.186 yamt savelen = oldlen; 2572 1.179 perry 2573 1.213 ad sysctl_lock(newp != NULL); 2574 1.186 yamt error = sysctl_dispatch(name, namelen, oldp, &oldlen, 2575 1.153 atatat newp, newlen, name, l, NULL); 2576 1.213 ad sysctl_unlock(); 2577 1.186 yamt if (error == 0 && oldp != NULL && savelen < oldlen) 2578 1.153 atatat error = ENOMEM; 2579 1.186 yamt if (oldlenp) { 2580 1.186 yamt *oldlenp = oldlen; 2581 1.186 yamt } 2582 1.186 yamt 2583 1.153 atatat return (error); 2584 1.62 simonb } 2585 1.62 simonb 2586 1.62 simonb /* 2587 1.153 atatat * ******************************************************************** 2588 1.153 atatat * Section 4: Generic helper routines 2589 1.153 atatat * ******************************************************************** 2590 1.153 atatat * "helper" routines that can do more finely grained access control, 2591 1.153 atatat * construct structures from disparate information, create the 2592 1.153 atatat * appearance of more nodes and sub-trees, etc. for example, if 2593 1.153 atatat * CTL_PROC wanted a helper function, it could respond to a CTL_QUERY 2594 1.153 atatat * with a dynamically created list of nodes that represented the 2595 1.153 atatat * currently running processes at that instant. 2596 1.153 atatat * ******************************************************************** 2597 1.153 atatat */ 2598 1.123 thorpej 2599 1.123 thorpej /* 2600 1.153 atatat * first, a few generic helpers that provide: 2601 1.153 atatat * 2602 1.153 atatat * sysctl_needfunc() a readonly interface that emits a warning 2603 1.153 atatat * sysctl_notavail() returns EOPNOTSUPP (generic error) 2604 1.153 atatat * sysctl_null() an empty return buffer with no error 2605 1.123 thorpej */ 2606 1.62 simonb int 2607 1.153 atatat sysctl_needfunc(SYSCTLFN_ARGS) 2608 1.62 simonb { 2609 1.153 atatat int error; 2610 1.153 atatat 2611 1.153 atatat printf("!!SYSCTL_NEEDFUNC!!\n"); 2612 1.62 simonb 2613 1.153 atatat if (newp != NULL || namelen != 0) 2614 1.153 atatat return (EOPNOTSUPP); 2615 1.62 simonb 2616 1.153 atatat error = 0; 2617 1.153 atatat if (oldp != NULL) 2618 1.153 atatat error = sysctl_copyout(l, rnode->sysctl_data, oldp, 2619 1.153 atatat MIN(rnode->sysctl_size, *oldlenp)); 2620 1.153 atatat *oldlenp = rnode->sysctl_size; 2621 1.62 simonb 2622 1.153 atatat return (error); 2623 1.153 atatat } 2624 1.62 simonb 2625 1.153 atatat int 2626 1.153 atatat sysctl_notavail(SYSCTLFN_ARGS) 2627 1.153 atatat { 2628 1.62 simonb 2629 1.155 atatat if (namelen == 1 && name[0] == CTL_QUERY) 2630 1.182 atatat return (sysctl_query(SYSCTLFN_CALL(rnode))); 2631 1.155 atatat 2632 1.153 atatat return (EOPNOTSUPP); 2633 1.153 atatat } 2634 1.62 simonb 2635 1.153 atatat int 2636 1.153 atatat sysctl_null(SYSCTLFN_ARGS) 2637 1.153 atatat { 2638 1.62 simonb 2639 1.153 atatat *oldlenp = 0; 2640 1.123 thorpej 2641 1.153 atatat return (0); 2642 1.153 atatat } 2643 1.67 simonb 2644 1.230 pooka u_int 2645 1.230 pooka sysctl_map_flags(const u_int *map, u_int word) 2646 1.230 pooka { 2647 1.230 pooka u_int rv; 2648 1.230 pooka 2649 1.230 pooka for (rv = 0; *map != 0; map += 2) 2650 1.230 pooka if ((word & map[0]) != 0) 2651 1.230 pooka rv |= map[1]; 2652 1.230 pooka 2653 1.230 pooka return rv; 2654 1.230 pooka } 2655 1.230 pooka 2656 1.153 atatat /* 2657 1.153 atatat * ******************************************************************** 2658 1.153 atatat * Section 5: The machinery that makes it all go 2659 1.153 atatat * ******************************************************************** 2660 1.153 atatat * Memory "manglement" routines. Not much to this, eh? 2661 1.153 atatat * ******************************************************************** 2662 1.153 atatat */ 2663 1.153 atatat static int 2664 1.153 atatat sysctl_alloc(struct sysctlnode *p, int x) 2665 1.153 atatat { 2666 1.153 atatat int i; 2667 1.153 atatat struct sysctlnode *n; 2668 1.62 simonb 2669 1.153 atatat assert(p->sysctl_child == NULL); 2670 1.62 simonb 2671 1.153 atatat if (x == 1) 2672 1.187 yamt n = malloc(sizeof(struct sysctlnode), 2673 1.262 jdolecek M_SYSCTLNODE, M_WAITOK); 2674 1.62 simonb else 2675 1.187 yamt n = malloc(SYSCTL_DEFSIZE * sizeof(struct sysctlnode), 2676 1.262 jdolecek M_SYSCTLNODE, M_WAITOK); 2677 1.153 atatat if (n == NULL) 2678 1.153 atatat return (ENOMEM); 2679 1.153 atatat 2680 1.153 atatat if (x == 1) { 2681 1.153 atatat memset(n, 0, sizeof(struct sysctlnode)); 2682 1.153 atatat p->sysctl_csize = 1; 2683 1.188 yamt } else { 2684 1.153 atatat memset(n, 0, SYSCTL_DEFSIZE * sizeof(struct sysctlnode)); 2685 1.153 atatat p->sysctl_csize = SYSCTL_DEFSIZE; 2686 1.62 simonb } 2687 1.153 atatat p->sysctl_clen = 0; 2688 1.62 simonb 2689 1.153 atatat for (i = 0; i < p->sysctl_csize; i++) 2690 1.153 atatat n[i].sysctl_parent = p; 2691 1.62 simonb 2692 1.153 atatat p->sysctl_child = n; 2693 1.153 atatat return (0); 2694 1.1 cgd } 2695 1.78 jdolecek 2696 1.78 jdolecek static int 2697 1.153 atatat sysctl_realloc(struct sysctlnode *p) 2698 1.78 jdolecek { 2699 1.224 dyoung int i, j, olen; 2700 1.153 atatat struct sysctlnode *n; 2701 1.78 jdolecek 2702 1.153 atatat assert(p->sysctl_csize == p->sysctl_clen); 2703 1.78 jdolecek 2704 1.153 atatat /* 2705 1.153 atatat * how many do we have...how many should we make? 2706 1.153 atatat */ 2707 1.224 dyoung olen = p->sysctl_clen; 2708 1.224 dyoung n = malloc(2 * olen * sizeof(struct sysctlnode), M_SYSCTLNODE, 2709 1.262 jdolecek M_WAITOK); 2710 1.153 atatat if (n == NULL) 2711 1.153 atatat return (ENOMEM); 2712 1.78 jdolecek 2713 1.153 atatat /* 2714 1.153 atatat * move old children over...initialize new children 2715 1.153 atatat */ 2716 1.224 dyoung memcpy(n, p->sysctl_child, olen * sizeof(struct sysctlnode)); 2717 1.224 dyoung memset(&n[olen], 0, olen * sizeof(struct sysctlnode)); 2718 1.224 dyoung p->sysctl_csize = 2 * olen; 2719 1.78 jdolecek 2720 1.153 atatat /* 2721 1.153 atatat * reattach moved (and new) children to parent; if a moved 2722 1.153 atatat * child node has children, reattach the parent pointers of 2723 1.153 atatat * grandchildren 2724 1.153 atatat */ 2725 1.153 atatat for (i = 0; i < p->sysctl_csize; i++) { 2726 1.153 atatat n[i].sysctl_parent = p; 2727 1.153 atatat if (n[i].sysctl_child != NULL) { 2728 1.153 atatat for (j = 0; j < n[i].sysctl_csize; j++) 2729 1.153 atatat n[i].sysctl_child[j].sysctl_parent = &n[i]; 2730 1.153 atatat } 2731 1.78 jdolecek } 2732 1.78 jdolecek 2733 1.153 atatat /* 2734 1.153 atatat * get out with the old and in with the new 2735 1.153 atatat */ 2736 1.187 yamt free(p->sysctl_child, M_SYSCTLNODE); 2737 1.153 atatat p->sysctl_child = n; 2738 1.100 simonb 2739 1.153 atatat return (0); 2740 1.100 simonb } 2741 1.162 atatat 2742 1.163 atatat static int 2743 1.163 atatat sysctl_log_realloc(struct sysctllog *log) 2744 1.163 atatat { 2745 1.163 atatat int *n, s, d; 2746 1.163 atatat 2747 1.163 atatat s = log->log_size * 2; 2748 1.163 atatat d = log->log_size; 2749 1.163 atatat 2750 1.262 jdolecek n = malloc(s * sizeof(int), M_SYSCTLDATA, M_WAITOK); 2751 1.163 atatat if (n == NULL) 2752 1.163 atatat return (-1); 2753 1.163 atatat 2754 1.163 atatat memset(n, 0, s * sizeof(int)); 2755 1.163 atatat memcpy(&n[d], log->log_num, d * sizeof(int)); 2756 1.163 atatat free(log->log_num, M_SYSCTLDATA); 2757 1.163 atatat log->log_num = n; 2758 1.163 atatat if (d) 2759 1.163 atatat log->log_left += d; 2760 1.163 atatat else 2761 1.163 atatat log->log_left = s; 2762 1.163 atatat log->log_size = s; 2763 1.163 atatat 2764 1.163 atatat return (0); 2765 1.163 atatat } 2766 1.163 atatat 2767 1.162 atatat /* 2768 1.162 atatat * ******************************************************************** 2769 1.162 atatat * Section 6: Conversion between API versions wrt the sysctlnode 2770 1.162 atatat * ******************************************************************** 2771 1.162 atatat */ 2772 1.162 atatat static int 2773 1.162 atatat sysctl_cvt_in(struct lwp *l, int *vp, const void *i, size_t sz, 2774 1.162 atatat struct sysctlnode *node) 2775 1.162 atatat { 2776 1.162 atatat int error, flags; 2777 1.162 atatat 2778 1.172 atatat if (i == NULL || sz < sizeof(flags)) 2779 1.162 atatat return (EINVAL); 2780 1.162 atatat 2781 1.162 atatat error = sysctl_copyin(l, i, &flags, sizeof(flags)); 2782 1.162 atatat if (error) 2783 1.162 atatat return (error); 2784 1.162 atatat 2785 1.164 atatat #if (SYSCTL_VERSION != SYSCTL_VERS_1) 2786 1.164 atatat #error sysctl_cvt_in: no support for SYSCTL_VERSION 2787 1.164 atatat #endif /* (SYSCTL_VERSION != SYSCTL_VERS_1) */ 2788 1.164 atatat 2789 1.162 atatat if (sz == sizeof(*node) && 2790 1.162 atatat SYSCTL_VERS(flags) == SYSCTL_VERSION) { 2791 1.162 atatat error = sysctl_copyin(l, i, node, sizeof(*node)); 2792 1.162 atatat if (error) 2793 1.162 atatat return (error); 2794 1.162 atatat *vp = SYSCTL_VERSION; 2795 1.162 atatat return (0); 2796 1.162 atatat } 2797 1.162 atatat 2798 1.162 atatat return (EINVAL); 2799 1.162 atatat } 2800 1.162 atatat 2801 1.162 atatat static int 2802 1.162 atatat sysctl_cvt_out(struct lwp *l, int v, const struct sysctlnode *i, 2803 1.162 atatat void *ovp, size_t left, size_t *szp) 2804 1.162 atatat { 2805 1.162 atatat size_t sz = sizeof(*i); 2806 1.162 atatat const void *src = i; 2807 1.162 atatat int error; 2808 1.162 atatat 2809 1.162 atatat switch (v) { 2810 1.164 atatat case SYSCTL_VERS_0: 2811 1.172 atatat return (EINVAL); 2812 1.164 atatat 2813 1.164 atatat #if (SYSCTL_VERSION != SYSCTL_VERS_1) 2814 1.164 atatat #error sysctl_cvt_out: no support for SYSCTL_VERSION 2815 1.164 atatat #endif /* (SYSCTL_VERSION != SYSCTL_VERS_1) */ 2816 1.164 atatat 2817 1.162 atatat case SYSCTL_VERSION: 2818 1.162 atatat /* nothing more to do here */ 2819 1.162 atatat break; 2820 1.162 atatat } 2821 1.162 atatat 2822 1.162 atatat if (ovp != NULL && left >= sz) { 2823 1.162 atatat error = sysctl_copyout(l, src, ovp, sz); 2824 1.162 atatat if (error) 2825 1.162 atatat return (error); 2826 1.162 atatat } 2827 1.162 atatat 2828 1.162 atatat if (szp != NULL) 2829 1.162 atatat *szp = sz; 2830 1.162 atatat 2831 1.162 atatat return (0); 2832 1.162 atatat } 2833 1.265 riastrad 2834 1.265 riastrad static uint8_t address_key[32]; /* key used in address hashing */ 2835 1.265 riastrad static ONCE_DECL(random_inithook); 2836 1.265 riastrad 2837 1.265 riastrad static int 2838 1.265 riastrad random_address_init(void) 2839 1.265 riastrad { 2840 1.266 riastrad 2841 1.265 riastrad cprng_strong(kern_cprng, address_key, sizeof(address_key), 0); 2842 1.265 riastrad return 0; 2843 1.265 riastrad } 2844 1.265 riastrad 2845 1.265 riastrad void 2846 1.270 christos hash_value_ensure_initialized(void) 2847 1.270 christos { 2848 1.270 christos 2849 1.270 christos RUN_ONCE(&random_inithook, random_address_init); 2850 1.270 christos } 2851 1.270 christos 2852 1.270 christos void 2853 1.265 riastrad hash_value(void *d, size_t ds, const void *s, size_t ss) 2854 1.266 riastrad { 2855 1.265 riastrad 2856 1.265 riastrad blake2s(d, ds, address_key, sizeof(address_key), s, ss); 2857 1.265 riastrad } 2858