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