1 /*- 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Mike Karels at Berkeley Software Design, Inc. 7 * 8 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD 9 * project, to make these variables more userfriendly. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 40 * $FreeBSD$ 41 */ 42 43 #include "opt_compat.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/kernel.h> 48 #include <sys/sysctl.h> 49 #include <sys/malloc.h> 50 #include <sys/proc.h> 51 #include <sys/lock.h> 52 #include <sys/mutex.h> 53 #include <sys/sysproto.h> 54 #include <vm/vm.h> 55 #include <vm/vm_extern.h> 56 57 static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic"); 58 static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids"); 59 60 /* 61 * Locking and stats 62 */ 63 static struct sysctl_lock { 64 int sl_lock; 65 int sl_want; 66 int sl_locked; 67 } memlock; 68 69 static int sysctl_root(SYSCTL_HANDLER_ARGS); 70 71 struct sysctl_oid_list sysctl__children; /* root list */ 72 73 static struct sysctl_oid * 74 sysctl_find_oidname(const char *name, struct sysctl_oid_list *list) 75 { 76 struct sysctl_oid *oidp; 77 78 SLIST_FOREACH(oidp, list, oid_link) { 79 if (strcmp(oidp->oid_name, name) == 0) { 80 return (oidp); 81 } 82 } 83 return (NULL); 84 } 85 86 /* 87 * Initialization of the MIB tree. 88 * 89 * Order by number in each list. 90 */ 91 92 void 93 sysctl_register_oid(struct sysctl_oid *oidp) 94 { 95 struct sysctl_oid_list *parent = oidp->oid_parent; 96 struct sysctl_oid *p; 97 struct sysctl_oid *q; 98 99 /* 100 * First check if another oid with the same name already 101 * exists in the parent's list. 102 */ 103 p = sysctl_find_oidname(oidp->oid_name, parent); 104 if (p != NULL) { 105 if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 106 p->oid_refcnt++; 107 return; 108 } else { 109 printf("can't re-use a leaf (%s)!\n", p->oid_name); 110 return; 111 } 112 } 113 /* 114 * If this oid has a number OID_AUTO, give it a number which 115 * is greater than any current oid. 116 * NOTE: DO NOT change the starting value here, change it in 117 * <sys/sysctl.h>, and make sure it is at least 256 to 118 * accomodate e.g. net.inet.raw as a static sysctl node. 119 */ 120 if (oidp->oid_number == OID_AUTO) { 121 static int newoid = CTL_AUTO_START; 122 123 oidp->oid_number = newoid++; 124 if (newoid == 0x7fffffff) 125 panic("out of oids"); 126 } 127 #if 0 128 else if (oidp->oid_number >= CTL_AUTO_START) { 129 /* do not panic; this happens when unregistering sysctl sets */ 130 printf("static sysctl oid too high: %d", oidp->oid_number); 131 } 132 #endif 133 134 /* 135 * Insert the oid into the parent's list in order. 136 */ 137 q = NULL; 138 SLIST_FOREACH(p, parent, oid_link) { 139 if (oidp->oid_number < p->oid_number) 140 break; 141 q = p; 142 } 143 if (q) 144 SLIST_INSERT_AFTER(q, oidp, oid_link); 145 else 146 SLIST_INSERT_HEAD(parent, oidp, oid_link); 147 } 148 149 void 150 sysctl_unregister_oid(struct sysctl_oid *oidp) 151 { 152 SLIST_REMOVE(oidp->oid_parent, oidp, sysctl_oid, oid_link); 153 } 154 155 /* Initialize a new context to keep track of dynamically added sysctls. */ 156 int 157 sysctl_ctx_init(struct sysctl_ctx_list *c) 158 { 159 160 if (c == NULL) { 161 return (EINVAL); 162 } 163 TAILQ_INIT(c); 164 return (0); 165 } 166 167 /* Free the context, and destroy all dynamic oids registered in this context */ 168 int 169 sysctl_ctx_free(struct sysctl_ctx_list *clist) 170 { 171 struct sysctl_ctx_entry *e, *e1; 172 int error; 173 174 error = 0; 175 /* 176 * First perform a "dry run" to check if it's ok to remove oids. 177 * XXX FIXME 178 * XXX This algorithm is a hack. But I don't know any 179 * XXX better solution for now... 180 */ 181 TAILQ_FOREACH(e, clist, link) { 182 error = sysctl_remove_oid(e->entry, 0, 0); 183 if (error) 184 break; 185 } 186 /* 187 * Restore deregistered entries, either from the end, 188 * or from the place where error occured. 189 * e contains the entry that was not unregistered 190 */ 191 if (error) 192 e1 = TAILQ_PREV(e, sysctl_ctx_list, link); 193 else 194 e1 = TAILQ_LAST(clist, sysctl_ctx_list); 195 while (e1 != NULL) { 196 sysctl_register_oid(e1->entry); 197 e1 = TAILQ_PREV(e1, sysctl_ctx_list, link); 198 } 199 if (error) 200 return(EBUSY); 201 /* Now really delete the entries */ 202 e = TAILQ_FIRST(clist); 203 while (e != NULL) { 204 e1 = TAILQ_NEXT(e, link); 205 error = sysctl_remove_oid(e->entry, 1, 0); 206 if (error) 207 panic("sysctl_remove_oid: corrupt tree, entry: %s", 208 e->entry->oid_name); 209 free(e, M_SYSCTLOID); 210 e = e1; 211 } 212 return (error); 213 } 214 215 /* Add an entry to the context */ 216 struct sysctl_ctx_entry * 217 sysctl_ctx_entry_add(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp) 218 { 219 struct sysctl_ctx_entry *e; 220 221 if (clist == NULL || oidp == NULL) 222 return(NULL); 223 e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK); 224 e->entry = oidp; 225 TAILQ_INSERT_HEAD(clist, e, link); 226 return (e); 227 } 228 229 /* Find an entry in the context */ 230 struct sysctl_ctx_entry * 231 sysctl_ctx_entry_find(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp) 232 { 233 struct sysctl_ctx_entry *e; 234 235 if (clist == NULL || oidp == NULL) 236 return(NULL); 237 TAILQ_FOREACH(e, clist, link) { 238 if(e->entry == oidp) 239 return(e); 240 } 241 return (e); 242 } 243 244 /* 245 * Delete an entry from the context. 246 * NOTE: this function doesn't free oidp! You have to remove it 247 * with sysctl_remove_oid(). 248 */ 249 int 250 sysctl_ctx_entry_del(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp) 251 { 252 struct sysctl_ctx_entry *e; 253 254 if (clist == NULL || oidp == NULL) 255 return (EINVAL); 256 e = sysctl_ctx_entry_find(clist, oidp); 257 if (e != NULL) { 258 TAILQ_REMOVE(clist, e, link); 259 free(e, M_SYSCTLOID); 260 return (0); 261 } else 262 return (ENOENT); 263 } 264 265 /* 266 * Remove dynamically created sysctl trees. 267 * oidp - top of the tree to be removed 268 * del - if 0 - just deregister, otherwise free up entries as well 269 * recurse - if != 0 traverse the subtree to be deleted 270 */ 271 int 272 sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse) 273 { 274 struct sysctl_oid *p; 275 int error; 276 277 if (oidp == NULL) 278 return(EINVAL); 279 if ((oidp->oid_kind & CTLFLAG_DYN) == 0) { 280 printf("can't remove non-dynamic nodes!\n"); 281 return (EINVAL); 282 } 283 /* 284 * WARNING: normal method to do this should be through 285 * sysctl_ctx_free(). Use recursing as the last resort 286 * method to purge your sysctl tree of leftovers... 287 * However, if some other code still references these nodes, 288 * it will panic. 289 */ 290 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 291 if (oidp->oid_refcnt == 1) { 292 SLIST_FOREACH(p, SYSCTL_CHILDREN(oidp), oid_link) { 293 if (!recurse) 294 return (ENOTEMPTY); 295 error = sysctl_remove_oid(p, del, recurse); 296 if (error) 297 return (error); 298 } 299 if (del) 300 free(SYSCTL_CHILDREN(oidp), M_SYSCTLOID); 301 } 302 } 303 if (oidp->oid_refcnt > 1 ) { 304 oidp->oid_refcnt--; 305 } else { 306 if (oidp->oid_refcnt == 0) { 307 printf("Warning: bad oid_refcnt=%u (%s)!\n", 308 oidp->oid_refcnt, oidp->oid_name); 309 return (EINVAL); 310 } 311 sysctl_unregister_oid(oidp); 312 if (del) { 313 if (oidp->descr) 314 free(oidp->descr, M_SYSCTLOID); 315 free((void *)(uintptr_t)(const void *)oidp->oid_name, 316 M_SYSCTLOID); 317 free(oidp, M_SYSCTLOID); 318 } 319 } 320 return (0); 321 } 322 323 /* 324 * Create new sysctls at run time. 325 * clist may point to a valid context initialized with sysctl_ctx_init(). 326 */ 327 struct sysctl_oid * 328 sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent, 329 int number, const char *name, int kind, void *arg1, int arg2, 330 int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr) 331 { 332 struct sysctl_oid *oidp; 333 ssize_t len; 334 char *newname; 335 336 /* You have to hook up somewhere.. */ 337 if (parent == NULL) 338 return(NULL); 339 /* Check if the node already exists, otherwise create it */ 340 oidp = sysctl_find_oidname(name, parent); 341 if (oidp != NULL) { 342 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 343 oidp->oid_refcnt++; 344 /* Update the context */ 345 if (clist != NULL) 346 sysctl_ctx_entry_add(clist, oidp); 347 return (oidp); 348 } else { 349 printf("can't re-use a leaf (%s)!\n", name); 350 return (NULL); 351 } 352 } 353 oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK|M_ZERO); 354 oidp->oid_parent = parent; 355 SLIST_NEXT(oidp, oid_link) = NULL; 356 oidp->oid_number = number; 357 oidp->oid_refcnt = 1; 358 len = strlen(name); 359 newname = malloc(len + 1, M_SYSCTLOID, M_WAITOK); 360 bcopy(name, newname, len + 1); 361 newname[len] = '\0'; 362 oidp->oid_name = newname; 363 oidp->oid_handler = handler; 364 oidp->oid_kind = CTLFLAG_DYN | kind; 365 if ((kind & CTLTYPE) == CTLTYPE_NODE) { 366 /* Allocate space for children */ 367 SYSCTL_CHILDREN(oidp) = malloc(sizeof(struct sysctl_oid_list), 368 M_SYSCTLOID, M_WAITOK); 369 SLIST_INIT(SYSCTL_CHILDREN(oidp)); 370 } else { 371 oidp->oid_arg1 = arg1; 372 oidp->oid_arg2 = arg2; 373 } 374 oidp->oid_fmt = fmt; 375 if (descr) { 376 int len = strlen(descr) + 1; 377 oidp->descr = malloc(len, M_SYSCTLOID, M_WAITOK); 378 if (oidp->descr) 379 strcpy(oidp->descr, descr); 380 } 381 /* Update the context, if used */ 382 if (clist != NULL) 383 sysctl_ctx_entry_add(clist, oidp); 384 /* Register this oid */ 385 sysctl_register_oid(oidp); 386 return (oidp); 387 } 388 389 /* 390 * Register the kernel's oids on startup. 391 */ 392 SET_DECLARE(sysctl_set, struct sysctl_oid); 393 394 static void 395 sysctl_register_all(void *arg) 396 { 397 struct sysctl_oid **oidp; 398 399 SET_FOREACH(oidp, sysctl_set) 400 sysctl_register_oid(*oidp); 401 } 402 SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_register_all, 0); 403 404 /* 405 * "Staff-functions" 406 * 407 * These functions implement a presently undocumented interface 408 * used by the sysctl program to walk the tree, and get the type 409 * so it can print the value. 410 * This interface is under work and consideration, and should probably 411 * be killed with a big axe by the first person who can find the time. 412 * (be aware though, that the proper interface isn't as obvious as it 413 * may seem, there are various conflicting requirements. 414 * 415 * {0,0} printf the entire MIB-tree. 416 * {0,1,...} return the name of the "..." OID. 417 * {0,2,...} return the next OID. 418 * {0,3} return the OID of the name in "new" 419 * {0,4,...} return the kind & format info for the "..." OID. 420 * {0,5,...} return the description the "..." OID. 421 */ 422 423 static void 424 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i) 425 { 426 int k; 427 struct sysctl_oid *oidp; 428 429 SLIST_FOREACH(oidp, l, oid_link) { 430 431 for (k=0; k<i; k++) 432 printf(" "); 433 434 printf("%d %s ", oidp->oid_number, oidp->oid_name); 435 436 printf("%c%c", 437 oidp->oid_kind & CTLFLAG_RD ? 'R':' ', 438 oidp->oid_kind & CTLFLAG_WR ? 'W':' '); 439 440 if (oidp->oid_handler) 441 printf(" *Handler"); 442 443 switch (oidp->oid_kind & CTLTYPE) { 444 case CTLTYPE_NODE: 445 printf(" Node\n"); 446 if (!oidp->oid_handler) { 447 sysctl_sysctl_debug_dump_node( 448 oidp->oid_arg1, i+2); 449 } 450 break; 451 case CTLTYPE_INT: printf(" Int\n"); break; 452 case CTLTYPE_STRING: printf(" String\n"); break; 453 case CTLTYPE_QUAD: printf(" Quad\n"); break; 454 case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break; 455 default: printf("\n"); 456 } 457 458 } 459 } 460 461 static int 462 sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS) 463 { 464 int error; 465 466 error = suser(req->td->td_proc); 467 if (error) 468 return error; 469 sysctl_sysctl_debug_dump_node(&sysctl__children, 0); 470 return ENOENT; 471 } 472 473 SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD, 474 0, 0, sysctl_sysctl_debug, "-", ""); 475 476 static int 477 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) 478 { 479 int *name = (int *) arg1; 480 u_int namelen = arg2; 481 int error = 0; 482 struct sysctl_oid *oid; 483 struct sysctl_oid_list *lsp = &sysctl__children, *lsp2; 484 char buf[10]; 485 486 while (namelen) { 487 if (!lsp) { 488 snprintf(buf,sizeof(buf),"%d",*name); 489 if (req->oldidx) 490 error = SYSCTL_OUT(req, ".", 1); 491 if (!error) 492 error = SYSCTL_OUT(req, buf, strlen(buf)); 493 if (error) 494 return (error); 495 namelen--; 496 name++; 497 continue; 498 } 499 lsp2 = 0; 500 SLIST_FOREACH(oid, lsp, oid_link) { 501 if (oid->oid_number != *name) 502 continue; 503 504 if (req->oldidx) 505 error = SYSCTL_OUT(req, ".", 1); 506 if (!error) 507 error = SYSCTL_OUT(req, oid->oid_name, 508 strlen(oid->oid_name)); 509 if (error) 510 return (error); 511 512 namelen--; 513 name++; 514 515 if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE) 516 break; 517 518 if (oid->oid_handler) 519 break; 520 521 lsp2 = (struct sysctl_oid_list *)oid->oid_arg1; 522 break; 523 } 524 lsp = lsp2; 525 } 526 return (SYSCTL_OUT(req, "", 1)); 527 } 528 529 SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD, sysctl_sysctl_name, ""); 530 531 static int 532 sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen, 533 int *next, int *len, int level, struct sysctl_oid **oidpp) 534 { 535 struct sysctl_oid *oidp; 536 537 *len = level; 538 SLIST_FOREACH(oidp, lsp, oid_link) { 539 *next = oidp->oid_number; 540 *oidpp = oidp; 541 542 if (!namelen) { 543 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 544 return 0; 545 if (oidp->oid_handler) 546 /* We really should call the handler here...*/ 547 return 0; 548 lsp = (struct sysctl_oid_list *)oidp->oid_arg1; 549 if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1, 550 len, level+1, oidpp)) 551 return 0; 552 goto next; 553 } 554 555 if (oidp->oid_number < *name) 556 continue; 557 558 if (oidp->oid_number > *name) { 559 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 560 return 0; 561 if (oidp->oid_handler) 562 return 0; 563 lsp = (struct sysctl_oid_list *)oidp->oid_arg1; 564 if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, 565 next+1, len, level+1, oidpp)) 566 return (0); 567 goto next; 568 } 569 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 570 continue; 571 572 if (oidp->oid_handler) 573 continue; 574 575 lsp = (struct sysctl_oid_list *)oidp->oid_arg1; 576 if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1, 577 len, level+1, oidpp)) 578 return (0); 579 next: 580 namelen = 1; 581 *len = level; 582 } 583 return 1; 584 } 585 586 static int 587 sysctl_sysctl_next(SYSCTL_HANDLER_ARGS) 588 { 589 int *name = (int *) arg1; 590 u_int namelen = arg2; 591 int i, j, error; 592 struct sysctl_oid *oid; 593 struct sysctl_oid_list *lsp = &sysctl__children; 594 int newoid[CTL_MAXNAME]; 595 596 i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid); 597 if (i) 598 return ENOENT; 599 error = SYSCTL_OUT(req, newoid, j * sizeof (int)); 600 return (error); 601 } 602 603 SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, ""); 604 605 static int 606 name2oid (char *name, int *oid, int *len, struct sysctl_oid **oidpp) 607 { 608 int i; 609 struct sysctl_oid *oidp; 610 struct sysctl_oid_list *lsp = &sysctl__children; 611 char *p; 612 613 if (!*name) 614 return ENOENT; 615 616 p = name + strlen(name) - 1 ; 617 if (*p == '.') 618 *p = '\0'; 619 620 *len = 0; 621 622 for (p = name; *p && *p != '.'; p++) 623 ; 624 i = *p; 625 if (i == '.') 626 *p = '\0'; 627 628 oidp = SLIST_FIRST(lsp); 629 630 while (oidp && *len < CTL_MAXNAME) { 631 if (strcmp(name, oidp->oid_name)) { 632 oidp = SLIST_NEXT(oidp, oid_link); 633 continue; 634 } 635 *oid++ = oidp->oid_number; 636 (*len)++; 637 638 if (!i) { 639 if (oidpp) 640 *oidpp = oidp; 641 return (0); 642 } 643 644 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 645 break; 646 647 if (oidp->oid_handler) 648 break; 649 650 lsp = (struct sysctl_oid_list *)oidp->oid_arg1; 651 oidp = SLIST_FIRST(lsp); 652 name = p+1; 653 for (p = name; *p && *p != '.'; p++) 654 ; 655 i = *p; 656 if (i == '.') 657 *p = '\0'; 658 } 659 return ENOENT; 660 } 661 662 static int 663 sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS) 664 { 665 char *p; 666 int error, oid[CTL_MAXNAME], len; 667 struct sysctl_oid *op = 0; 668 669 if (!req->newlen) 670 return ENOENT; 671 if (req->newlen >= MAXPATHLEN) /* XXX arbitrary, undocumented */ 672 return (ENAMETOOLONG); 673 674 p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK); 675 676 error = SYSCTL_IN(req, p, req->newlen); 677 if (error) { 678 free(p, M_SYSCTL); 679 return (error); 680 } 681 682 p [req->newlen] = '\0'; 683 684 error = name2oid(p, oid, &len, &op); 685 686 free(p, M_SYSCTL); 687 688 if (error) 689 return (error); 690 691 error = SYSCTL_OUT(req, oid, len * sizeof *oid); 692 return (error); 693 } 694 695 SYSCTL_PROC(_sysctl, 3, name2oid, CTLFLAG_RW|CTLFLAG_ANYBODY, 0, 0, 696 sysctl_sysctl_name2oid, "I", ""); 697 698 static int 699 sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS) 700 { 701 struct sysctl_oid *oid; 702 int error; 703 704 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req); 705 if (error) 706 return (error); 707 708 if (!oid->oid_fmt) 709 return (ENOENT); 710 error = SYSCTL_OUT(req, &oid->oid_kind, sizeof(oid->oid_kind)); 711 if (error) 712 return (error); 713 error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1); 714 return (error); 715 } 716 717 718 SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD, sysctl_sysctl_oidfmt, ""); 719 720 static int 721 sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS) 722 { 723 struct sysctl_oid *oid; 724 int error; 725 726 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req); 727 if (error) 728 return (error); 729 730 if (!oid->descr) 731 return (ENOENT); 732 error = SYSCTL_OUT(req, oid->descr, strlen(oid->descr) + 1); 733 return (error); 734 } 735 736 SYSCTL_NODE(_sysctl, 5, oiddescr, CTLFLAG_RD, sysctl_sysctl_oiddescr, ""); 737 738 /* 739 * Default "handler" functions. 740 */ 741 742 /* 743 * Handle an int, signed or unsigned. 744 * Two cases: 745 * a variable: point arg1 at it. 746 * a constant: pass it in arg2. 747 */ 748 749 int 750 sysctl_handle_int(SYSCTL_HANDLER_ARGS) 751 { 752 int error = 0; 753 754 if (arg1) 755 error = SYSCTL_OUT(req, arg1, sizeof(int)); 756 else 757 error = SYSCTL_OUT(req, &arg2, sizeof(int)); 758 759 if (error || !req->newptr) 760 return (error); 761 762 if (!arg1) 763 error = EPERM; 764 else 765 error = SYSCTL_IN(req, arg1, sizeof(int)); 766 return (error); 767 } 768 769 /* 770 * Handle a long, signed or unsigned. arg1 points to it. 771 */ 772 773 int 774 sysctl_handle_long(SYSCTL_HANDLER_ARGS) 775 { 776 int error = 0; 777 778 if (!arg1) 779 return (EINVAL); 780 error = SYSCTL_OUT(req, arg1, sizeof(long)); 781 782 if (error || !req->newptr) 783 return (error); 784 785 error = SYSCTL_IN(req, arg1, sizeof(long)); 786 return (error); 787 } 788 789 /* 790 * Handle our generic '\0' terminated 'C' string. 791 * Two cases: 792 * a variable string: point arg1 at it, arg2 is max length. 793 * a constant string: point arg1 at it, arg2 is zero. 794 */ 795 796 int 797 sysctl_handle_string(SYSCTL_HANDLER_ARGS) 798 { 799 int error=0; 800 801 error = SYSCTL_OUT(req, arg1, strlen((char *)arg1)+1); 802 803 if (error || !req->newptr) 804 return (error); 805 806 if ((req->newlen - req->newidx) >= arg2) { 807 error = EINVAL; 808 } else { 809 arg2 = (req->newlen - req->newidx); 810 error = SYSCTL_IN(req, arg1, arg2); 811 ((char *)arg1)[arg2] = '\0'; 812 } 813 814 return (error); 815 } 816 817 /* 818 * Handle any kind of opaque data. 819 * arg1 points to it, arg2 is the size. 820 */ 821 822 int 823 sysctl_handle_opaque(SYSCTL_HANDLER_ARGS) 824 { 825 int error; 826 827 error = SYSCTL_OUT(req, arg1, arg2); 828 829 if (error || !req->newptr) 830 return (error); 831 832 error = SYSCTL_IN(req, arg1, arg2); 833 834 return (error); 835 } 836 837 /* 838 * Transfer functions to/from kernel space. 839 * XXX: rather untested at this point 840 */ 841 static int 842 sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l) 843 { 844 size_t i = 0; 845 846 if (req->oldptr) { 847 i = l; 848 if (req->oldlen <= req->oldidx) 849 i = 0; 850 else 851 if (i > req->oldlen - req->oldidx) 852 i = req->oldlen - req->oldidx; 853 if (i > 0) 854 bcopy(p, (char *)req->oldptr + req->oldidx, i); 855 } 856 req->oldidx += l; 857 if (req->oldptr && i != l) 858 return (ENOMEM); 859 return (0); 860 } 861 862 static int 863 sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l) 864 { 865 if (!req->newptr) 866 return 0; 867 if (req->newlen - req->newidx < l) 868 return (EINVAL); 869 bcopy((char *)req->newptr + req->newidx, p, l); 870 req->newidx += l; 871 return (0); 872 } 873 874 int 875 kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old, 876 size_t *oldlenp, void *new, size_t newlen, size_t *retval) 877 { 878 int error = 0; 879 struct sysctl_req req; 880 881 bzero(&req, sizeof req); 882 883 req.td = td; 884 885 if (oldlenp) { 886 req.oldlen = *oldlenp; 887 } 888 889 if (old) { 890 req.oldptr= old; 891 } 892 893 if (new != NULL) { 894 req.newlen = newlen; 895 req.newptr = new; 896 } 897 898 req.oldfunc = sysctl_old_kernel; 899 req.newfunc = sysctl_new_kernel; 900 req.lock = 1; 901 902 /* XXX this should probably be done in a general way */ 903 while (memlock.sl_lock) { 904 memlock.sl_want = 1; 905 (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 906 memlock.sl_locked++; 907 } 908 memlock.sl_lock = 1; 909 910 error = sysctl_root(0, name, namelen, &req); 911 912 if (req.lock == 2) 913 vsunlock(req.oldptr, req.oldlen); 914 915 memlock.sl_lock = 0; 916 917 if (memlock.sl_want) { 918 memlock.sl_want = 0; 919 wakeup((caddr_t)&memlock); 920 } 921 922 if (error && error != ENOMEM) 923 return (error); 924 925 if (retval) { 926 if (req.oldptr && req.oldidx > req.oldlen) 927 *retval = req.oldlen; 928 else 929 *retval = req.oldidx; 930 } 931 return (error); 932 } 933 934 int 935 kernel_sysctlbyname(struct thread *td, char *name, void *old, size_t *oldlenp, 936 void *new, size_t newlen, size_t *retval) 937 { 938 int oid[CTL_MAXNAME]; 939 size_t oidlen, plen; 940 int error; 941 942 oid[0] = 0; /* sysctl internal magic */ 943 oid[1] = 3; /* name2oid */ 944 oidlen = sizeof(oid); 945 946 error = kernel_sysctl(td, oid, 2, oid, &oidlen, 947 (void *)name, strlen(name), &plen); 948 if (error) 949 return (error); 950 951 error = kernel_sysctl(td, oid, plen / sizeof(int), old, oldlenp, 952 new, newlen, retval); 953 return (error); 954 } 955 956 /* 957 * Transfer function to/from user space. 958 */ 959 static int 960 sysctl_old_user(struct sysctl_req *req, const void *p, size_t l) 961 { 962 int error = 0; 963 size_t i = 0; 964 965 if (req->lock == 1 && req->oldptr) { 966 vslock(req->oldptr, req->oldlen); 967 req->lock = 2; 968 } 969 if (req->oldptr) { 970 i = l; 971 if (req->oldlen <= req->oldidx) 972 i = 0; 973 else 974 if (i > req->oldlen - req->oldidx) 975 i = req->oldlen - req->oldidx; 976 if (i > 0) 977 error = copyout(p, (char *)req->oldptr + req->oldidx, 978 i); 979 } 980 req->oldidx += l; 981 if (error) 982 return (error); 983 if (req->oldptr && i < l) 984 return (ENOMEM); 985 return (0); 986 } 987 988 static int 989 sysctl_new_user(struct sysctl_req *req, void *p, size_t l) 990 { 991 int error; 992 993 if (!req->newptr) 994 return 0; 995 if (req->newlen - req->newidx < l) 996 return (EINVAL); 997 error = copyin((char *)req->newptr + req->newidx, p, l); 998 req->newidx += l; 999 return (error); 1000 } 1001 1002 int 1003 sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid, 1004 int *nindx, struct sysctl_req *req) 1005 { 1006 struct sysctl_oid *oid; 1007 int indx; 1008 1009 oid = SLIST_FIRST(&sysctl__children); 1010 indx = 0; 1011 while (oid && indx < CTL_MAXNAME) { 1012 if (oid->oid_number == name[indx]) { 1013 indx++; 1014 if (oid->oid_kind & CTLFLAG_NOLOCK) 1015 req->lock = 0; 1016 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 1017 if (oid->oid_handler != NULL || 1018 indx == namelen) { 1019 *noid = oid; 1020 if (nindx != NULL) 1021 *nindx = indx; 1022 return (0); 1023 } 1024 oid = SLIST_FIRST( 1025 (struct sysctl_oid_list *)oid->oid_arg1); 1026 } else if (indx == namelen) { 1027 *noid = oid; 1028 if (nindx != NULL) 1029 *nindx = indx; 1030 return (0); 1031 } else { 1032 return (ENOTDIR); 1033 } 1034 } else { 1035 oid = SLIST_NEXT(oid, oid_link); 1036 } 1037 } 1038 return (ENOENT); 1039 } 1040 1041 /* 1042 * Traverse our tree, and find the right node, execute whatever it points 1043 * to, and return the resulting error code. 1044 */ 1045 1046 int 1047 sysctl_root(SYSCTL_HANDLER_ARGS) 1048 { 1049 struct sysctl_oid *oid; 1050 int error, indx; 1051 1052 error = sysctl_find_oid(arg1, arg2, &oid, &indx, req); 1053 if (error) 1054 return (error); 1055 1056 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 1057 /* 1058 * You can't call a sysctl when it's a node, but has 1059 * no handler. Inform the user that it's a node. 1060 * The indx may or may not be the same as namelen. 1061 */ 1062 if (oid->oid_handler == NULL) 1063 return (EISDIR); 1064 } 1065 1066 /* Is this sysctl writable? */ 1067 if (req->newptr && !(oid->oid_kind & CTLFLAG_WR)) 1068 return (EPERM); 1069 1070 KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL")); 1071 1072 /* Is this sysctl sensitive to securelevels? */ 1073 if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) { 1074 error = securelevel_gt(req->td->td_ucred, 0); 1075 if (error) 1076 return (error); 1077 } 1078 1079 /* Is this sysctl writable by only privileged users? */ 1080 if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) { 1081 int flags; 1082 1083 if (oid->oid_kind & CTLFLAG_PRISON) 1084 flags = PRISON_ROOT; 1085 else 1086 flags = 0; 1087 error = suser_xxx(NULL, req->td->td_proc, flags); 1088 if (error) 1089 return (error); 1090 } 1091 1092 if (!oid->oid_handler) 1093 return EINVAL; 1094 1095 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) 1096 error = oid->oid_handler(oid, (int *)arg1 + indx, arg2 - indx, 1097 req); 1098 else 1099 error = oid->oid_handler(oid, oid->oid_arg1, oid->oid_arg2, 1100 req); 1101 return (error); 1102 } 1103 1104 #ifndef _SYS_SYSPROTO_H_ 1105 struct sysctl_args { 1106 int *name; 1107 u_int namelen; 1108 void *old; 1109 size_t *oldlenp; 1110 void *new; 1111 size_t newlen; 1112 }; 1113 #endif 1114 1115 /* 1116 * MPSAFE 1117 */ 1118 int 1119 __sysctl(struct thread *td, struct sysctl_args *uap) 1120 { 1121 int error, name[CTL_MAXNAME]; 1122 size_t j; 1123 1124 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1125 return (EINVAL); 1126 1127 error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 1128 if (error) 1129 return (error); 1130 1131 mtx_lock(&Giant); 1132 1133 error = userland_sysctl(td, name, uap->namelen, 1134 uap->old, uap->oldlenp, 0, 1135 uap->new, uap->newlen, &j); 1136 if (error && error != ENOMEM) 1137 goto done2; 1138 if (uap->oldlenp) { 1139 int i = copyout(&j, uap->oldlenp, sizeof(j)); 1140 if (i) 1141 error = i; 1142 } 1143 done2: 1144 mtx_unlock(&Giant); 1145 return (error); 1146 } 1147 1148 /* 1149 * This is used from various compatibility syscalls too. That's why name 1150 * must be in kernel space. 1151 */ 1152 int 1153 userland_sysctl(struct thread *td, int *name, u_int namelen, void *old, 1154 size_t *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval) 1155 { 1156 int error = 0; 1157 struct sysctl_req req, req2; 1158 1159 bzero(&req, sizeof req); 1160 1161 req.td = td; 1162 1163 if (oldlenp) { 1164 if (inkernel) { 1165 req.oldlen = *oldlenp; 1166 } else { 1167 error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp)); 1168 if (error) 1169 return (error); 1170 } 1171 } 1172 1173 if (old) { 1174 if (!useracc(old, req.oldlen, VM_PROT_WRITE)) 1175 return (EFAULT); 1176 req.oldptr= old; 1177 } 1178 1179 if (new != NULL) { 1180 if (!useracc(new, req.newlen, VM_PROT_READ)) 1181 return (EFAULT); 1182 req.newlen = newlen; 1183 req.newptr = new; 1184 } 1185 1186 req.oldfunc = sysctl_old_user; 1187 req.newfunc = sysctl_new_user; 1188 req.lock = 1; 1189 1190 /* XXX this should probably be done in a general way */ 1191 while (memlock.sl_lock) { 1192 memlock.sl_want = 1; 1193 (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 1194 memlock.sl_locked++; 1195 } 1196 memlock.sl_lock = 1; 1197 1198 do { 1199 req2 = req; 1200 error = sysctl_root(0, name, namelen, &req2); 1201 } while (error == EAGAIN); 1202 1203 req = req2; 1204 if (req.lock == 2) 1205 vsunlock(req.oldptr, req.oldlen); 1206 1207 memlock.sl_lock = 0; 1208 1209 if (memlock.sl_want) { 1210 memlock.sl_want = 0; 1211 wakeup((caddr_t)&memlock); 1212 } 1213 1214 if (error && error != ENOMEM) 1215 return (error); 1216 1217 if (retval) { 1218 if (req.oldptr && req.oldidx > req.oldlen) 1219 *retval = req.oldlen; 1220 else 1221 *retval = req.oldidx; 1222 } 1223 return (error); 1224 } 1225 1226 #ifdef COMPAT_43 1227 #include <sys/socket.h> 1228 #include <vm/vm_param.h> 1229 1230 #define KINFO_PROC (0<<8) 1231 #define KINFO_RT (1<<8) 1232 #define KINFO_VNODE (2<<8) 1233 #define KINFO_FILE (3<<8) 1234 #define KINFO_METER (4<<8) 1235 #define KINFO_LOADAVG (5<<8) 1236 #define KINFO_CLOCKRATE (6<<8) 1237 1238 /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ 1239 #define KINFO_BSDI_SYSINFO (101<<8) 1240 1241 /* 1242 * XXX this is bloat, but I hope it's better here than on the potentially 1243 * limited kernel stack... -Peter 1244 */ 1245 1246 static struct { 1247 int bsdi_machine; /* "i386" on BSD/386 */ 1248 /* ^^^ this is an offset to the string, relative to the struct start */ 1249 char *pad0; 1250 long pad1; 1251 long pad2; 1252 long pad3; 1253 u_long pad4; 1254 u_long pad5; 1255 u_long pad6; 1256 1257 int bsdi_ostype; /* "BSD/386" on BSD/386 */ 1258 int bsdi_osrelease; /* "1.1" on BSD/386 */ 1259 long pad7; 1260 long pad8; 1261 char *pad9; 1262 1263 long pad10; 1264 long pad11; 1265 int pad12; 1266 long pad13; 1267 quad_t pad14; 1268 long pad15; 1269 1270 struct timeval pad16; 1271 /* we dont set this, because BSDI's uname used gethostname() instead */ 1272 int bsdi_hostname; /* hostname on BSD/386 */ 1273 1274 /* the actual string data is appended here */ 1275 1276 } bsdi_si; 1277 /* 1278 * this data is appended to the end of the bsdi_si structure during copyout. 1279 * The "char *" offsets are relative to the base of the bsdi_si struct. 1280 * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings 1281 * should not exceed the length of the buffer here... (or else!! :-) 1282 */ 1283 static char bsdi_strings[80]; /* It had better be less than this! */ 1284 1285 #ifndef _SYS_SYSPROTO_H_ 1286 struct getkerninfo_args { 1287 int op; 1288 char *where; 1289 size_t *size; 1290 int arg; 1291 }; 1292 #endif 1293 1294 /* 1295 * MPSAFE 1296 */ 1297 int 1298 ogetkerninfo(struct thread *td, struct getkerninfo_args *uap) 1299 { 1300 int error, name[6]; 1301 size_t size; 1302 u_int needed = 0; 1303 1304 mtx_lock(&Giant); 1305 1306 switch (uap->op & 0xff00) { 1307 1308 case KINFO_RT: 1309 name[0] = CTL_NET; 1310 name[1] = PF_ROUTE; 1311 name[2] = 0; 1312 name[3] = (uap->op & 0xff0000) >> 16; 1313 name[4] = uap->op & 0xff; 1314 name[5] = uap->arg; 1315 error = userland_sysctl(td, name, 6, uap->where, uap->size, 1316 0, 0, 0, &size); 1317 break; 1318 1319 case KINFO_VNODE: 1320 name[0] = CTL_KERN; 1321 name[1] = KERN_VNODE; 1322 error = userland_sysctl(td, name, 2, uap->where, uap->size, 1323 0, 0, 0, &size); 1324 break; 1325 1326 case KINFO_PROC: 1327 name[0] = CTL_KERN; 1328 name[1] = KERN_PROC; 1329 name[2] = uap->op & 0xff; 1330 name[3] = uap->arg; 1331 error = userland_sysctl(td, name, 4, uap->where, uap->size, 1332 0, 0, 0, &size); 1333 break; 1334 1335 case KINFO_FILE: 1336 name[0] = CTL_KERN; 1337 name[1] = KERN_FILE; 1338 error = userland_sysctl(td, name, 2, uap->where, uap->size, 1339 0, 0, 0, &size); 1340 break; 1341 1342 case KINFO_METER: 1343 name[0] = CTL_VM; 1344 name[1] = VM_METER; 1345 error = userland_sysctl(td, name, 2, uap->where, uap->size, 1346 0, 0, 0, &size); 1347 break; 1348 1349 case KINFO_LOADAVG: 1350 name[0] = CTL_VM; 1351 name[1] = VM_LOADAVG; 1352 error = userland_sysctl(td, name, 2, uap->where, uap->size, 1353 0, 0, 0, &size); 1354 break; 1355 1356 case KINFO_CLOCKRATE: 1357 name[0] = CTL_KERN; 1358 name[1] = KERN_CLOCKRATE; 1359 error = userland_sysctl(td, name, 2, uap->where, uap->size, 1360 0, 0, 0, &size); 1361 break; 1362 1363 case KINFO_BSDI_SYSINFO: { 1364 /* 1365 * this is pretty crude, but it's just enough for uname() 1366 * from BSDI's 1.x libc to work. 1367 * 1368 * *size gives the size of the buffer before the call, and 1369 * the amount of data copied after a successful call. 1370 * If successful, the return value is the amount of data 1371 * available, which can be larger than *size. 1372 * 1373 * BSDI's 2.x product apparently fails with ENOMEM if *size 1374 * is too small. 1375 */ 1376 1377 u_int left; 1378 char *s; 1379 1380 bzero((char *)&bsdi_si, sizeof(bsdi_si)); 1381 bzero(bsdi_strings, sizeof(bsdi_strings)); 1382 1383 s = bsdi_strings; 1384 1385 bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); 1386 strcpy(s, ostype); 1387 s += strlen(s) + 1; 1388 1389 bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); 1390 strcpy(s, osrelease); 1391 s += strlen(s) + 1; 1392 1393 bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); 1394 strcpy(s, machine); 1395 s += strlen(s) + 1; 1396 1397 needed = sizeof(bsdi_si) + (s - bsdi_strings); 1398 1399 if ((uap->where == NULL) || (uap->size == NULL)) { 1400 /* process is asking how much buffer to supply.. */ 1401 size = needed; 1402 error = 0; 1403 break; 1404 } 1405 1406 if ((error = copyin(uap->size, &size, sizeof(size))) != 0) 1407 break; 1408 1409 /* if too much buffer supplied, trim it down */ 1410 if (size > needed) 1411 size = needed; 1412 1413 /* how much of the buffer is remaining */ 1414 left = size; 1415 1416 if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) 1417 break; 1418 1419 /* is there any point in continuing? */ 1420 if (left > sizeof(bsdi_si)) { 1421 left -= sizeof(bsdi_si); 1422 error = copyout(&bsdi_strings, 1423 uap->where + sizeof(bsdi_si), left); 1424 } 1425 break; 1426 } 1427 1428 default: 1429 error = EOPNOTSUPP; 1430 break; 1431 } 1432 if (error == 0) { 1433 td->td_retval[0] = needed ? needed : size; 1434 if (uap->size) { 1435 error = copyout((caddr_t)&size, (caddr_t)uap->size, 1436 sizeof(size)); 1437 } 1438 } 1439 mtx_unlock(&Giant); 1440 return (error); 1441 } 1442 #endif /* COMPAT_43 */ 1443