1 /* $NetBSD: kern_sysctl.c,v 1.176 2004/05/12 12:21:39 cube 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.176 2004/05/12 12:21:39 cube 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_RWPROTO); 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 **, struct sysctlnode *); 109 static int sysctl_log_realloc(struct sysctllog *); 110 111 struct sysctllog { 112 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 static 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_RWARGS) 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 struct sysctlnode **rnode, int *nip) 483 { 484 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 struct sysctlnode *enode, *onode, qnode; 594 595 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 596 printf("sysctl_query: rnode %p wrong version\n", rnode); 597 return (EINVAL); 598 } 599 600 if (SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE) 601 return (ENOTDIR); 602 if (namelen != 1 || name[0] != CTL_QUERY) 603 return (EINVAL); 604 605 error = 0; 606 out = 0; 607 left = *oldlenp; 608 elim = 0; 609 enode = NULL; 610 611 /* 612 * translate the given request to a current node 613 */ 614 error = sysctl_cvt_in(l, &v, newp, newlen, &qnode); 615 if (error) 616 return (error); 617 618 /* 619 * if the request specifies a version, check it 620 */ 621 if (qnode.sysctl_ver != 0) { 622 enode = (struct sysctlnode *)rnode; /* discard const */ 623 if (qnode.sysctl_ver != enode->sysctl_ver && 624 qnode.sysctl_ver != sysctl_rootof(enode)->sysctl_ver) 625 return (EINVAL); 626 } 627 628 /* 629 * process has overlay tree 630 */ 631 if (l && l->l_proc->p_emul->e_sysctlovly) { 632 enode = l->l_proc->p_emul->e_sysctlovly; 633 elim = (name - oname); 634 error = sysctl_locate(l, oname, elim, &enode, NULL); 635 if (error == 0) { 636 /* ah, found parent in overlay */ 637 elim = enode->sysctl_clen; 638 enode = enode->sysctl_child; 639 } 640 else { 641 error = 0; 642 elim = 0; 643 enode = NULL; 644 } 645 } 646 647 for (ni = 0; ni < rnode->sysctl_clen; ni++) { 648 onode = &rnode->sysctl_child[ni]; 649 if (enode && enode->sysctl_num == onode->sysctl_num) { 650 if (SYSCTL_TYPE(enode->sysctl_flags) != CTLTYPE_NODE) 651 onode = enode; 652 if (--elim > 0) 653 enode++; 654 else 655 enode = NULL; 656 } 657 error = sysctl_cvt_out(l, v, onode, oldp, left, &t); 658 if (error) 659 return (error); 660 if (oldp != NULL) 661 oldp = (char*)oldp + t; 662 out += t; 663 left -= MIN(left, t); 664 } 665 666 /* 667 * overlay trees *MUST* be entirely consumed 668 */ 669 KASSERT(enode == NULL); 670 671 *oldlenp = out; 672 673 return (error); 674 } 675 676 #ifdef SYSCTL_DEBUG_CREATE 677 #undef sysctl_create 678 #endif /* SYSCTL_DEBUG_CREATE */ 679 680 /* 681 * sysctl_create -- Adds a node (the description of which is taken 682 * from newp) to the tree, returning a copy of it in the space pointed 683 * to by oldp. In the event that the requested slot is already taken 684 * (either by name or by number), the offending node is returned 685 * instead. Yes, this is complex, but we want to make sure everything 686 * is proper. 687 */ 688 int 689 sysctl_create(SYSCTLFN_RWARGS) 690 { 691 struct sysctlnode nnode, *node, *pnode; 692 int error, ni, at, nm, type, sz, flags, rw, anum, v; 693 void *own; 694 695 error = 0; 696 own = NULL; 697 anum = -1; 698 699 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 700 printf("sysctl_create: rnode %p wrong version\n", rnode); 701 return (EINVAL); 702 } 703 704 if (namelen != 1 || (name[namelen - 1] != CTL_CREATE 705 #if NKSYMS > 0 706 && name[namelen - 1] != CTL_CREATESYM 707 #endif /* NKSYMS > 0 */ 708 )) 709 return (EINVAL); 710 711 /* 712 * processes can only add nodes at securelevel 0, must be 713 * root, and can't add nodes to a parent that's not writeable 714 */ 715 if (l != NULL) { 716 #ifndef SYSCTL_DISALLOW_CREATE 717 if (securelevel > 0) 718 return (EPERM); 719 error = suser(l->l_proc->p_ucred, &l->l_proc->p_acflag); 720 if (error) 721 return (error); 722 if (!(rnode->sysctl_flags & CTLFLAG_READWRITE)) 723 #endif /* SYSCTL_DISALLOW_CREATE */ 724 return (EPERM); 725 } 726 727 /* 728 * nothing can add a node if: 729 * we've finished initial set up and 730 * the tree itself is not writeable or 731 * the entire sysctl system is not writeable 732 */ 733 if ((sysctl_root.sysctl_flags & CTLFLAG_PERMANENT) && 734 (!(sysctl_rootof(rnode)->sysctl_flags & CTLFLAG_READWRITE) || 735 !(sysctl_root.sysctl_flags & CTLFLAG_READWRITE))) 736 return (EPERM); 737 738 /* 739 * it must be a "node", not a "int" or something 740 */ 741 if (SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE) 742 return (ENOTDIR); 743 if (rnode->sysctl_flags & CTLFLAG_ALIAS) { 744 printf("sysctl_create: attempt to add node to aliased " 745 "node %p\n", rnode); 746 return (EINVAL); 747 } 748 pnode = rnode; 749 750 if (newp == NULL) 751 return (EINVAL); 752 error = sysctl_cvt_in(l, &v, newp, newlen, &nnode); 753 if (error) 754 return (error); 755 756 /* 757 * nodes passed in don't *have* parents 758 */ 759 if (nnode.sysctl_parent != NULL) 760 return (EINVAL); 761 762 /* 763 * if we are indeed adding it, it should be a "good" name and 764 * number 765 */ 766 nm = nnode.sysctl_num; 767 #if NKSYMS > 0 768 if (nm == CTL_CREATESYM) 769 nm = CTL_CREATE; 770 #endif /* NKSYMS > 0 */ 771 if (nm < 0 && nm != CTL_CREATE) 772 return (EINVAL); 773 sz = 0; 774 775 /* 776 * the name can't start with a digit 777 */ 778 if (nnode.sysctl_name[sz] >= '0' && 779 nnode.sysctl_name[sz] <= '9') 780 return (EINVAL); 781 782 /* 783 * the name must be only alphanumerics or - or _, longer than 784 * 0 bytes and less that SYSCTL_NAMELEN 785 */ 786 while (sz < SYSCTL_NAMELEN && nnode.sysctl_name[sz] != '\0') { 787 if ((nnode.sysctl_name[sz] >= '0' && 788 nnode.sysctl_name[sz] <= '9') || 789 (nnode.sysctl_name[sz] >= 'A' && 790 nnode.sysctl_name[sz] <= 'Z') || 791 (nnode.sysctl_name[sz] >= 'a' && 792 nnode.sysctl_name[sz] <= 'z') || 793 nnode.sysctl_name[sz] == '-' || 794 nnode.sysctl_name[sz] == '_') 795 sz++; 796 else 797 return (EINVAL); 798 } 799 if (sz == 0 || sz == SYSCTL_NAMELEN) 800 return (EINVAL); 801 802 /* 803 * various checks revolve around size vs type, etc 804 */ 805 type = SYSCTL_TYPE(nnode.sysctl_flags); 806 flags = SYSCTL_FLAGS(nnode.sysctl_flags); 807 rw = (flags & CTLFLAG_READWRITE) ? B_WRITE : B_READ; 808 sz = nnode.sysctl_size; 809 810 /* 811 * find out if there's a collision, and if so, let the caller 812 * know what they collided with 813 */ 814 node = pnode->sysctl_child; 815 if (((flags & CTLFLAG_ANYNUMBER) && node) || 816 (node && node->sysctl_flags & CTLFLAG_ANYNUMBER)) 817 return (EINVAL); 818 for (ni = at = 0; ni < pnode->sysctl_clen; ni++) { 819 if (nm == node[ni].sysctl_num || 820 strcmp(nnode.sysctl_name, node[ni].sysctl_name) == 0) { 821 /* 822 * ignore error here, since we 823 * are already fixed on EEXIST 824 */ 825 (void)sysctl_cvt_out(l, v, &node[ni], oldp, 826 *oldlenp, oldlenp); 827 return (EEXIST); 828 } 829 if (nm > node[ni].sysctl_num) 830 at++; 831 } 832 833 /* 834 * use sysctl_ver to add to the tree iff it hasn't changed 835 */ 836 if (nnode.sysctl_ver != 0) { 837 /* 838 * a specified value must match either the parent 839 * node's version or the root node's version 840 */ 841 if (nnode.sysctl_ver != sysctl_rootof(rnode)->sysctl_ver && 842 nnode.sysctl_ver != rnode->sysctl_ver) { 843 return (EINVAL); 844 } 845 } 846 847 /* 848 * only the kernel can assign functions to entries 849 */ 850 if (l != NULL && nnode.sysctl_func != NULL) 851 return (EPERM); 852 853 /* 854 * only the kernel can create permanent entries, and only then 855 * before the kernel is finished setting itself up 856 */ 857 if (l != NULL && (flags & ~SYSCTL_USERFLAGS)) 858 return (EPERM); 859 if ((flags & CTLFLAG_PERMANENT) & 860 (sysctl_root.sysctl_flags & CTLFLAG_PERMANENT)) 861 return (EPERM); 862 if ((flags & (CTLFLAG_OWNDATA | CTLFLAG_IMMEDIATE)) == 863 (CTLFLAG_OWNDATA | CTLFLAG_IMMEDIATE)) 864 return (EINVAL); 865 if ((flags & CTLFLAG_IMMEDIATE) && 866 type != CTLTYPE_INT && type != CTLTYPE_QUAD) 867 return (EINVAL); 868 869 /* 870 * check size, or set it if unset and we can figure it out. 871 * kernel created nodes are allowed to have a function instead 872 * of a size (or a data pointer). 873 */ 874 switch (type) { 875 case CTLTYPE_NODE: 876 /* 877 * only *i* can assert the size of a node 878 */ 879 if (flags & CTLFLAG_ALIAS) { 880 anum = nnode.sysctl_alias; 881 if (anum < 0) 882 return (EINVAL); 883 nnode.sysctl_alias = 0; 884 } 885 if (sz != 0 || nnode.sysctl_data != NULL) 886 return (EINVAL); 887 if (nnode.sysctl_csize != 0 || 888 nnode.sysctl_clen != 0 || 889 nnode.sysctl_child != 0) 890 return (EINVAL); 891 if (flags & CTLFLAG_OWNDATA) 892 return (EINVAL); 893 sz = sizeof(struct sysctlnode); 894 break; 895 case CTLTYPE_INT: 896 /* 897 * since an int is an int, if the size is not given or 898 * is wrong, we can "int-uit" it. 899 */ 900 if (sz != 0 && sz != sizeof(int)) 901 return (EINVAL); 902 sz = sizeof(int); 903 break; 904 case CTLTYPE_STRING: 905 /* 906 * strings are a little more tricky 907 */ 908 if (sz == 0) { 909 if (l == NULL) { 910 if (nnode.sysctl_func == NULL) { 911 if (nnode.sysctl_data == NULL) 912 return (EINVAL); 913 else 914 sz = strlen(nnode.sysctl_data) + 915 1; 916 } 917 } 918 else if (nnode.sysctl_data == NULL && 919 flags & CTLFLAG_OWNDATA) { 920 return (EINVAL); 921 } 922 else { 923 char v[PAGE_SIZE], *e; 924 size_t s; 925 926 /* 927 * we want a rough idea of what the 928 * size is now 929 */ 930 e = nnode.sysctl_data; 931 do { 932 error = copyinstr(e, &v[0], sizeof(v), 933 &s); 934 if (error) { 935 if (error != ENAMETOOLONG) 936 return (error); 937 e += PAGE_SIZE; 938 if ((e - 32 * PAGE_SIZE) > 939 (char*)nnode.sysctl_data) 940 return (ERANGE); 941 } 942 } while (error != 0); 943 sz = s + (e - (char*)nnode.sysctl_data); 944 } 945 } 946 break; 947 case CTLTYPE_QUAD: 948 if (sz != 0 && sz != sizeof(u_quad_t)) 949 return (EINVAL); 950 sz = sizeof(u_quad_t); 951 break; 952 case CTLTYPE_STRUCT: 953 if (sz == 0) { 954 if (l != NULL || nnode.sysctl_func == NULL) 955 return (EINVAL); 956 if (flags & CTLFLAG_OWNDATA) 957 return (EINVAL); 958 } 959 break; 960 default: 961 return (EINVAL); 962 } 963 964 /* 965 * at this point, if sz is zero, we *must* have a 966 * function to go with it and we can't own it. 967 */ 968 969 /* 970 * l ptr own 971 * 0 0 0 -> EINVAL (if no func) 972 * 0 0 1 -> own 973 * 0 1 0 -> kptr 974 * 0 1 1 -> kptr 975 * 1 0 0 -> EINVAL 976 * 1 0 1 -> own 977 * 1 1 0 -> kptr, no own (fault on lookup) 978 * 1 1 1 -> uptr, own 979 */ 980 if (type != CTLTYPE_NODE) { 981 if (sz != 0) { 982 if (flags & CTLFLAG_OWNDATA) { 983 own = malloc(sz, M_SYSCTLDATA, 984 M_WAITOK|M_CANFAIL); 985 if (nnode.sysctl_data == NULL) 986 memset(own, 0, sz); 987 else { 988 error = sysctl_copyin(l, 989 nnode.sysctl_data, own, sz); 990 if (error != 0) { 991 FREE(own, M_SYSCTLDATA); 992 return (error); 993 } 994 } 995 } 996 else if ((nnode.sysctl_data != NULL) && 997 !(flags & CTLFLAG_IMMEDIATE)) { 998 #if NKSYMS > 0 999 if (name[namelen - 1] == CTL_CREATESYM) { 1000 char symname[128]; /* XXX enough? */ 1001 u_long symaddr; 1002 size_t symlen; 1003 1004 error = sysctl_copyinstr(l, 1005 nnode.sysctl_data, symname, 1006 sizeof(symname), &symlen); 1007 if (error) 1008 return (error); 1009 error = ksyms_getval_from_kernel(NULL, 1010 symname, &symaddr, KSYMS_EXTERN); 1011 if (error) 1012 return (error); /* EINVAL? */ 1013 nnode.sysctl_data = (void*)symaddr; 1014 } 1015 #endif /* NKSYMS > 0 */ 1016 /* 1017 * Ideally, we'd like to verify here 1018 * that this address is acceptable, 1019 * but... 1020 * 1021 * - it might be valid now, only to 1022 * become invalid later 1023 * 1024 * - it might be invalid only for the 1025 * moment and valid later 1026 * 1027 * - or something else. 1028 * 1029 * Since we can't get a good answer, 1030 * we'll just accept the address as 1031 * given, and fault on individual 1032 * lookups. 1033 */ 1034 } 1035 } 1036 else if (nnode.sysctl_func == NULL) 1037 return (EINVAL); 1038 } 1039 1040 /* 1041 * a process can't assign a function to a node, and the kernel 1042 * can't create a node that has no function or data. 1043 * (XXX somewhat redundant check) 1044 */ 1045 if (l != NULL || nnode.sysctl_func == NULL) { 1046 if (type != CTLTYPE_NODE && 1047 nnode.sysctl_data == NULL && 1048 !(flags & CTLFLAG_IMMEDIATE) && 1049 own == NULL) 1050 return (EINVAL); 1051 } 1052 1053 #ifdef SYSCTL_DISALLOW_KWRITE 1054 /* 1055 * a process can't create a writable node unless it refers to 1056 * new data. 1057 */ 1058 if (l != NULL && own == NULL && type != CTLTYPE_NODE && 1059 (flags & CTLFLAG_READWRITE) != CTLFLAG_READONLY && 1060 !(flags & CTLFLAG_IMMEDIATE)) 1061 return (EPERM); 1062 #endif /* SYSCTL_DISALLOW_KWRITE */ 1063 1064 /* 1065 * make sure there's somewhere to put the new stuff. 1066 */ 1067 if (pnode->sysctl_child == NULL) { 1068 if (flags & CTLFLAG_ANYNUMBER) 1069 error = sysctl_alloc(pnode, 1); 1070 else 1071 error = sysctl_alloc(pnode, 0); 1072 if (error) 1073 return (error); 1074 } 1075 node = pnode->sysctl_child; 1076 1077 /* 1078 * no collisions, so pick a good dynamic number if we need to. 1079 */ 1080 if (nm == CTL_CREATE) { 1081 nm = ++sysctl_root.sysctl_num; 1082 for (ni = 0; ni < pnode->sysctl_clen; ni++) { 1083 if (nm == node[ni].sysctl_num) { 1084 nm++; 1085 ni = -1; 1086 } 1087 else if (nm > node[ni].sysctl_num) 1088 at = ni + 1; 1089 } 1090 } 1091 1092 /* 1093 * oops...ran out of space 1094 */ 1095 if (pnode->sysctl_clen == pnode->sysctl_csize) { 1096 error = sysctl_realloc(pnode); 1097 if (error) 1098 return (error); 1099 node = pnode->sysctl_child; 1100 } 1101 1102 /* 1103 * insert new node data 1104 */ 1105 if (at < pnode->sysctl_clen) { 1106 int t; 1107 1108 /* 1109 * move the nodes that should come after the new one 1110 */ 1111 memmove(&node[at + 1], &node[at], 1112 (pnode->sysctl_clen - at) * sizeof(struct sysctlnode)); 1113 memset(&node[at], 0, sizeof(struct sysctlnode)); 1114 node[at].sysctl_parent = pnode; 1115 /* 1116 * and...reparent any children of any moved nodes 1117 */ 1118 for (ni = at; ni <= pnode->sysctl_clen; ni++) 1119 if (SYSCTL_TYPE(node[ni].sysctl_flags) == CTLTYPE_NODE) 1120 for (t = 0; t < node[ni].sysctl_clen; t++) 1121 node[ni].sysctl_child[t].sysctl_parent = 1122 &node[ni]; 1123 } 1124 node = &node[at]; 1125 pnode->sysctl_clen++; 1126 1127 strlcpy(node->sysctl_name, nnode.sysctl_name, 1128 sizeof(node->sysctl_name)); 1129 node->sysctl_num = nm; 1130 node->sysctl_size = sz; 1131 node->sysctl_flags = SYSCTL_VERSION|type|flags; /* XXX other trees */ 1132 node->sysctl_csize = 0; 1133 node->sysctl_clen = 0; 1134 if (own) { 1135 node->sysctl_data = own; 1136 node->sysctl_flags |= CTLFLAG_OWNDATA; 1137 } 1138 else if (flags & CTLFLAG_ALIAS) { 1139 node->sysctl_alias = anum; 1140 } 1141 else if (flags & CTLFLAG_IMMEDIATE) { 1142 switch (type) { 1143 case CTLTYPE_INT: 1144 node->sysctl_idata = nnode.sysctl_idata; 1145 break; 1146 case CTLTYPE_QUAD: 1147 node->sysctl_qdata = nnode.sysctl_qdata; 1148 break; 1149 } 1150 } 1151 else { 1152 node->sysctl_data = nnode.sysctl_data; 1153 node->sysctl_flags &= ~CTLFLAG_OWNDATA; 1154 } 1155 node->sysctl_func = nnode.sysctl_func; 1156 node->sysctl_child = NULL; 1157 /* node->sysctl_parent should already be done */ 1158 1159 /* 1160 * update "version" on path to "root" 1161 */ 1162 for (; rnode->sysctl_parent != NULL; rnode = rnode->sysctl_parent) 1163 ; 1164 pnode = node; 1165 for (nm = rnode->sysctl_ver + 1; pnode != NULL; 1166 pnode = pnode->sysctl_parent) 1167 pnode->sysctl_ver = nm; 1168 1169 error = sysctl_cvt_out(l, v, node, oldp, *oldlenp, oldlenp); 1170 1171 return (error); 1172 } 1173 1174 /* 1175 * ******************************************************************** 1176 * A wrapper around sysctl_create() that prints the thing we're trying 1177 * to add. 1178 * ******************************************************************** 1179 */ 1180 #ifdef SYSCTL_DEBUG_CREATE 1181 int _sysctl_create(SYSCTLFN_RWPROTO); 1182 int 1183 _sysctl_create(SYSCTLFN_RWARGS) 1184 { 1185 const struct sysctlnode *node; 1186 int k, rc, ni, nl = namelen + (name - oname); 1187 1188 node = newp; 1189 1190 printf("namelen %d (", nl); 1191 for (ni = 0; ni < nl - 1; ni++) 1192 printf(" %d", oname[ni]); 1193 printf(" %d )\t[%s]\tflags %08x (%08x %d %zu)\n", 1194 k = node->sysctl_num, 1195 node->sysctl_name, 1196 node->sysctl_flags, 1197 SYSCTL_FLAGS(node->sysctl_flags), 1198 SYSCTL_TYPE(node->sysctl_flags), 1199 node->sysctl_size); 1200 1201 node = rnode; 1202 rc = sysctl_create(SYSCTLFN_CALL(rnode)); 1203 1204 printf("sysctl_create("); 1205 for (ni = 0; ni < nl - 1; ni++) 1206 printf(" %d", oname[ni]); 1207 printf(" %d ) returned %d\n", k, rc); 1208 1209 return (rc); 1210 } 1211 #define sysctl_create _sysctl_create 1212 #endif /* SYSCTL_DEBUG_CREATE */ 1213 1214 /* 1215 * sysctl_destroy -- Removes a node (as described by newp) from the 1216 * given tree, returning (if successful) a copy of the dead node in 1217 * oldp. Since we're removing stuff, there's not much to check. 1218 */ 1219 int 1220 sysctl_destroy(SYSCTLFN_RWARGS) 1221 { 1222 struct sysctlnode *node, *pnode, onode, nnode; 1223 int ni, error, v; 1224 1225 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 1226 printf("sysctl_destroy: rnode %p wrong version\n", rnode); 1227 return (EINVAL); 1228 } 1229 1230 error = 0; 1231 1232 if (namelen != 1 || name[namelen - 1] != CTL_DESTROY) 1233 return (EINVAL); 1234 1235 /* 1236 * processes can only destroy nodes at securelevel 0, must be 1237 * root, and can't remove nodes from a parent that's not 1238 * writeable 1239 */ 1240 if (l != NULL) { 1241 #ifndef SYSCTL_DISALLOW_CREATE 1242 if (securelevel > 0) 1243 return (EPERM); 1244 error = suser(l->l_proc->p_ucred, &l->l_proc->p_acflag); 1245 if (error) 1246 return (error); 1247 if (!(rnode->sysctl_flags & CTLFLAG_READWRITE)) 1248 #endif /* SYSCTL_DISALLOW_CREATE */ 1249 return (EPERM); 1250 } 1251 1252 /* 1253 * nothing can remove a node if: 1254 * the node is permanent (checked later) or 1255 * the tree itself is not writeable or 1256 * the entire sysctl system is not writeable 1257 * 1258 * note that we ignore whether setup is complete or not, 1259 * because these rules always apply. 1260 */ 1261 if (!(sysctl_rootof(rnode)->sysctl_flags & CTLFLAG_READWRITE) || 1262 !(sysctl_root.sysctl_flags & CTLFLAG_READWRITE)) 1263 return (EPERM); 1264 1265 if (newp == NULL) 1266 return (EINVAL); 1267 error = sysctl_cvt_in(l, &v, newp, newlen, &nnode); 1268 if (error) 1269 return (error); 1270 memset(&onode, 0, sizeof(struct sysctlnode)); 1271 1272 node = rnode->sysctl_child; 1273 for (ni = 0; ni < rnode->sysctl_clen; ni++) { 1274 if (nnode.sysctl_num == node[ni].sysctl_num) { 1275 /* 1276 * if name specified, must match 1277 */ 1278 if (nnode.sysctl_name[0] != '\0' && 1279 strcmp(nnode.sysctl_name, node[ni].sysctl_name)) 1280 continue; 1281 /* 1282 * if version specified, must match 1283 */ 1284 if (nnode.sysctl_ver != 0 && 1285 nnode.sysctl_ver != node[ni].sysctl_ver) 1286 continue; 1287 /* 1288 * this must be the one 1289 */ 1290 break; 1291 } 1292 } 1293 if (ni == rnode->sysctl_clen) 1294 return (ENOENT); 1295 node = &node[ni]; 1296 pnode = node->sysctl_parent; 1297 1298 /* 1299 * if the kernel says permanent, it is, so there. nyah. 1300 */ 1301 if (SYSCTL_FLAGS(node->sysctl_flags) & CTLFLAG_PERMANENT) 1302 return (EPERM); 1303 1304 /* 1305 * can't delete non-empty nodes 1306 */ 1307 if (SYSCTL_TYPE(node->sysctl_flags) == CTLTYPE_NODE && 1308 node->sysctl_clen != 0) 1309 return (ENOTEMPTY); 1310 1311 /* 1312 * if the node "owns" data, release it now 1313 */ 1314 if (node->sysctl_flags & CTLFLAG_OWNDATA) { 1315 if (node->sysctl_data != NULL) 1316 FREE(node->sysctl_data, M_SYSCTLDATA); 1317 node->sysctl_data = NULL; 1318 } 1319 if (node->sysctl_flags & CTLFLAG_OWNDESC) { 1320 if (node->sysctl_desc != NULL) 1321 FREE(node->sysctl_desc, M_SYSCTLDATA); 1322 node->sysctl_desc = NULL; 1323 } 1324 1325 /* 1326 * if the node to be removed is not the last one on the list, 1327 * move the remaining nodes up, and reparent any grandchildren 1328 */ 1329 onode = *node; 1330 if (ni < pnode->sysctl_clen - 1) { 1331 int t; 1332 1333 memmove(&pnode->sysctl_child[ni], &pnode->sysctl_child[ni + 1], 1334 (pnode->sysctl_clen - ni - 1) * 1335 sizeof(struct sysctlnode)); 1336 for (; ni < pnode->sysctl_clen - 1; ni++) 1337 if (SYSCTL_TYPE(pnode->sysctl_child[ni].sysctl_flags) == 1338 CTLTYPE_NODE) 1339 for (t = 0; 1340 t < pnode->sysctl_child[ni].sysctl_clen; 1341 t++) 1342 pnode->sysctl_child[ni].sysctl_child[t]. 1343 sysctl_parent = 1344 &pnode->sysctl_child[ni]; 1345 ni = pnode->sysctl_clen - 1; 1346 node = &pnode->sysctl_child[ni]; 1347 } 1348 1349 /* 1350 * reset the space we just vacated 1351 */ 1352 memset(node, 0, sizeof(struct sysctlnode)); 1353 node->sysctl_parent = pnode; 1354 pnode->sysctl_clen--; 1355 1356 /* 1357 * if this parent just lost its last child, nuke the creche 1358 */ 1359 if (pnode->sysctl_clen == 0) { 1360 FREE(pnode->sysctl_child, M_SYSCTLNODE); 1361 pnode->sysctl_csize = 0; 1362 pnode->sysctl_child = NULL; 1363 } 1364 1365 /* 1366 * update "version" on path to "root" 1367 */ 1368 for (; rnode->sysctl_parent != NULL; rnode = rnode->sysctl_parent) 1369 ; 1370 for (ni = rnode->sysctl_ver + 1; pnode != NULL; 1371 pnode = pnode->sysctl_parent) 1372 pnode->sysctl_ver = ni; 1373 1374 error = sysctl_cvt_out(l, v, &onode, oldp, *oldlenp, oldlenp); 1375 1376 return (error); 1377 } 1378 1379 /* 1380 * sysctl_lookup -- Handles copyin/copyout of new and old values. 1381 * Partial reads are globally allowed. Only root can write to things 1382 * unless the node says otherwise. 1383 */ 1384 int 1385 sysctl_lookup(SYSCTLFN_RWARGS) 1386 { 1387 int error, rw; 1388 size_t sz, len; 1389 void *d; 1390 1391 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 1392 printf("sysctl_lookup: rnode %p wrong version\n", rnode); 1393 return (EINVAL); 1394 } 1395 1396 error = 0; 1397 1398 /* 1399 * you can't "look up" a node. you can "query" it, but you 1400 * can't "look it up". 1401 */ 1402 if (SYSCTL_TYPE(rnode->sysctl_flags) == CTLTYPE_NODE || namelen != 0) 1403 return (EINVAL); 1404 1405 /* 1406 * some nodes are private, so only root can look into them. 1407 */ 1408 if (l != NULL && (rnode->sysctl_flags & CTLFLAG_PRIVATE) && 1409 (error = suser(l->l_proc->p_ucred, &l->l_proc->p_acflag)) != 0) 1410 return (error); 1411 1412 /* 1413 * if a node wants to be writable according to different rules 1414 * other than "only root can write to stuff unless a flag is 1415 * set", then it needs its own function which should have been 1416 * called and not us. 1417 */ 1418 if (l != NULL && newp != NULL && 1419 !(rnode->sysctl_flags & CTLFLAG_ANYWRITE) && 1420 (error = suser(l->l_proc->p_ucred, &l->l_proc->p_acflag)) != 0) 1421 return (error); 1422 1423 /* 1424 * is this node supposedly writable? 1425 */ 1426 rw = 0; 1427 switch (rnode->sysctl_flags & CTLFLAG_READWRITE) { 1428 case CTLFLAG_READONLY1: 1429 rw = (securelevel < 1) ? 1 : 0; 1430 break; 1431 case CTLFLAG_READONLY2: 1432 rw = (securelevel < 2) ? 1 : 0; 1433 break; 1434 case CTLFLAG_READWRITE: 1435 rw = 1; 1436 break; 1437 } 1438 1439 /* 1440 * it appears not to be writable at this time, so if someone 1441 * tried to write to it, we must tell them to go away 1442 */ 1443 if (!rw && newp != NULL) 1444 return (EPERM); 1445 1446 /* 1447 * step one, copy out the stuff we have presently 1448 */ 1449 if (rnode->sysctl_flags & CTLFLAG_IMMEDIATE) { 1450 switch (SYSCTL_TYPE(rnode->sysctl_flags)) { 1451 case CTLTYPE_INT: 1452 d = &rnode->sysctl_idata; 1453 break; 1454 case CTLTYPE_QUAD: 1455 d = &rnode->sysctl_qdata; 1456 break; 1457 default: 1458 return (EINVAL); 1459 } 1460 } 1461 else 1462 d = rnode->sysctl_data; 1463 if (SYSCTL_TYPE(rnode->sysctl_flags) == CTLTYPE_STRING) 1464 sz = strlen(d) + 1; /* XXX@@@ possible fault here */ 1465 else 1466 sz = rnode->sysctl_size; 1467 if (oldp != NULL) 1468 error = sysctl_copyout(l, d, oldp, MIN(sz, *oldlenp)); 1469 if (error) 1470 return (error); 1471 *oldlenp = sz; 1472 1473 /* 1474 * are we done? 1475 */ 1476 if (newp == NULL || newlen == 0) 1477 return (0); 1478 1479 /* 1480 * hmm...not done. must now "copy in" new value. re-adjust 1481 * sz to maximum value (strings are "weird"). 1482 */ 1483 sz = rnode->sysctl_size; 1484 switch (SYSCTL_TYPE(rnode->sysctl_flags)) { 1485 case CTLTYPE_INT: 1486 case CTLTYPE_QUAD: 1487 case CTLTYPE_STRUCT: 1488 /* 1489 * these data must be *exactly* the same size coming 1490 * in. 1491 */ 1492 if (newlen != sz) 1493 return (EINVAL); 1494 error = sysctl_copyin(l, newp, d, sz); 1495 break; 1496 case CTLTYPE_STRING: { 1497 /* 1498 * strings, on the other hand, can be shorter, and we 1499 * let userland be sloppy about the trailing nul. 1500 */ 1501 char *newbuf; 1502 1503 /* 1504 * too much new string? 1505 */ 1506 if (newlen > sz) 1507 return (EINVAL); 1508 1509 /* 1510 * temporary copy of new inbound string 1511 */ 1512 len = MIN(sz, newlen); 1513 newbuf = malloc(len, M_SYSCTLDATA, M_WAITOK|M_CANFAIL); 1514 if (newbuf == NULL) 1515 return (ENOMEM); 1516 error = sysctl_copyin(l, newp, newbuf, len); 1517 if (error) { 1518 FREE(newbuf, M_SYSCTLDATA); 1519 return (error); 1520 } 1521 1522 /* 1523 * did they null terminate it, or do we have space 1524 * left to do it ourselves? 1525 */ 1526 if (newbuf[len - 1] != '\0' && len == sz) { 1527 FREE(newbuf, M_SYSCTLDATA); 1528 return (EINVAL); 1529 } 1530 1531 /* 1532 * looks good, so pop it into place and zero the rest. 1533 */ 1534 if (len > 0) 1535 memcpy(rnode->sysctl_data, newbuf, len); 1536 if (sz != len) 1537 memset((char*)rnode->sysctl_data + len, 0, sz - len); 1538 FREE(newbuf, M_SYSCTLDATA); 1539 break; 1540 } 1541 default: 1542 return (EINVAL); 1543 } 1544 1545 return (error); 1546 } 1547 1548 /* 1549 * sysctl_mmap -- Dispatches sysctl mmap requests to those nodes that 1550 * purport to handle it. This interface isn't fully fleshed out yet, 1551 * unfortunately. 1552 */ 1553 static int 1554 sysctl_mmap(SYSCTLFN_RWARGS) 1555 { 1556 struct sysctlnode nnode, *node; 1557 int error; 1558 1559 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 1560 printf("sysctl_mmap: rnode %p wrong version\n", rnode); 1561 return (EINVAL); 1562 } 1563 1564 /* 1565 * let's just pretend that didn't happen, m'kay? 1566 */ 1567 if (l == NULL) 1568 return (EPERM); 1569 1570 /* 1571 * is this a sysctlnode description of an mmap request? 1572 */ 1573 if (newp == NULL || newlen != sizeof(struct sysctlnode)) 1574 return (EINVAL); 1575 error = sysctl_copyin(l, newp, &nnode, sizeof(nnode)); 1576 if (error) 1577 return (error); 1578 1579 /* 1580 * does the node they asked for exist? 1581 */ 1582 if (namelen != 1) 1583 return (EOPNOTSUPP); 1584 node = rnode; 1585 error = sysctl_locate(l, &nnode.sysctl_num, 1, &node, NULL); 1586 if (error) 1587 return (error); 1588 1589 /* 1590 * does this node that we have found purport to handle mmap? 1591 */ 1592 if (node->sysctl_func == NULL || 1593 !(node->sysctl_flags & CTLFLAG_MMAP)) 1594 return (EOPNOTSUPP); 1595 1596 /* 1597 * well...okay, they asked for it. 1598 */ 1599 return ((*node->sysctl_func)(SYSCTLFN_CALL(node))); 1600 } 1601 1602 int 1603 sysctl_describe(SYSCTLFN_ARGS) 1604 { 1605 struct sysctldesc *d; 1606 char buf[1024]; 1607 size_t sz, left, tot; 1608 int i, error, v = -1; 1609 struct sysctlnode *node; 1610 struct sysctlnode dnode; 1611 1612 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 1613 printf("sysctl_query: rnode %p wrong version\n", rnode); 1614 return (EINVAL); 1615 } 1616 1617 if (SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE) 1618 return (ENOTDIR); 1619 if (namelen != 1 || name[0] != CTL_DESCRIBE) 1620 return (EINVAL); 1621 1622 /* 1623 * get ready... 1624 */ 1625 error = 0; 1626 d = (void*)&buf[0]; 1627 tot = 0; 1628 node = rnode->sysctl_child; 1629 left = *oldlenp; 1630 1631 /* 1632 * no request -> all descriptions at this level 1633 * request with desc unset -> just this node 1634 * request with desc set -> set descr for this node 1635 */ 1636 if (newp != NULL) { 1637 error = sysctl_cvt_in(l, &v, newp, newlen, &dnode); 1638 if (error) 1639 return (error); 1640 if (dnode.sysctl_desc != NULL) { 1641 /* 1642 * processes cannot set descriptions above 1643 * securelevel 0. and must be root. blah 1644 * blah blah. a couple more checks are made 1645 * once we find the node we want. 1646 */ 1647 if (l != NULL) { 1648 #ifndef SYSCTL_DISALLOW_CREATE 1649 if (securelevel > 0) 1650 return (EPERM); 1651 error = suser(l->l_proc->p_ucred, 1652 &l->l_proc->p_acflag); 1653 if (error) 1654 return (error); 1655 #else /* SYSCTL_DISALLOW_CREATE */ 1656 return (EPERM); 1657 #endif /* SYSCTL_DISALLOW_CREATE */ 1658 } 1659 1660 /* 1661 * find node and try to set the description on it 1662 */ 1663 for (i = 0; i < rnode->sysctl_clen; i++) 1664 if (node[i].sysctl_num == dnode.sysctl_num) 1665 break; 1666 if (i == rnode->sysctl_clen) 1667 return (ENOENT); 1668 node = &node[i]; 1669 1670 /* 1671 * did the caller specify a node version? 1672 */ 1673 if (dnode.sysctl_ver != 0 && 1674 dnode.sysctl_ver != node->sysctl_ver) 1675 return (EINVAL); 1676 1677 /* 1678 * okay...some rules: 1679 * (1) if setup is done and the tree is 1680 * read-only or the whole system is 1681 * read-only 1682 * (2) no one can set a description on a 1683 * permanent node (it must be set when 1684 * using createv) 1685 * (3) processes cannot *change* a description 1686 * (4) processes *can*, however, set a 1687 * description on a read-only node so that 1688 * one can be created and then described 1689 * in two steps 1690 * anything else come to mind? 1691 */ 1692 if ((sysctl_root.sysctl_flags & CTLFLAG_PERMANENT) && 1693 (!(sysctl_rootof(node)->sysctl_flags & 1694 CTLFLAG_READWRITE) || 1695 !(sysctl_root.sysctl_flags & CTLFLAG_READWRITE))) 1696 return (EPERM); 1697 if (node->sysctl_flags & CTLFLAG_PERMANENT) 1698 return (EPERM); 1699 if (l != NULL && node->sysctl_desc != NULL) 1700 return (EPERM); 1701 1702 /* 1703 * right, let's go ahead. the first step is 1704 * making the description into something the 1705 * node can "own", if need be. 1706 */ 1707 if (l != NULL || 1708 dnode.sysctl_flags & CTLFLAG_OWNDESC) { 1709 char *nd, k[1024]; 1710 1711 error = sysctl_copyinstr(l, dnode.sysctl_desc, 1712 &k[0], sizeof(k), &sz); 1713 if (error) 1714 return (error); 1715 nd = malloc(sz, M_SYSCTLDATA, 1716 M_WAITOK|M_CANFAIL); 1717 if (nd == NULL) 1718 return (ENOMEM); 1719 memcpy(nd, k, sz); 1720 dnode.sysctl_flags |= CTLFLAG_OWNDESC; 1721 dnode.sysctl_desc = nd; 1722 } 1723 1724 /* 1725 * now "release" the old description and 1726 * attach the new one. ta-da. 1727 */ 1728 if ((node->sysctl_flags & CTLFLAG_OWNDESC) && 1729 node->sysctl_desc != NULL) 1730 free((void*)node->sysctl_desc, M_SYSCTLDATA); 1731 node->sysctl_desc = dnode.sysctl_desc; 1732 node->sysctl_flags |= 1733 (dnode.sysctl_flags & CTLFLAG_OWNDESC); 1734 1735 /* 1736 * now we "fall out" and into the loop which 1737 * will copy the new description back out for 1738 * those interested parties 1739 */ 1740 } 1741 } 1742 1743 /* 1744 * scan for one description or just retrieve all descriptions 1745 */ 1746 for (i = 0; i < rnode->sysctl_clen; i++) { 1747 /* 1748 * did they ask for the description of only one node? 1749 */ 1750 if (v != -1 && node[i].sysctl_num != dnode.sysctl_num) 1751 continue; 1752 1753 /* 1754 * don't describe "private" nodes to non-suser users 1755 */ 1756 if ((node[i].sysctl_flags & CTLFLAG_PRIVATE) && (l != NULL) && 1757 !(suser(l->l_proc->p_ucred, &l->l_proc->p_acflag))) 1758 continue; 1759 1760 /* 1761 * is this description "valid"? 1762 */ 1763 memset(&buf[0], 0, sizeof(buf)); 1764 if (node[i].sysctl_desc == NULL) 1765 sz = 1; 1766 else if (copystr(node[i].sysctl_desc, &d->descr_str[0], 1767 sizeof(buf) - sizeof(*d), &sz) != 0) { 1768 /* 1769 * erase possible partial description 1770 */ 1771 memset(&buf[0], 0, sizeof(buf)); 1772 sz = 1; 1773 } 1774 1775 /* 1776 * we've got it, stuff it into the caller's buffer 1777 */ 1778 d->descr_num = node[i].sysctl_num; 1779 d->descr_ver = node[i].sysctl_ver; 1780 d->descr_len = sz; /* includes trailing nul */ 1781 sz = (caddr_t)NEXT_DESCR(d) - (caddr_t)d; 1782 if (oldp != NULL && left >= sz) { 1783 error = sysctl_copyout(l, d, oldp, sz); 1784 if (error) 1785 return (error); 1786 left -= sz; 1787 oldp = (void*)__sysc_desc_adv(oldp, d->descr_len); 1788 } 1789 tot += sz; 1790 1791 /* 1792 * if we get this far with v not "unset", they asked 1793 * for a specific node and we found it 1794 */ 1795 if (v != -1) 1796 break; 1797 } 1798 1799 /* 1800 * did we find it after all? 1801 */ 1802 if (v != -1 && tot == 0) 1803 error = ENOENT; 1804 else 1805 *oldlenp = tot; 1806 1807 return (error); 1808 } 1809 1810 /* 1811 * ******************************************************************** 1812 * Section 3: Create and destroy from inside the kernel 1813 * ******************************************************************** 1814 * sysctl_createv() and sysctl_destroyv() are simpler-to-use 1815 * interfaces for the kernel to fling new entries into the mib and rip 1816 * them out later. In the case of sysctl_createv(), the returned copy 1817 * of the node (see sysctl_create()) will be translated back into a 1818 * pointer to the actual node. 1819 * 1820 * Note that sysctl_createv() will return 0 if the create request 1821 * matches an existing node (ala mkdir -p), and that sysctl_destroyv() 1822 * will return 0 if the node to be destroyed already does not exist 1823 * (aka rm -f) or if it is a parent of other nodes. 1824 * 1825 * This allows two (or more) different subsystems to assert sub-tree 1826 * existence before populating their own nodes, and to remove their 1827 * own nodes without orphaning the others when they are done. 1828 * ******************************************************************** 1829 */ 1830 int 1831 sysctl_createv(struct sysctllog **log, int cflags, 1832 struct sysctlnode **rnode, struct sysctlnode **cnode, 1833 int flags, int type, const char *namep, const char *descr, 1834 sysctlfn func, u_quad_t qv, void *newp, size_t newlen, 1835 ...) 1836 { 1837 va_list ap; 1838 int error, ni, namelen, name[CTL_MAXNAME]; 1839 struct sysctlnode *pnode, nnode, onode, *root; 1840 size_t sz; 1841 1842 /* 1843 * where are we putting this? 1844 */ 1845 if (rnode != NULL && *rnode == NULL) { 1846 printf("sysctl_createv: rnode NULL\n"); 1847 return (EINVAL); 1848 } 1849 root = rnode ? *rnode : NULL; 1850 if (cnode != NULL) 1851 *cnode = NULL; 1852 if (cflags != 0) 1853 return (EINVAL); 1854 1855 /* 1856 * what is it? 1857 */ 1858 flags = SYSCTL_VERSION|SYSCTL_TYPE(type)|SYSCTL_FLAGS(flags); 1859 if (log != NULL) 1860 flags &= ~CTLFLAG_PERMANENT; 1861 1862 /* 1863 * where do we put it? 1864 */ 1865 va_start(ap, newlen); 1866 namelen = 0; 1867 ni = -1; 1868 do { 1869 if (++ni == CTL_MAXNAME) 1870 return (ENAMETOOLONG); 1871 name[ni] = va_arg(ap, int); 1872 /* 1873 * sorry, this is not supported from here 1874 */ 1875 if (name[ni] == CTL_CREATESYM) 1876 return (EINVAL); 1877 } while (name[ni] != CTL_EOL && name[ni] != CTL_CREATE); 1878 namelen = ni + (name[ni] == CTL_CREATE ? 1 : 0); 1879 va_end(ap); 1880 1881 /* 1882 * what's it called 1883 */ 1884 if (strlcpy(nnode.sysctl_name, namep, sizeof(nnode.sysctl_name)) > 1885 sizeof(nnode.sysctl_name)) 1886 return (ENAMETOOLONG); 1887 1888 /* 1889 * cons up the description of the new node 1890 */ 1891 nnode.sysctl_num = name[namelen - 1]; 1892 name[namelen - 1] = CTL_CREATE; 1893 nnode.sysctl_size = newlen; 1894 nnode.sysctl_flags = flags; 1895 if (type == CTLTYPE_NODE) { 1896 nnode.sysctl_csize = 0; 1897 nnode.sysctl_clen = 0; 1898 nnode.sysctl_child = NULL; 1899 if (flags & CTLFLAG_ALIAS) 1900 nnode.sysctl_alias = qv; 1901 } 1902 else if (flags & CTLFLAG_IMMEDIATE) { 1903 switch (type) { 1904 case CTLTYPE_INT: 1905 nnode.sysctl_idata = qv; 1906 break; 1907 case CTLTYPE_QUAD: 1908 nnode.sysctl_qdata = qv; 1909 break; 1910 default: 1911 return (EINVAL); 1912 } 1913 } 1914 else { 1915 nnode.sysctl_data = newp; 1916 } 1917 nnode.sysctl_func = func; 1918 nnode.sysctl_parent = NULL; 1919 nnode.sysctl_ver = 0; 1920 1921 /* 1922 * initialize lock state -- we need locks if the main tree has 1923 * been marked as complete, but since we could be called from 1924 * either there, or from a device driver (say, at device 1925 * insertion), or from an lkm (at lkm load time, say), we 1926 * don't really want to "wait"... 1927 */ 1928 error = sysctl_lock(NULL, NULL, 0); 1929 if (error) 1930 return (error); 1931 1932 /* 1933 * locate the prospective parent of the new node, and if we 1934 * find it, add the new node. 1935 */ 1936 sz = sizeof(onode); 1937 pnode = root; 1938 error = sysctl_locate(NULL, &name[0], namelen - 1, &pnode, &ni); 1939 if (error) { 1940 printf("sysctl_createv: sysctl_locate(%s) returned %d\n", 1941 nnode.sysctl_name, error); 1942 sysctl_unlock(NULL); 1943 return (error); 1944 } 1945 error = sysctl_create(&name[ni], namelen - ni, &onode, &sz, 1946 &nnode, sizeof(nnode), &name[0], NULL, 1947 pnode); 1948 1949 /* 1950 * unfortunately the node we wanted to create is already 1951 * there. if the node that's already there is a reasonable 1952 * facsimile of the node we wanted to create, just pretend 1953 * (for the caller's benefit) that we managed to create the 1954 * node they wanted. 1955 */ 1956 if (error == EEXIST) { 1957 /* name is the same as requested... */ 1958 if (strcmp(nnode.sysctl_name, onode.sysctl_name) == 0 && 1959 /* they want the same function... */ 1960 nnode.sysctl_func == onode.sysctl_func && 1961 /* number is the same as requested, or... */ 1962 (nnode.sysctl_num == onode.sysctl_num || 1963 /* they didn't pick a number... */ 1964 nnode.sysctl_num == CTL_CREATE)) { 1965 /* 1966 * collision here from trying to create 1967 * something that already existed; let's give 1968 * our customers a hand and tell them they got 1969 * what they wanted. 1970 */ 1971 #ifdef SYSCTL_DEBUG_CREATE 1972 printf("cleared\n"); 1973 #endif /* SYSCTL_DEBUG_CREATE */ 1974 error = 0; 1975 } 1976 } 1977 1978 if (error == 0 && 1979 (cnode != NULL || log != NULL || descr != NULL)) { 1980 /* 1981 * sysctl_create() gave us back a copy of the node, 1982 * but we need to know where it actually is... 1983 */ 1984 pnode = root; 1985 error = sysctl_locate(NULL, &name[0], namelen - 1, &pnode, &ni); 1986 1987 /* 1988 * manual scan of last layer so that aliased nodes 1989 * aren't followed. 1990 */ 1991 if (error == 0) { 1992 for (ni = 0; ni < pnode->sysctl_clen; ni++) 1993 if (pnode->sysctl_child[ni].sysctl_num == 1994 onode.sysctl_num) 1995 break; 1996 if (ni < pnode->sysctl_clen) 1997 pnode = &pnode->sysctl_child[ni]; 1998 else 1999 error = ENOENT; 2000 } 2001 2002 /* 2003 * not expecting an error here, but... 2004 */ 2005 if (error == 0) { 2006 if (log != NULL) 2007 sysctl_log_add(log, pnode); 2008 if (cnode != NULL) 2009 *cnode = pnode; 2010 if (descr != NULL) { 2011 /* 2012 * allow first caller to *set* a 2013 * description actually to set it 2014 */ 2015 if (pnode->sysctl_desc != NULL) 2016 /* skip it...we've got one */; 2017 else if (flags & CTLFLAG_OWNDESC) { 2018 size_t l = strlen(descr) + 1; 2019 char *d = malloc(l, M_SYSCTLDATA, 2020 M_WAITOK|M_CANFAIL); 2021 if (d != NULL) { 2022 memcpy(d, descr, l); 2023 pnode->sysctl_desc = d; 2024 pnode->sysctl_flags |= 2025 CTLFLAG_OWNDESC; 2026 } 2027 } 2028 else 2029 pnode->sysctl_desc = descr; 2030 } 2031 } 2032 else { 2033 printf("sysctl_create succeeded but node not found?!\n"); 2034 /* 2035 * confusing, but the create said it 2036 * succeeded, so... 2037 */ 2038 error = 0; 2039 } 2040 } 2041 2042 /* 2043 * now it should be safe to release the lock state. note that 2044 * the pointer to the newly created node being passed back may 2045 * not be "good" for very long. 2046 */ 2047 sysctl_unlock(NULL); 2048 2049 if (error != 0) { 2050 printf("sysctl_createv: sysctl_create(%s) returned %d\n", 2051 nnode.sysctl_name, error); 2052 #if 0 2053 if (error != ENOENT) 2054 sysctl_dump(&onode); 2055 #endif 2056 } 2057 2058 return (error); 2059 } 2060 2061 int 2062 sysctl_destroyv(struct sysctlnode *rnode, ...) 2063 { 2064 va_list ap; 2065 int error, name[CTL_MAXNAME], namelen, ni; 2066 struct sysctlnode *pnode, *node, dnode; 2067 size_t sz; 2068 2069 va_start(ap, rnode); 2070 namelen = 0; 2071 ni = 0; 2072 do { 2073 if (ni == CTL_MAXNAME) 2074 return (ENAMETOOLONG); 2075 name[ni] = va_arg(ap, int); 2076 } while (name[ni++] != CTL_EOL); 2077 namelen = ni - 1; 2078 va_end(ap); 2079 2080 /* 2081 * i can't imagine why we'd be destroying a node when the tree 2082 * wasn't complete, but who knows? 2083 */ 2084 error = sysctl_lock(NULL, NULL, 0); 2085 if (error) 2086 return (error); 2087 2088 /* 2089 * where is it? 2090 */ 2091 node = rnode; 2092 error = sysctl_locate(NULL, &name[0], namelen - 1, &node, &ni); 2093 if (error) { 2094 /* they want it gone and it's not there, so... */ 2095 sysctl_unlock(NULL); 2096 return (error == ENOENT ? 0 : error); 2097 } 2098 2099 /* 2100 * set up the deletion 2101 */ 2102 pnode = node; 2103 node = &dnode; 2104 memset(&dnode, 0, sizeof(dnode)); 2105 dnode.sysctl_flags = SYSCTL_VERSION; 2106 dnode.sysctl_num = name[namelen - 1]; 2107 2108 /* 2109 * we found it, now let's nuke it 2110 */ 2111 name[namelen - 1] = CTL_DESTROY; 2112 sz = 0; 2113 error = sysctl_destroy(&name[namelen - 1], 1, NULL, &sz, 2114 node, sizeof(*node), &name[0], NULL, 2115 pnode); 2116 if (error == ENOTEMPTY) { 2117 /* 2118 * think of trying to delete "foo" when "foo.bar" 2119 * (which someone else put there) is still in 2120 * existence 2121 */ 2122 error = 0; 2123 2124 /* 2125 * dunno who put the description there, but if this 2126 * node can ever be removed, we need to make sure the 2127 * string doesn't go out of context. that means we 2128 * need to find the node that's still there (don't use 2129 * sysctl_locate() because that follows aliasing). 2130 */ 2131 node = pnode->sysctl_child; 2132 for (ni = 0; ni < pnode->sysctl_clen; ni++) 2133 if (node[ni].sysctl_num == dnode.sysctl_num) 2134 break; 2135 node = (ni < pnode->sysctl_clen) ? &node[ni] : NULL; 2136 2137 /* 2138 * if we found it, and this node has a description, 2139 * and this node can be released, and it doesn't 2140 * already own its own description...sigh. :) 2141 */ 2142 if (node != NULL && node->sysctl_desc != NULL && 2143 !(node->sysctl_flags & CTLFLAG_PERMANENT) && 2144 !(node->sysctl_flags & CTLFLAG_OWNDESC)) { 2145 char *d; 2146 2147 sz = strlen(node->sysctl_desc) + 1; 2148 d = malloc(sz, M_SYSCTLDATA, M_WAITOK|M_CANFAIL); 2149 if (d != NULL) { 2150 memcpy(d, node->sysctl_desc, sz); 2151 node->sysctl_desc = d; 2152 node->sysctl_flags |= CTLFLAG_OWNDESC; 2153 } 2154 else { 2155 /* 2156 * XXX drop the description? be 2157 * afraid? don't care? 2158 */ 2159 } 2160 } 2161 } 2162 2163 sysctl_unlock(NULL); 2164 2165 return (error); 2166 } 2167 2168 #if 0 2169 /* 2170 * ******************************************************************** 2171 * the dump routine. i haven't yet decided how (if at all) i'll call 2172 * this from userland when it's in the kernel. 2173 * ******************************************************************** 2174 */ 2175 static const char * 2176 sf(int f) 2177 { 2178 static char s[256]; 2179 char *c; 2180 2181 s[0] = '\0'; 2182 c = ""; 2183 2184 #define print_flag(_f, _s, _c, _q, _x) \ 2185 if (((_f) & (__CONCAT(CTLFLAG_,_x))) == (__CONCAT(CTLFLAG_,_q))) { \ 2186 strlcat((_s), (_c), sizeof(_s)); \ 2187 strlcat((_s), __STRING(_q), sizeof(_s)); \ 2188 (_c) = ","; \ 2189 (_f) &= ~__CONCAT(CTLFLAG_,_x); \ 2190 } 2191 2192 print_flag(f, s, c, READONLY, READWRITE); 2193 print_flag(f, s, c, READONLY1, READWRITE); 2194 print_flag(f, s, c, READONLY2, READWRITE); 2195 print_flag(f, s, c, READWRITE, READWRITE); 2196 print_flag(f, s, c, ANYWRITE, ANYWRITE); 2197 print_flag(f, s, c, PRIVATE, PRIVATE); 2198 print_flag(f, s, c, PERMANENT, PERMANENT); 2199 print_flag(f, s, c, OWNDATA, OWNDATA); 2200 print_flag(f, s, c, IMMEDIATE, IMMEDIATE); 2201 print_flag(f, s, c, HEX, HEX); 2202 print_flag(f, s, c, ROOT, ROOT); 2203 print_flag(f, s, c, ANYNUMBER, ANYNUMBER); 2204 print_flag(f, s, c, HIDDEN, HIDDEN); 2205 print_flag(f, s, c, ALIAS, ALIAS); 2206 #undef print_flag 2207 2208 if (f) { 2209 char foo[9]; 2210 snprintf(foo, sizeof(foo), "%x", f); 2211 strlcat(s, c, sizeof(s)); 2212 strlcat(s, foo, sizeof(s)); 2213 } 2214 2215 return (s); 2216 } 2217 2218 static const char * 2219 st(int t) 2220 { 2221 2222 switch (t) { 2223 case CTLTYPE_NODE: 2224 return "NODE"; 2225 case CTLTYPE_INT: 2226 return "INT"; 2227 case CTLTYPE_STRING: 2228 return "STRING"; 2229 case CTLTYPE_QUAD: 2230 return "QUAD"; 2231 case CTLTYPE_STRUCT: 2232 return "STRUCT"; 2233 } 2234 2235 return "???"; 2236 } 2237 2238 void 2239 sysctl_dump(const struct sysctlnode *d) 2240 { 2241 static char nmib[64], smib[256]; 2242 static int indent; 2243 struct sysctlnode *n; 2244 char *np, *sp, tmp[20]; 2245 int i; 2246 2247 if (d == NULL) 2248 return; 2249 2250 np = &nmib[strlen(nmib)]; 2251 sp = &smib[strlen(smib)]; 2252 2253 if (!(d->sysctl_flags & CTLFLAG_ROOT)) { 2254 snprintf(tmp, sizeof(tmp), "%d", d->sysctl_num); 2255 strcat(nmib, "."); 2256 strcat(smib, "."); 2257 strcat(nmib, tmp); 2258 strcat(smib, d->sysctl_name); 2259 printf("%s -> %s (%d)\n", &nmib[1], &smib[1], 2260 SYSCTL_TYPE(d->sysctl_flags)); 2261 } 2262 2263 if (1) { 2264 printf("%*s%p:\tsysctl_name [%s]\n", indent, "", 2265 d, d->sysctl_name); 2266 printf("%*s\t\tsysctl_num %d\n", indent, "", 2267 d->sysctl_num); 2268 printf("%*s\t\tsysctl_flags %x (flags=%x<%s> type=%d<%s> " 2269 "size=%zu)\n", 2270 indent, "", d->sysctl_flags, 2271 SYSCTL_FLAGS(d->sysctl_flags), 2272 sf(SYSCTL_FLAGS(d->sysctl_flags)), 2273 SYSCTL_TYPE(d->sysctl_flags), 2274 st(SYSCTL_TYPE(d->sysctl_flags)), 2275 d->sysctl_size); 2276 if (SYSCTL_TYPE(d->sysctl_flags) == CTLTYPE_NODE) { 2277 printf("%*s\t\tsysctl_csize %d\n", indent, "", 2278 d->sysctl_csize); 2279 printf("%*s\t\tsysctl_clen %d\n", indent, "", 2280 d->sysctl_clen); 2281 printf("%*s\t\tsysctl_child %p\n", indent, "", 2282 d->sysctl_child); 2283 } 2284 else 2285 printf("%*s\t\tsysctl_data %p\n", indent, "", 2286 d->sysctl_data); 2287 printf("%*s\t\tsysctl_func %p\n", indent, "", 2288 d->sysctl_func); 2289 printf("%*s\t\tsysctl_parent %p\n", indent, "", 2290 d->sysctl_parent); 2291 printf("%*s\t\tsysctl_ver %d\n", indent, "", 2292 d->sysctl_ver); 2293 } 2294 2295 if (SYSCTL_TYPE(d->sysctl_flags) == CTLTYPE_NODE) { 2296 indent += 8; 2297 n = d->sysctl_child; 2298 for (i = 0; i < d->sysctl_clen; i++) { 2299 sysctl_dump(&n[i]); 2300 } 2301 indent -= 8; 2302 } 2303 2304 np[0] = '\0'; 2305 sp[0] = '\0'; 2306 } 2307 #endif /* 0 */ 2308 2309 /* 2310 * ******************************************************************** 2311 * Deletes an entire n-ary tree. Not recommended unless you know why 2312 * you're doing it. Personally, I don't know why you'd even think 2313 * about it. 2314 * ******************************************************************** 2315 */ 2316 void 2317 sysctl_free(struct sysctlnode *rnode) 2318 { 2319 struct sysctlnode *node, *pnode; 2320 2321 if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) { 2322 printf("sysctl_free: rnode %p wrong version\n", rnode); 2323 return; 2324 } 2325 2326 if (rnode == NULL) 2327 rnode = &sysctl_root; 2328 pnode = rnode; 2329 2330 node = pnode->sysctl_child; 2331 do { 2332 while (node != NULL && pnode->sysctl_csize > 0) { 2333 while (node < 2334 &pnode->sysctl_child[pnode->sysctl_clen] && 2335 (SYSCTL_TYPE(node->sysctl_flags) != 2336 CTLTYPE_NODE || 2337 node->sysctl_csize == 0)) { 2338 if (SYSCTL_FLAGS(node->sysctl_flags) & 2339 CTLFLAG_OWNDATA) { 2340 if (node->sysctl_data != NULL) { 2341 FREE(node->sysctl_data, 2342 M_SYSCTLDATA); 2343 node->sysctl_data = NULL; 2344 } 2345 } 2346 if (SYSCTL_FLAGS(node->sysctl_flags) & 2347 CTLFLAG_OWNDESC) { 2348 if (node->sysctl_desc != NULL) { 2349 FREE(node->sysctl_desc, 2350 M_SYSCTLDATA); 2351 node->sysctl_desc = NULL; 2352 } 2353 } 2354 node++; 2355 } 2356 if (node < &pnode->sysctl_child[pnode->sysctl_clen]) { 2357 pnode = node; 2358 node = node->sysctl_child; 2359 } 2360 else 2361 break; 2362 } 2363 if (pnode->sysctl_child != NULL) 2364 FREE(pnode->sysctl_child, M_SYSCTLNODE); 2365 pnode->sysctl_clen = 0; 2366 pnode->sysctl_csize = 0; 2367 pnode->sysctl_child = NULL; 2368 node = pnode; 2369 pnode = node->sysctl_parent; 2370 } while (pnode != NULL && node != rnode); 2371 } 2372 2373 int 2374 sysctl_log_add(struct sysctllog **logp, struct sysctlnode *node) 2375 { 2376 int name[CTL_MAXNAME], namelen, i; 2377 struct sysctlnode *pnode; 2378 struct sysctllog *log; 2379 2380 if (node->sysctl_flags & CTLFLAG_PERMANENT) 2381 return (0); 2382 2383 if (logp == NULL) 2384 return (0); 2385 2386 if (*logp == NULL) { 2387 MALLOC(log, struct sysctllog *, sizeof(struct sysctllog), 2388 M_SYSCTLDATA, M_WAITOK|M_CANFAIL); 2389 if (log == NULL) { 2390 /* XXX print error message? */ 2391 return (-1); 2392 } 2393 MALLOC(log->log_num, int *, 16 * sizeof(int), 2394 M_SYSCTLDATA, M_WAITOK|M_CANFAIL); 2395 if (log->log_num == NULL) { 2396 /* XXX print error message? */ 2397 free(log, M_SYSCTLDATA); 2398 return (-1); 2399 } 2400 memset(log->log_num, 0, 16 * sizeof(int)); 2401 log->log_root = NULL; 2402 log->log_size = 16; 2403 log->log_left = 16; 2404 *logp = log; 2405 } 2406 else 2407 log = *logp; 2408 2409 /* 2410 * check that the root is proper. it's okay to record the 2411 * address of the root of a tree. it's the only thing that's 2412 * guaranteed not to shift around as nodes come and go. 2413 */ 2414 if (log->log_root == NULL) 2415 log->log_root = sysctl_rootof(node); 2416 else if (log->log_root != sysctl_rootof(node)) { 2417 printf("sysctl: log %p root mismatch (%p)\n", 2418 log->log_root, sysctl_rootof(node)); 2419 return (-1); 2420 } 2421 2422 /* 2423 * we will copy out name in reverse order 2424 */ 2425 for (pnode = node, namelen = 0; 2426 pnode != NULL && !(pnode->sysctl_flags & CTLFLAG_ROOT); 2427 pnode = pnode->sysctl_parent) 2428 name[namelen++] = pnode->sysctl_num; 2429 2430 /* 2431 * do we have space? 2432 */ 2433 if (log->log_left < (namelen + 3)) 2434 sysctl_log_realloc(log); 2435 if (log->log_left < (namelen + 3)) 2436 return (-1); 2437 2438 /* 2439 * stuff name in, then namelen, then node type, and finally, 2440 * the version for non-node nodes. 2441 */ 2442 for (i = 0; i < namelen; i++) 2443 log->log_num[--log->log_left] = name[i]; 2444 log->log_num[--log->log_left] = namelen; 2445 log->log_num[--log->log_left] = SYSCTL_TYPE(node->sysctl_flags); 2446 if (log->log_num[log->log_left] != CTLTYPE_NODE) 2447 log->log_num[--log->log_left] = node->sysctl_ver; 2448 else 2449 log->log_num[--log->log_left] = 0; 2450 2451 return (0); 2452 } 2453 2454 void 2455 sysctl_teardown(struct sysctllog **logp) 2456 { 2457 struct sysctlnode node, *rnode; 2458 struct sysctllog *log; 2459 uint namelen; 2460 int *name, t, v, error, ni; 2461 size_t sz; 2462 2463 if (logp == NULL || *logp == NULL) 2464 return; 2465 log = *logp; 2466 2467 error = sysctl_lock(NULL, NULL, 0); 2468 if (error) 2469 return; 2470 2471 memset(&node, 0, sizeof(node)); 2472 2473 while (log->log_left < log->log_size) { 2474 KASSERT((log->log_left + 3 < log->log_size) && 2475 (log->log_left + log->log_num[log->log_left + 2] <= 2476 log->log_size)); 2477 v = log->log_num[log->log_left++]; 2478 t = log->log_num[log->log_left++]; 2479 namelen = log->log_num[log->log_left++]; 2480 name = &log->log_num[log->log_left]; 2481 2482 node.sysctl_num = name[namelen - 1]; 2483 node.sysctl_flags = SYSCTL_VERSION|t; 2484 node.sysctl_ver = v; 2485 2486 rnode = log->log_root; 2487 error = sysctl_locate(NULL, &name[0], namelen, &rnode, &ni); 2488 if (error == 0) { 2489 name[namelen - 1] = CTL_DESTROY; 2490 rnode = rnode->sysctl_parent; 2491 sz = 0; 2492 (void)sysctl_destroy(&name[namelen - 1], 1, NULL, 2493 &sz, &node, sizeof(node), 2494 &name[0], NULL, rnode); 2495 } 2496 2497 log->log_left += namelen; 2498 } 2499 2500 KASSERT(log->log_size == log->log_left); 2501 free(log->log_num, M_SYSCTLDATA); 2502 free(log, M_SYSCTLDATA); 2503 *logp = NULL; 2504 2505 sysctl_unlock(NULL); 2506 } 2507 2508 /* 2509 * ******************************************************************** 2510 * old_sysctl -- A routine to bridge old-style internal calls to the 2511 * new infrastructure. 2512 * ******************************************************************** 2513 */ 2514 int 2515 old_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 2516 void *newp, size_t newlen, struct lwp *l) 2517 { 2518 int error; 2519 size_t savelen = *oldlenp; 2520 2521 error = sysctl_lock(l, oldp, savelen); 2522 if (error) 2523 return (error); 2524 error = sysctl_dispatch(name, namelen, oldp, oldlenp, 2525 newp, newlen, name, l, NULL); 2526 sysctl_unlock(l); 2527 if (error == 0 && oldp != NULL && savelen < *oldlenp) 2528 error = ENOMEM; 2529 2530 return (error); 2531 } 2532 2533 /* 2534 * ******************************************************************** 2535 * Section 4: Generic helper routines 2536 * ******************************************************************** 2537 * "helper" routines that can do more finely grained access control, 2538 * construct structures from disparate information, create the 2539 * appearance of more nodes and sub-trees, etc. for example, if 2540 * CTL_PROC wanted a helper function, it could respond to a CTL_QUERY 2541 * with a dynamically created list of nodes that represented the 2542 * currently running processes at that instant. 2543 * ******************************************************************** 2544 */ 2545 2546 /* 2547 * first, a few generic helpers that provide: 2548 * 2549 * sysctl_needfunc() a readonly interface that emits a warning 2550 * sysctl_notavail() returns EOPNOTSUPP (generic error) 2551 * sysctl_null() an empty return buffer with no error 2552 */ 2553 int 2554 sysctl_needfunc(SYSCTLFN_ARGS) 2555 { 2556 int error; 2557 2558 printf("!!SYSCTL_NEEDFUNC!!\n"); 2559 2560 if (newp != NULL || namelen != 0) 2561 return (EOPNOTSUPP); 2562 2563 error = 0; 2564 if (oldp != NULL) 2565 error = sysctl_copyout(l, rnode->sysctl_data, oldp, 2566 MIN(rnode->sysctl_size, *oldlenp)); 2567 *oldlenp = rnode->sysctl_size; 2568 2569 return (error); 2570 } 2571 2572 int 2573 sysctl_notavail(SYSCTLFN_ARGS) 2574 { 2575 2576 if (namelen == 1 && name[0] == CTL_QUERY) 2577 return (sysctl_query(SYSCTLFN_CALL(rnode))); 2578 2579 return (EOPNOTSUPP); 2580 } 2581 2582 int 2583 sysctl_null(SYSCTLFN_ARGS) 2584 { 2585 2586 *oldlenp = 0; 2587 2588 return (0); 2589 } 2590 2591 /* 2592 * ******************************************************************** 2593 * Section 5: The machinery that makes it all go 2594 * ******************************************************************** 2595 * Memory "manglement" routines. Not much to this, eh? 2596 * ******************************************************************** 2597 */ 2598 static int 2599 sysctl_alloc(struct sysctlnode *p, int x) 2600 { 2601 int i; 2602 struct sysctlnode *n; 2603 2604 assert(p->sysctl_child == NULL); 2605 2606 if (x == 1) 2607 MALLOC(n, struct sysctlnode *, 2608 sizeof(struct sysctlnode), 2609 M_SYSCTLNODE, M_WAITOK|M_CANFAIL); 2610 else 2611 MALLOC(n, struct sysctlnode *, 2612 SYSCTL_DEFSIZE * sizeof(struct sysctlnode), 2613 M_SYSCTLNODE, M_WAITOK|M_CANFAIL); 2614 if (n == NULL) 2615 return (ENOMEM); 2616 2617 if (x == 1) { 2618 memset(n, 0, sizeof(struct sysctlnode)); 2619 p->sysctl_csize = 1; 2620 } 2621 else { 2622 memset(n, 0, SYSCTL_DEFSIZE * sizeof(struct sysctlnode)); 2623 p->sysctl_csize = SYSCTL_DEFSIZE; 2624 } 2625 p->sysctl_clen = 0; 2626 2627 for (i = 0; i < p->sysctl_csize; i++) 2628 n[i].sysctl_parent = p; 2629 2630 p->sysctl_child = n; 2631 return (0); 2632 } 2633 2634 static int 2635 sysctl_realloc(struct sysctlnode *p) 2636 { 2637 int i, j; 2638 struct sysctlnode *n; 2639 2640 assert(p->sysctl_csize == p->sysctl_clen); 2641 2642 /* 2643 * how many do we have...how many should we make? 2644 */ 2645 i = p->sysctl_clen; 2646 n = malloc(2 * i * sizeof(struct sysctlnode), M_SYSCTLNODE, 2647 M_WAITOK|M_CANFAIL); 2648 if (n == NULL) 2649 return (ENOMEM); 2650 2651 /* 2652 * move old children over...initialize new children 2653 */ 2654 memcpy(n, p->sysctl_child, i * sizeof(struct sysctlnode)); 2655 memset(&n[i], 0, i * sizeof(struct sysctlnode)); 2656 p->sysctl_csize = 2 * i; 2657 2658 /* 2659 * reattach moved (and new) children to parent; if a moved 2660 * child node has children, reattach the parent pointers of 2661 * grandchildren 2662 */ 2663 for (i = 0; i < p->sysctl_csize; i++) { 2664 n[i].sysctl_parent = p; 2665 if (n[i].sysctl_child != NULL) { 2666 for (j = 0; j < n[i].sysctl_csize; j++) 2667 n[i].sysctl_child[j].sysctl_parent = &n[i]; 2668 } 2669 } 2670 2671 /* 2672 * get out with the old and in with the new 2673 */ 2674 FREE(p->sysctl_child, M_SYSCTLNODE); 2675 p->sysctl_child = n; 2676 2677 return (0); 2678 } 2679 2680 static int 2681 sysctl_log_realloc(struct sysctllog *log) 2682 { 2683 int *n, s, d; 2684 2685 s = log->log_size * 2; 2686 d = log->log_size; 2687 2688 n = malloc(s * sizeof(int), M_SYSCTLDATA, M_WAITOK|M_CANFAIL); 2689 if (n == NULL) 2690 return (-1); 2691 2692 memset(n, 0, s * sizeof(int)); 2693 memcpy(&n[d], log->log_num, d * sizeof(int)); 2694 free(log->log_num, M_SYSCTLDATA); 2695 log->log_num = n; 2696 if (d) 2697 log->log_left += d; 2698 else 2699 log->log_left = s; 2700 log->log_size = s; 2701 2702 return (0); 2703 } 2704 2705 /* 2706 * ******************************************************************** 2707 * Section 6: Conversion between API versions wrt the sysctlnode 2708 * ******************************************************************** 2709 */ 2710 static int 2711 sysctl_cvt_in(struct lwp *l, int *vp, const void *i, size_t sz, 2712 struct sysctlnode *node) 2713 { 2714 int error, flags; 2715 2716 if (i == NULL || sz < sizeof(flags)) 2717 return (EINVAL); 2718 2719 error = sysctl_copyin(l, i, &flags, sizeof(flags)); 2720 if (error) 2721 return (error); 2722 2723 #if (SYSCTL_VERSION != SYSCTL_VERS_1) 2724 #error sysctl_cvt_in: no support for SYSCTL_VERSION 2725 #endif /* (SYSCTL_VERSION != SYSCTL_VERS_1) */ 2726 2727 if (sz == sizeof(*node) && 2728 SYSCTL_VERS(flags) == SYSCTL_VERSION) { 2729 error = sysctl_copyin(l, i, node, sizeof(*node)); 2730 if (error) 2731 return (error); 2732 *vp = SYSCTL_VERSION; 2733 return (0); 2734 } 2735 2736 return (EINVAL); 2737 } 2738 2739 static int 2740 sysctl_cvt_out(struct lwp *l, int v, const struct sysctlnode *i, 2741 void *ovp, size_t left, size_t *szp) 2742 { 2743 size_t sz = sizeof(*i); 2744 const void *src = i; 2745 int error; 2746 2747 switch (v) { 2748 case SYSCTL_VERS_0: 2749 return (EINVAL); 2750 2751 #if (SYSCTL_VERSION != SYSCTL_VERS_1) 2752 #error sysctl_cvt_out: no support for SYSCTL_VERSION 2753 #endif /* (SYSCTL_VERSION != SYSCTL_VERS_1) */ 2754 2755 case SYSCTL_VERSION: 2756 /* nothing more to do here */ 2757 break; 2758 } 2759 2760 if (ovp != NULL && left >= sz) { 2761 error = sysctl_copyout(l, src, ovp, sz); 2762 if (error) 2763 return (error); 2764 } 2765 2766 if (szp != NULL) 2767 *szp = sz; 2768 2769 return (0); 2770 } 2771