1 /* $OpenBSD: kern_sysctl.c,v 1.92 2003/11/23 20:17:14 millert Exp $ */ 2 /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ 3 4 /*- 5 * Copyright (c) 1982, 1986, 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Mike Karels at Berkeley Software Design, Inc. 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. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 36 */ 37 38 /* 39 * sysctl system call. 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/malloc.h> 46 #include <sys/proc.h> 47 #include <sys/resourcevar.h> 48 #include <sys/file.h> 49 #include <sys/vnode.h> 50 #include <sys/unistd.h> 51 #include <sys/buf.h> 52 #include <sys/ioctl.h> 53 #include <sys/tty.h> 54 #include <sys/disklabel.h> 55 #include <sys/disk.h> 56 #include <uvm/uvm_extern.h> 57 #include <sys/sysctl.h> 58 #include <sys/msgbuf.h> 59 #include <sys/dkstat.h> 60 #include <sys/vmmeter.h> 61 #include <sys/namei.h> 62 #include <sys/exec.h> 63 #include <sys/mbuf.h> 64 #include <sys/sensors.h> 65 66 #include <sys/mount.h> 67 #include <sys/syscallargs.h> 68 #include <dev/rndvar.h> 69 70 #ifdef DDB 71 #include <ddb/db_var.h> 72 #endif 73 74 #ifdef SYSVMSG 75 #include <sys/msg.h> 76 #endif 77 #ifdef SYSVSEM 78 #include <sys/sem.h> 79 #endif 80 #ifdef SYSVSHM 81 #include <sys/shm.h> 82 #endif 83 84 extern struct forkstat forkstat; 85 extern struct nchstats nchstats; 86 extern int nselcoll, fscale; 87 extern struct disklist_head disklist; 88 extern fixpt_t ccpu; 89 extern long numvnodes; 90 91 int sysctl_diskinit(int, struct proc *); 92 int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *); 93 int sysctl_intrcnt(int *, u_int, void *, size_t *); 94 int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t); 95 int sysctl_emul(int *, u_int, void *, size_t *, void *, size_t); 96 97 /* 98 * Lock to avoid too many processes vslocking a large amount of memory 99 * at the same time. 100 */ 101 struct lock sysctl_lock, sysctl_disklock; 102 103 #if defined(KMEMSTATS) || defined(DIAGNOSTIC) || defined(FFS_SOFTUPDATES) 104 struct lock sysctl_kmemlock; 105 #endif 106 107 void 108 sysctl_init() 109 { 110 lockinit(&sysctl_lock, PLOCK|PCATCH, "sysctl", 0, 0); 111 lockinit(&sysctl_disklock, PLOCK|PCATCH, "sysctl_disklock", 0, 0); 112 113 #if defined(KMEMSTATS) || defined(DIAGNOSTIC) || defined(FFS_SOFTUPDATES) 114 lockinit(&sysctl_kmemlock, PLOCK|PCATCH, "sysctl_kmemlock", 0, 0); 115 #endif 116 } 117 118 int 119 sys___sysctl(p, v, retval) 120 struct proc *p; 121 void *v; 122 register_t *retval; 123 { 124 register struct sys___sysctl_args /* { 125 syscallarg(int *) name; 126 syscallarg(u_int) namelen; 127 syscallarg(void *) old; 128 syscallarg(size_t *) oldlenp; 129 syscallarg(void *) new; 130 syscallarg(size_t) newlen; 131 } */ *uap = v; 132 int error, dolock = 1; 133 size_t savelen = 0, oldlen = 0; 134 sysctlfn *fn; 135 int name[CTL_MAXNAME]; 136 137 if (SCARG(uap, new) != NULL && 138 (error = suser(p, 0))) 139 return (error); 140 /* 141 * all top-level sysctl names are non-terminal 142 */ 143 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2) 144 return (EINVAL); 145 error = copyin(SCARG(uap, name), name, 146 SCARG(uap, namelen) * sizeof(int)); 147 if (error) 148 return (error); 149 150 switch (name[0]) { 151 case CTL_KERN: 152 fn = kern_sysctl; 153 if (name[1] == KERN_VNODE) /* XXX */ 154 dolock = 0; 155 break; 156 case CTL_HW: 157 fn = hw_sysctl; 158 break; 159 case CTL_VM: 160 fn = uvm_sysctl; 161 break; 162 case CTL_NET: 163 fn = net_sysctl; 164 break; 165 case CTL_FS: 166 fn = fs_sysctl; 167 break; 168 case CTL_VFS: 169 fn = vfs_sysctl; 170 break; 171 case CTL_MACHDEP: 172 fn = cpu_sysctl; 173 break; 174 #ifdef DEBUG 175 case CTL_DEBUG: 176 fn = debug_sysctl; 177 break; 178 #endif 179 #ifdef DDB 180 case CTL_DDB: 181 fn = ddb_sysctl; 182 break; 183 #endif 184 default: 185 return (EOPNOTSUPP); 186 } 187 188 if (SCARG(uap, oldlenp) && 189 (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen)))) 190 return (error); 191 if (SCARG(uap, old) != NULL) { 192 if ((error = lockmgr(&sysctl_lock, LK_EXCLUSIVE, NULL, p)) != 0) 193 return (error); 194 if (dolock) { 195 error = uvm_vslock(p, SCARG(uap, old), oldlen, 196 VM_PROT_READ|VM_PROT_WRITE); 197 if (error) { 198 lockmgr(&sysctl_lock, LK_RELEASE, NULL, p); 199 return (error); 200 } 201 } 202 savelen = oldlen; 203 } 204 error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old), 205 &oldlen, SCARG(uap, new), SCARG(uap, newlen), p); 206 if (SCARG(uap, old) != NULL) { 207 if (dolock) 208 uvm_vsunlock(p, SCARG(uap, old), savelen); 209 lockmgr(&sysctl_lock, LK_RELEASE, NULL, p); 210 } 211 if (error) 212 return (error); 213 if (SCARG(uap, oldlenp)) 214 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen)); 215 return (error); 216 } 217 218 /* 219 * Attributes stored in the kernel. 220 */ 221 char hostname[MAXHOSTNAMELEN]; 222 int hostnamelen; 223 char domainname[MAXHOSTNAMELEN]; 224 int domainnamelen; 225 long hostid; 226 char *disknames = NULL; 227 struct diskstats *diskstats = NULL; 228 #ifdef INSECURE 229 int securelevel = -1; 230 #else 231 int securelevel; 232 #endif 233 234 /* 235 * kernel related system variables. 236 */ 237 int 238 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 239 int *name; 240 u_int namelen; 241 void *oldp; 242 size_t *oldlenp; 243 void *newp; 244 size_t newlen; 245 struct proc *p; 246 { 247 int error, level, inthostid, stackgap; 248 extern int somaxconn, sominconn; 249 extern int usermount, nosuidcoredump; 250 extern long cp_time[CPUSTATES]; 251 extern int stackgap_random; 252 #ifdef CRYPTO 253 extern int usercrypto; 254 extern int userasymcrypto; 255 extern int cryptodevallowsoft; 256 #endif 257 258 /* all sysctl names at this level are terminal except a ton of them */ 259 if (namelen != 1) { 260 switch (name[0]) { 261 case KERN_PROC: 262 case KERN_PROF: 263 case KERN_MALLOCSTATS: 264 case KERN_TTY: 265 case KERN_POOL: 266 case KERN_PROC_ARGS: 267 case KERN_SYSVIPC_INFO: 268 case KERN_SEMINFO: 269 case KERN_SHMINFO: 270 case KERN_INTRCNT: 271 case KERN_WATCHDOG: 272 case KERN_EMUL: 273 break; 274 default: 275 return (ENOTDIR); /* overloaded */ 276 } 277 } 278 279 switch (name[0]) { 280 case KERN_OSTYPE: 281 return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 282 case KERN_OSRELEASE: 283 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 284 case KERN_OSREV: 285 return (sysctl_rdint(oldp, oldlenp, newp, OpenBSD)); 286 case KERN_OSVERSION: 287 return (sysctl_rdstring(oldp, oldlenp, newp, osversion)); 288 case KERN_VERSION: 289 return (sysctl_rdstring(oldp, oldlenp, newp, version)); 290 case KERN_MAXVNODES: 291 return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes)); 292 case KERN_MAXPROC: 293 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 294 case KERN_MAXFILES: 295 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 296 case KERN_NFILES: 297 return (sysctl_rdint(oldp, oldlenp, newp, nfiles)); 298 case KERN_TTYCOUNT: 299 return (sysctl_rdint(oldp, oldlenp, newp, tty_count)); 300 case KERN_NUMVNODES: 301 return (sysctl_rdint(oldp, oldlenp, newp, numvnodes)); 302 case KERN_ARGMAX: 303 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 304 case KERN_NSELCOLL: 305 return (sysctl_rdint(oldp, oldlenp, newp, nselcoll)); 306 case KERN_SECURELVL: 307 level = securelevel; 308 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 309 newp == NULL) 310 return (error); 311 if ((securelevel > 0 || level < -1) && 312 level < securelevel && p->p_pid != 1) 313 return (EPERM); 314 securelevel = level; 315 return (0); 316 case KERN_HOSTNAME: 317 error = sysctl_tstring(oldp, oldlenp, newp, newlen, 318 hostname, sizeof(hostname)); 319 if (newp && !error) 320 hostnamelen = newlen; 321 return (error); 322 case KERN_DOMAINNAME: 323 error = sysctl_tstring(oldp, oldlenp, newp, newlen, 324 domainname, sizeof(domainname)); 325 if (newp && !error) 326 domainnamelen = newlen; 327 return (error); 328 case KERN_HOSTID: 329 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ 330 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); 331 hostid = inthostid; 332 return (error); 333 case KERN_CLOCKRATE: 334 return (sysctl_clockrate(oldp, oldlenp)); 335 case KERN_BOOTTIME: 336 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, 337 sizeof(struct timeval))); 338 case KERN_VNODE: 339 return (sysctl_vnode(oldp, oldlenp, p)); 340 case KERN_PROC: 341 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 342 case KERN_PROC_ARGS: 343 return (sysctl_proc_args(name + 1, namelen - 1, oldp, oldlenp, 344 p)); 345 case KERN_FILE: 346 return (sysctl_file(oldp, oldlenp)); 347 case KERN_MBSTAT: 348 return (sysctl_rdstruct(oldp, oldlenp, newp, &mbstat, 349 sizeof(mbstat))); 350 #ifdef GPROF 351 case KERN_PROF: 352 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 353 newp, newlen)); 354 #endif 355 case KERN_POSIX1: 356 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 357 case KERN_NGROUPS: 358 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); 359 case KERN_JOB_CONTROL: 360 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 361 case KERN_SAVED_IDS: 362 #ifdef _POSIX_SAVED_IDS 363 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 364 #else 365 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 366 #endif 367 case KERN_MAXPARTITIONS: 368 return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS)); 369 case KERN_RAWPARTITION: 370 return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART)); 371 case KERN_SOMAXCONN: 372 return (sysctl_int(oldp, oldlenp, newp, newlen, &somaxconn)); 373 case KERN_SOMINCONN: 374 return (sysctl_int(oldp, oldlenp, newp, newlen, &sominconn)); 375 case KERN_USERMOUNT: 376 return (sysctl_int(oldp, oldlenp, newp, newlen, &usermount)); 377 case KERN_RND: 378 return (sysctl_rdstruct(oldp, oldlenp, newp, &rndstats, 379 sizeof(rndstats))); 380 case KERN_ARND: 381 return (sysctl_rdint(oldp, oldlenp, newp, arc4random())); 382 case KERN_NOSUIDCOREDUMP: 383 return (sysctl_int(oldp, oldlenp, newp, newlen, &nosuidcoredump)); 384 case KERN_FSYNC: 385 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 386 case KERN_SYSVMSG: 387 #ifdef SYSVMSG 388 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 389 #else 390 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 391 #endif 392 case KERN_SYSVSEM: 393 #ifdef SYSVSEM 394 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 395 #else 396 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 397 #endif 398 case KERN_SYSVSHM: 399 #ifdef SYSVSHM 400 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 401 #else 402 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 403 #endif 404 case KERN_MSGBUFSIZE: 405 /* 406 * deal with cases where the message buffer has 407 * become corrupted. 408 */ 409 if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC) 410 return (ENXIO); 411 return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs)); 412 case KERN_MSGBUF: 413 /* see note above */ 414 if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC) 415 return (ENXIO); 416 return (sysctl_rdstruct(oldp, oldlenp, newp, msgbufp, 417 msgbufp->msg_bufs + offsetof(struct msgbuf, msg_bufc))); 418 case KERN_MALLOCSTATS: 419 return (sysctl_malloc(name + 1, namelen - 1, oldp, oldlenp, 420 newp, newlen, p)); 421 case KERN_CPTIME: 422 return (sysctl_rdstruct(oldp, oldlenp, newp, &cp_time, 423 sizeof(cp_time))); 424 case KERN_NCHSTATS: 425 return (sysctl_rdstruct(oldp, oldlenp, newp, &nchstats, 426 sizeof(struct nchstats))); 427 case KERN_FORKSTAT: 428 return (sysctl_rdstruct(oldp, oldlenp, newp, &forkstat, 429 sizeof(struct forkstat))); 430 case KERN_TTY: 431 return (sysctl_tty(name + 1, namelen - 1, oldp, oldlenp, 432 newp, newlen)); 433 case KERN_FSCALE: 434 return (sysctl_rdint(oldp, oldlenp, newp, fscale)); 435 case KERN_CCPU: 436 return (sysctl_rdint(oldp, oldlenp, newp, ccpu)); 437 case KERN_NPROCS: 438 return (sysctl_rdint(oldp, oldlenp, newp, nprocs)); 439 case KERN_POOL: 440 return (sysctl_dopool(name + 1, namelen - 1, oldp, oldlenp)); 441 case KERN_STACKGAPRANDOM: 442 stackgap = stackgap_random; 443 error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap); 444 if (error) 445 return (error); 446 /* 447 * Safety harness. 448 */ 449 if ((stackgap < ALIGNBYTES && stackgap != 0) || 450 !powerof2(stackgap) || stackgap >= 256 * 1024 * 1024) 451 return (EINVAL); 452 stackgap_random = stackgap; 453 return (0); 454 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 455 case KERN_SYSVIPC_INFO: 456 return (sysctl_sysvipc(name + 1, namelen - 1, oldp, oldlenp)); 457 #endif 458 #ifdef CRYPTO 459 case KERN_USERCRYPTO: 460 return (sysctl_int(oldp, oldlenp, newp, newlen, &usercrypto)); 461 case KERN_USERASYMCRYPTO: 462 return (sysctl_int(oldp, oldlenp, newp, newlen, 463 &userasymcrypto)); 464 case KERN_CRYPTODEVALLOWSOFT: 465 return (sysctl_int(oldp, oldlenp, newp, newlen, 466 &cryptodevallowsoft)); 467 #endif 468 case KERN_SPLASSERT: 469 return (sysctl_int(oldp, oldlenp, newp, newlen, 470 &splassert_ctl)); 471 #ifdef SYSVSEM 472 case KERN_SEMINFO: 473 return (sysctl_sysvsem(name + 1, namelen - 1, oldp, oldlenp, 474 newp, newlen)); 475 #endif 476 #ifdef SYSVSHM 477 case KERN_SHMINFO: 478 return (sysctl_sysvshm(name + 1, namelen - 1, oldp, oldlenp, 479 newp, newlen)); 480 #endif 481 case KERN_INTRCNT: 482 return (sysctl_intrcnt(name + 1, namelen - 1, oldp, oldlenp)); 483 case KERN_WATCHDOG: 484 return (sysctl_wdog(name + 1, namelen - 1, oldp, oldlenp, 485 newp, newlen)); 486 case KERN_EMUL: 487 return (sysctl_emul(name + 1, namelen - 1, oldp, oldlenp, 488 newp, newlen)); 489 default: 490 return (EOPNOTSUPP); 491 } 492 /* NOTREACHED */ 493 } 494 495 /* 496 * hardware related system variables. 497 */ 498 int 499 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 500 int *name; 501 u_int namelen; 502 void *oldp; 503 size_t *oldlenp; 504 void *newp; 505 size_t newlen; 506 struct proc *p; 507 { 508 extern char machine[], cpu_model[]; 509 int err; 510 511 /* all sysctl names at this level except sensors are terminal */ 512 if (name[0] != HW_SENSORS && namelen != 1) 513 return (ENOTDIR); /* overloaded */ 514 515 switch (name[0]) { 516 case HW_MACHINE: 517 return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 518 case HW_MODEL: 519 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 520 case HW_NCPU: 521 return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ 522 case HW_BYTEORDER: 523 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 524 case HW_PHYSMEM: 525 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 526 case HW_USERMEM: 527 return (sysctl_rdint(oldp, oldlenp, newp, 528 ctob(physmem - uvmexp.wired))); 529 case HW_PAGESIZE: 530 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 531 case HW_DISKNAMES: 532 err = sysctl_diskinit(0, p); 533 if (err) 534 return err; 535 if (disknames) 536 return (sysctl_rdstring(oldp, oldlenp, newp, 537 disknames)); 538 else 539 return (sysctl_rdstring(oldp, oldlenp, newp, "")); 540 case HW_DISKSTATS: 541 err = sysctl_diskinit(1, p); 542 if (err) 543 return err; 544 return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats, 545 disk_count * sizeof(struct diskstats))); 546 case HW_DISKCOUNT: 547 return (sysctl_rdint(oldp, oldlenp, newp, disk_count)); 548 case HW_SENSORS: 549 return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp, 550 newp, newlen)); 551 default: 552 return (EOPNOTSUPP); 553 } 554 /* NOTREACHED */ 555 } 556 557 #ifdef DEBUG 558 /* 559 * Debugging related system variables. 560 */ 561 extern struct ctldebug debug0, debug1; 562 struct ctldebug debug2, debug3, debug4; 563 struct ctldebug debug5, debug6, debug7, debug8, debug9; 564 struct ctldebug debug10, debug11, debug12, debug13, debug14; 565 struct ctldebug debug15, debug16, debug17, debug18, debug19; 566 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 567 &debug0, &debug1, &debug2, &debug3, &debug4, 568 &debug5, &debug6, &debug7, &debug8, &debug9, 569 &debug10, &debug11, &debug12, &debug13, &debug14, 570 &debug15, &debug16, &debug17, &debug18, &debug19, 571 }; 572 int 573 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 574 int *name; 575 u_int namelen; 576 void *oldp; 577 size_t *oldlenp; 578 void *newp; 579 size_t newlen; 580 struct proc *p; 581 { 582 struct ctldebug *cdp; 583 584 /* all sysctl names at this level are name and field */ 585 if (namelen != 2) 586 return (ENOTDIR); /* overloaded */ 587 cdp = debugvars[name[0]]; 588 if (cdp->debugname == 0) 589 return (EOPNOTSUPP); 590 switch (name[1]) { 591 case CTL_DEBUG_NAME: 592 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 593 case CTL_DEBUG_VALUE: 594 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 595 default: 596 return (EOPNOTSUPP); 597 } 598 /* NOTREACHED */ 599 } 600 #endif /* DEBUG */ 601 602 /* 603 * Validate parameters and get old / set new parameters 604 * for an integer-valued sysctl function. 605 */ 606 int 607 sysctl_int(oldp, oldlenp, newp, newlen, valp) 608 void *oldp; 609 size_t *oldlenp; 610 void *newp; 611 size_t newlen; 612 int *valp; 613 { 614 int error = 0; 615 616 if (oldp && *oldlenp < sizeof(int)) 617 return (ENOMEM); 618 if (newp && newlen != sizeof(int)) 619 return (EINVAL); 620 *oldlenp = sizeof(int); 621 if (oldp) 622 error = copyout(valp, oldp, sizeof(int)); 623 if (error == 0 && newp) 624 error = copyin(newp, valp, sizeof(int)); 625 return (error); 626 } 627 628 /* 629 * As above, but read-only. 630 */ 631 int 632 sysctl_rdint(oldp, oldlenp, newp, val) 633 void *oldp; 634 size_t *oldlenp; 635 void *newp; 636 int val; 637 { 638 int error = 0; 639 640 if (oldp && *oldlenp < sizeof(int)) 641 return (ENOMEM); 642 if (newp) 643 return (EPERM); 644 *oldlenp = sizeof(int); 645 if (oldp) 646 error = copyout((caddr_t)&val, oldp, sizeof(int)); 647 return (error); 648 } 649 650 /* 651 * Validate parameters and get old / set new parameters 652 * for an integer-valued sysctl function. 653 */ 654 int 655 sysctl_quad(oldp, oldlenp, newp, newlen, valp) 656 void *oldp; 657 size_t *oldlenp; 658 void *newp; 659 size_t newlen; 660 int64_t *valp; 661 { 662 int error = 0; 663 664 if (oldp && *oldlenp < sizeof(int64_t)) 665 return (ENOMEM); 666 if (newp && newlen != sizeof(int64_t)) 667 return (EINVAL); 668 *oldlenp = sizeof(int64_t); 669 if (oldp) 670 error = copyout(valp, oldp, sizeof(int64_t)); 671 if (error == 0 && newp) 672 error = copyin(newp, valp, sizeof(int64_t)); 673 return (error); 674 } 675 676 /* 677 * As above, but read-only. 678 */ 679 int 680 sysctl_rdquad(oldp, oldlenp, newp, val) 681 void *oldp; 682 size_t *oldlenp; 683 void *newp; 684 int64_t val; 685 { 686 int error = 0; 687 688 if (oldp && *oldlenp < sizeof(int64_t)) 689 return (ENOMEM); 690 if (newp) 691 return (EPERM); 692 *oldlenp = sizeof(int64_t); 693 if (oldp) 694 error = copyout((caddr_t)&val, oldp, sizeof(int64_t)); 695 return (error); 696 } 697 698 /* 699 * Validate parameters and get old / set new parameters 700 * for a string-valued sysctl function. 701 */ 702 int 703 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 704 void *oldp; 705 size_t *oldlenp; 706 void *newp; 707 size_t newlen; 708 char *str; 709 int maxlen; 710 { 711 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0); 712 } 713 714 int 715 sysctl_tstring(oldp, oldlenp, newp, newlen, str, maxlen) 716 void *oldp; 717 size_t *oldlenp; 718 void *newp; 719 size_t newlen; 720 char *str; 721 int maxlen; 722 { 723 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1); 724 } 725 726 int 727 sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, trunc) 728 void *oldp; 729 size_t *oldlenp; 730 void *newp; 731 size_t newlen; 732 char *str; 733 int maxlen; 734 int trunc; 735 { 736 int len, error = 0; 737 char c; 738 739 len = strlen(str) + 1; 740 if (oldp && *oldlenp < len) { 741 if (trunc == 0 || *oldlenp == 0) 742 return (ENOMEM); 743 } 744 if (newp && newlen >= maxlen) 745 return (EINVAL); 746 if (oldp) { 747 if (trunc && *oldlenp < len) { 748 /* save & zap NUL terminator while copying */ 749 c = str[*oldlenp-1]; 750 str[*oldlenp-1] = '\0'; 751 error = copyout(str, oldp, *oldlenp); 752 str[*oldlenp-1] = c; 753 } else { 754 *oldlenp = len; 755 error = copyout(str, oldp, len); 756 } 757 } 758 if (error == 0 && newp) { 759 error = copyin(newp, str, newlen); 760 str[newlen] = 0; 761 } 762 return (error); 763 } 764 765 /* 766 * As above, but read-only. 767 */ 768 int 769 sysctl_rdstring(oldp, oldlenp, newp, str) 770 void *oldp; 771 size_t *oldlenp; 772 void *newp; 773 const char *str; 774 { 775 int len, error = 0; 776 777 len = strlen(str) + 1; 778 if (oldp && *oldlenp < len) 779 return (ENOMEM); 780 if (newp) 781 return (EPERM); 782 *oldlenp = len; 783 if (oldp) 784 error = copyout(str, oldp, len); 785 return (error); 786 } 787 788 /* 789 * Validate parameters and get old / set new parameters 790 * for a structure oriented sysctl function. 791 */ 792 int 793 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 794 void *oldp; 795 size_t *oldlenp; 796 void *newp; 797 size_t newlen; 798 void *sp; 799 int len; 800 { 801 int error = 0; 802 803 if (oldp && *oldlenp < len) 804 return (ENOMEM); 805 if (newp && newlen > len) 806 return (EINVAL); 807 if (oldp) { 808 *oldlenp = len; 809 error = copyout(sp, oldp, len); 810 } 811 if (error == 0 && newp) 812 error = copyin(newp, sp, len); 813 return (error); 814 } 815 816 /* 817 * Validate parameters and get old parameters 818 * for a structure oriented sysctl function. 819 */ 820 int 821 sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 822 void *oldp; 823 size_t *oldlenp; 824 void *newp; 825 const void *sp; 826 int len; 827 { 828 int error = 0; 829 830 if (oldp && *oldlenp < len) 831 return (ENOMEM); 832 if (newp) 833 return (EPERM); 834 *oldlenp = len; 835 if (oldp) 836 error = copyout(sp, oldp, len); 837 return (error); 838 } 839 840 /* 841 * Get file structures. 842 */ 843 int 844 sysctl_file(where, sizep) 845 char *where; 846 size_t *sizep; 847 { 848 int buflen, error; 849 struct file *fp; 850 char *start = where; 851 852 buflen = *sizep; 853 if (where == NULL) { 854 /* 855 * overestimate by 10 files 856 */ 857 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 858 return (0); 859 } 860 861 /* 862 * first copyout filehead 863 */ 864 if (buflen < sizeof(filehead)) { 865 *sizep = 0; 866 return (0); 867 } 868 error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 869 if (error) 870 return (error); 871 buflen -= sizeof(filehead); 872 where += sizeof(filehead); 873 874 /* 875 * followed by an array of file structures 876 */ 877 LIST_FOREACH(fp, &filehead, f_list) { 878 if (buflen < sizeof(struct file)) { 879 *sizep = where - start; 880 return (ENOMEM); 881 } 882 error = copyout((caddr_t)fp, where, sizeof (struct file)); 883 if (error) 884 return (error); 885 buflen -= sizeof(struct file); 886 where += sizeof(struct file); 887 } 888 *sizep = where - start; 889 return (0); 890 } 891 892 /* 893 * try over estimating by 5 procs 894 */ 895 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 896 897 int 898 sysctl_doproc(name, namelen, where, sizep) 899 int *name; 900 u_int namelen; 901 char *where; 902 size_t *sizep; 903 { 904 register struct proc *p; 905 register struct kinfo_proc *dp = (struct kinfo_proc *)where; 906 register int needed = 0; 907 int buflen = where != NULL ? *sizep : 0; 908 int doingzomb; 909 struct eproc eproc; 910 int error = 0; 911 912 if (namelen != 2 && !(namelen == 1 && 913 (name[0] == KERN_PROC_ALL || name[0] == KERN_PROC_KTHREAD))) 914 return (EINVAL); 915 p = LIST_FIRST(&allproc); 916 doingzomb = 0; 917 again: 918 for (; p != 0; p = LIST_NEXT(p, p_list)) { 919 /* 920 * Skip embryonic processes. 921 */ 922 if (p->p_stat == SIDL) 923 continue; 924 /* 925 * TODO - make more efficient (see notes below). 926 * do by session. 927 */ 928 switch (name[0]) { 929 930 case KERN_PROC_PID: 931 /* could do this with just a lookup */ 932 if (p->p_pid != (pid_t)name[1]) 933 continue; 934 break; 935 936 case KERN_PROC_PGRP: 937 /* could do this by traversing pgrp */ 938 if (p->p_pgrp->pg_id != (pid_t)name[1]) 939 continue; 940 break; 941 942 case KERN_PROC_TTY: 943 if ((p->p_flag & P_CONTROLT) == 0 || 944 p->p_session->s_ttyp == NULL || 945 p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 946 continue; 947 break; 948 949 case KERN_PROC_UID: 950 if (p->p_ucred->cr_uid != (uid_t)name[1]) 951 continue; 952 break; 953 954 case KERN_PROC_RUID: 955 if (p->p_cred->p_ruid != (uid_t)name[1]) 956 continue; 957 break; 958 959 case KERN_PROC_ALL: 960 if (p->p_flag & P_SYSTEM) 961 continue; 962 break; 963 } 964 if (buflen >= sizeof(struct kinfo_proc)) { 965 fill_eproc(p, &eproc); 966 error = copyout((caddr_t)p, &dp->kp_proc, 967 sizeof(struct proc)); 968 if (error) 969 return (error); 970 error = copyout((caddr_t)&eproc, &dp->kp_eproc, 971 sizeof(eproc)); 972 if (error) 973 return (error); 974 dp++; 975 buflen -= sizeof(struct kinfo_proc); 976 } 977 needed += sizeof(struct kinfo_proc); 978 } 979 if (doingzomb == 0) { 980 p = LIST_FIRST(&zombproc); 981 doingzomb++; 982 goto again; 983 } 984 if (where != NULL) { 985 *sizep = (caddr_t)dp - where; 986 if (needed > *sizep) 987 return (ENOMEM); 988 } else { 989 needed += KERN_PROCSLOP; 990 *sizep = needed; 991 } 992 return (0); 993 } 994 995 /* 996 * Fill in an eproc structure for the specified process. 997 */ 998 void 999 fill_eproc(struct proc *p, struct eproc *ep) 1000 { 1001 struct tty *tp; 1002 1003 ep->e_paddr = p; 1004 ep->e_sess = p->p_pgrp->pg_session; 1005 ep->e_pcred = *p->p_cred; 1006 ep->e_ucred = *p->p_ucred; 1007 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 1008 ep->e_vm.vm_rssize = 0; 1009 ep->e_vm.vm_tsize = 0; 1010 ep->e_vm.vm_dsize = 0; 1011 ep->e_vm.vm_ssize = 0; 1012 bzero(&ep->e_pstats, sizeof(ep->e_pstats)); 1013 ep->e_pstats_valid = 0; 1014 } else { 1015 struct vmspace *vm = p->p_vmspace; 1016 1017 PHOLD(p); /* need for pstats */ 1018 ep->e_vm.vm_rssize = vm_resident_count(vm); 1019 ep->e_vm.vm_tsize = vm->vm_tsize; 1020 ep->e_vm.vm_dsize = vm->vm_dsize; 1021 ep->e_vm.vm_ssize = vm->vm_ssize; 1022 ep->e_pstats = *p->p_stats; 1023 ep->e_pstats_valid = 1; 1024 PRELE(p); 1025 } 1026 if (p->p_pptr) 1027 ep->e_ppid = p->p_pptr->p_pid; 1028 else 1029 ep->e_ppid = 0; 1030 ep->e_pgid = p->p_pgrp->pg_id; 1031 ep->e_jobc = p->p_pgrp->pg_jobc; 1032 if ((p->p_flag & P_CONTROLT) && 1033 (tp = ep->e_sess->s_ttyp)) { 1034 ep->e_tdev = tp->t_dev; 1035 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1036 ep->e_tsess = tp->t_session; 1037 } else 1038 ep->e_tdev = NODEV; 1039 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 1040 if (SESS_LEADER(p)) 1041 ep->e_flag |= EPROC_SLEADER; 1042 strncpy(ep->e_wmesg, p->p_wmesg ? p->p_wmesg : "", WMESGLEN); 1043 ep->e_wmesg[WMESGLEN] = '\0'; 1044 ep->e_xsize = ep->e_xrssize = 0; 1045 ep->e_xccount = ep->e_xswrss = 0; 1046 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME-1); 1047 ep->e_login[MAXLOGNAME-1] = '\0'; 1048 strncpy(ep->e_emul, p->p_emul->e_name, EMULNAMELEN); 1049 ep->e_emul[EMULNAMELEN] = '\0'; 1050 ep->e_maxrss = p->p_rlimit ? p->p_rlimit[RLIMIT_RSS].rlim_cur : 0; 1051 } 1052 1053 int 1054 sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1055 struct proc *cp) 1056 { 1057 struct proc *vp; 1058 pid_t pid; 1059 int op; 1060 struct ps_strings pss; 1061 struct iovec iov; 1062 struct uio uio; 1063 int error; 1064 size_t limit; 1065 int cnt; 1066 char **rargv, **vargv; /* reader vs. victim */ 1067 char *rarg, *varg; 1068 char *buf; 1069 1070 if (namelen > 2) 1071 return (ENOTDIR); 1072 if (namelen < 2) 1073 return (EINVAL); 1074 1075 pid = name[0]; 1076 op = name[1]; 1077 1078 switch (op) { 1079 case KERN_PROC_ARGV: 1080 case KERN_PROC_NARGV: 1081 case KERN_PROC_ENV: 1082 case KERN_PROC_NENV: 1083 break; 1084 default: 1085 return (EOPNOTSUPP); 1086 } 1087 1088 if ((vp = pfind(pid)) == NULL) 1089 return (ESRCH); 1090 1091 if (P_ZOMBIE(vp) || (vp->p_flag & P_SYSTEM)) 1092 return (EINVAL); 1093 1094 /* Exiting - don't bother, it will be gone soon anyway */ 1095 if ((vp->p_flag & P_WEXIT)) 1096 return (ESRCH); 1097 1098 /* Execing - danger. */ 1099 if ((vp->p_flag & P_INEXEC)) 1100 return (EBUSY); 1101 1102 vp->p_vmspace->vm_refcnt++; /* XXX */ 1103 buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 1104 1105 iov.iov_base = &pss; 1106 iov.iov_len = sizeof(pss); 1107 uio.uio_iov = &iov; 1108 uio.uio_iovcnt = 1; 1109 uio.uio_offset = (off_t)PS_STRINGS; 1110 uio.uio_resid = sizeof(pss); 1111 uio.uio_segflg = UIO_SYSSPACE; 1112 uio.uio_rw = UIO_READ; 1113 uio.uio_procp = cp; 1114 1115 if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0) 1116 goto out; 1117 1118 if (op == KERN_PROC_NARGV) { 1119 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr); 1120 goto out; 1121 } 1122 if (op == KERN_PROC_NENV) { 1123 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr); 1124 goto out; 1125 } 1126 1127 if (op == KERN_PROC_ARGV) { 1128 cnt = pss.ps_nargvstr; 1129 vargv = pss.ps_argvstr; 1130 } else { 1131 cnt = pss.ps_nenvstr; 1132 vargv = pss.ps_envstr; 1133 } 1134 1135 /* -1 to have space for a terminating NUL */ 1136 limit = *oldlenp - 1; 1137 *oldlenp = 0; 1138 1139 if (limit > 8 * PAGE_SIZE) { 1140 /* Don't allow a denial of service. */ 1141 error = E2BIG; 1142 goto out; 1143 } 1144 1145 rargv = oldp; 1146 1147 /* 1148 * *oldlenp - number of bytes copied out into readers buffer. 1149 * limit - maximal number of bytes allowed into readers buffer. 1150 * rarg - pointer into readers buffer where next arg will be stored. 1151 * rargv - pointer into readers buffer where the next rarg pointer 1152 * will be stored. 1153 * vargv - pointer into victim address space where the next argument 1154 * will be read. 1155 */ 1156 1157 /* space for cnt pointers and a NULL */ 1158 rarg = (char *)(rargv + cnt + 1); 1159 *oldlenp += (cnt + 1) * sizeof(char **); 1160 1161 while (cnt > 0 && *oldlenp < limit) { 1162 size_t len, vstrlen; 1163 1164 /* Write to readers argv */ 1165 if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0) 1166 goto out; 1167 1168 /* read the victim argv */ 1169 iov.iov_base = &varg; 1170 iov.iov_len = sizeof(varg); 1171 uio.uio_iov = &iov; 1172 uio.uio_iovcnt = 1; 1173 uio.uio_offset = (off_t)(vaddr_t)vargv; 1174 uio.uio_resid = sizeof(varg); 1175 uio.uio_segflg = UIO_SYSSPACE; 1176 uio.uio_rw = UIO_READ; 1177 uio.uio_procp = cp; 1178 if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0) 1179 goto out; 1180 1181 if (varg == NULL) 1182 break; 1183 1184 /* 1185 * read the victim arg. We must jump through hoops to avoid 1186 * crossing a page boundary too much and returning an error. 1187 */ 1188 more: 1189 len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK); 1190 /* leave space for the terminating NUL */ 1191 iov.iov_base = buf; 1192 iov.iov_len = len; 1193 uio.uio_iov = &iov; 1194 uio.uio_iovcnt = 1; 1195 uio.uio_offset = (off_t)(vaddr_t)varg; 1196 uio.uio_resid = len; 1197 uio.uio_segflg = UIO_SYSSPACE; 1198 uio.uio_rw = UIO_READ; 1199 uio.uio_procp = cp; 1200 if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0) 1201 goto out; 1202 1203 for (vstrlen = 0; vstrlen < len; vstrlen++) { 1204 if (buf[vstrlen] == '\0') 1205 break; 1206 } 1207 1208 /* Don't overflow readers buffer. */ 1209 if (*oldlenp + vstrlen + 1 >= limit) { 1210 error = ENOMEM; 1211 goto out; 1212 } 1213 1214 if ((error = copyout(buf, rarg, vstrlen)) != 0) 1215 goto out; 1216 1217 *oldlenp += vstrlen; 1218 rarg += vstrlen; 1219 1220 /* The string didn't end in this page? */ 1221 if (vstrlen == len) { 1222 varg += vstrlen; 1223 goto more; 1224 } 1225 1226 /* End of string. Terminate it with a NUL */ 1227 buf[0] = '\0'; 1228 if ((error = copyout(buf, rarg, 1)) != 0) 1229 goto out; 1230 *oldlenp += 1; 1231 rarg += 1; 1232 1233 vargv++; 1234 rargv++; 1235 cnt--; 1236 } 1237 1238 if (*oldlenp >= limit) { 1239 error = ENOMEM; 1240 goto out; 1241 } 1242 1243 /* Write the terminating null */ 1244 rarg = NULL; 1245 error = copyout(&rarg, rargv, sizeof(rarg)); 1246 1247 out: 1248 uvmspace_free(vp->p_vmspace); 1249 free(buf, M_TEMP); 1250 return (error); 1251 } 1252 1253 /* 1254 * Initialize disknames/diskstats for export by sysctl. If update is set, 1255 * then we simply update the disk statistics information. 1256 */ 1257 int 1258 sysctl_diskinit(update, p) 1259 int update; 1260 struct proc *p; 1261 { 1262 struct diskstats *sdk; 1263 struct disk *dk; 1264 int i, tlen, l; 1265 1266 if ((i = lockmgr(&sysctl_disklock, LK_EXCLUSIVE, NULL, p)) != 0) 1267 return i; 1268 1269 if (disk_change) { 1270 for (dk = TAILQ_FIRST(&disklist), tlen = 0; dk; 1271 dk = TAILQ_NEXT(dk, dk_link)) 1272 tlen += strlen(dk->dk_name) + 1; 1273 tlen++; 1274 1275 if (disknames) 1276 free(disknames, M_SYSCTL); 1277 if (diskstats) 1278 free(diskstats, M_SYSCTL); 1279 diskstats = NULL; 1280 disknames = NULL; 1281 diskstats = malloc(disk_count * sizeof(struct diskstats), 1282 M_SYSCTL, M_WAITOK); 1283 disknames = malloc(tlen, M_SYSCTL, M_WAITOK); 1284 disknames[0] = '\0'; 1285 1286 for (dk = TAILQ_FIRST(&disklist), i = 0, l = 0; dk; 1287 dk = TAILQ_NEXT(dk, dk_link), i++) { 1288 snprintf(disknames + l, tlen - l, "%s,", 1289 dk->dk_name ? dk->dk_name : ""); 1290 l += strlen(disknames + l); 1291 sdk = diskstats + i; 1292 sdk->ds_busy = dk->dk_busy; 1293 sdk->ds_xfer = dk->dk_xfer; 1294 sdk->ds_seek = dk->dk_seek; 1295 sdk->ds_bytes = dk->dk_bytes; 1296 sdk->ds_attachtime = dk->dk_attachtime; 1297 sdk->ds_timestamp = dk->dk_timestamp; 1298 sdk->ds_time = dk->dk_time; 1299 } 1300 1301 /* Eliminate trailing comma */ 1302 if (l != 0) 1303 disknames[l - 1] = '\0'; 1304 disk_change = 0; 1305 } else if (update) { 1306 /* Just update, number of drives hasn't changed */ 1307 for (dk = TAILQ_FIRST(&disklist), i = 0; dk; 1308 dk = TAILQ_NEXT(dk, dk_link), i++) { 1309 sdk = diskstats + i; 1310 sdk->ds_busy = dk->dk_busy; 1311 sdk->ds_xfer = dk->dk_xfer; 1312 sdk->ds_seek = dk->dk_seek; 1313 sdk->ds_bytes = dk->dk_bytes; 1314 sdk->ds_attachtime = dk->dk_attachtime; 1315 sdk->ds_timestamp = dk->dk_timestamp; 1316 sdk->ds_time = dk->dk_time; 1317 } 1318 } 1319 lockmgr(&sysctl_disklock, LK_RELEASE, NULL, p); 1320 return 0; 1321 } 1322 1323 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 1324 int 1325 sysctl_sysvipc(name, namelen, where, sizep) 1326 int *name; 1327 u_int namelen; 1328 void *where; 1329 size_t *sizep; 1330 { 1331 #ifdef SYSVMSG 1332 struct msg_sysctl_info *msgsi; 1333 #endif 1334 #ifdef SYSVSEM 1335 struct sem_sysctl_info *semsi; 1336 #endif 1337 #ifdef SYSVSHM 1338 struct shm_sysctl_info *shmsi; 1339 #endif 1340 size_t infosize, dssize, tsize, buflen; 1341 int i, nds, error, ret; 1342 void *buf; 1343 1344 if (namelen != 1) 1345 return (EINVAL); 1346 1347 buflen = *sizep; 1348 1349 switch (*name) { 1350 case KERN_SYSVIPC_MSG_INFO: 1351 #ifdef SYSVMSG 1352 infosize = sizeof(msgsi->msginfo); 1353 nds = msginfo.msgmni; 1354 dssize = sizeof(msgsi->msgids[0]); 1355 break; 1356 #else 1357 return (EOPNOTSUPP); 1358 #endif 1359 case KERN_SYSVIPC_SEM_INFO: 1360 #ifdef SYSVSEM 1361 infosize = sizeof(semsi->seminfo); 1362 nds = seminfo.semmni; 1363 dssize = sizeof(semsi->semids[0]); 1364 break; 1365 #else 1366 return (EOPNOTSUPP); 1367 #endif 1368 case KERN_SYSVIPC_SHM_INFO: 1369 #ifdef SYSVSHM 1370 infosize = sizeof(shmsi->shminfo); 1371 nds = shminfo.shmmni; 1372 dssize = sizeof(shmsi->shmids[0]); 1373 break; 1374 #else 1375 return (EOPNOTSUPP); 1376 #endif 1377 default: 1378 return (EINVAL); 1379 } 1380 tsize = infosize + (nds * dssize); 1381 1382 /* Return just the total size required. */ 1383 if (where == NULL) { 1384 *sizep = tsize; 1385 return (0); 1386 } 1387 1388 /* Not enough room for even the info struct. */ 1389 if (buflen < infosize) { 1390 *sizep = 0; 1391 return (ENOMEM); 1392 } 1393 buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK); 1394 bzero(buf, min(tsize, buflen)); 1395 1396 switch (*name) { 1397 #ifdef SYSVMSG 1398 case KERN_SYSVIPC_MSG_INFO: 1399 msgsi = (struct msg_sysctl_info *)buf; 1400 msgsi->msginfo = msginfo; 1401 break; 1402 #endif 1403 #ifdef SYSVSEM 1404 case KERN_SYSVIPC_SEM_INFO: 1405 semsi = (struct sem_sysctl_info *)buf; 1406 semsi->seminfo = seminfo; 1407 break; 1408 #endif 1409 #ifdef SYSVSHM 1410 case KERN_SYSVIPC_SHM_INFO: 1411 shmsi = (struct shm_sysctl_info *)buf; 1412 shmsi->shminfo = shminfo; 1413 break; 1414 #endif 1415 } 1416 buflen -= infosize; 1417 1418 ret = 0; 1419 if (buflen > 0) { 1420 /* Fill in the IPC data structures. */ 1421 for (i = 0; i < nds; i++) { 1422 if (buflen < dssize) { 1423 ret = ENOMEM; 1424 break; 1425 } 1426 switch (*name) { 1427 #ifdef SYSVMSG 1428 case KERN_SYSVIPC_MSG_INFO: 1429 bcopy(&msqids[i], &msgsi->msgids[i], dssize); 1430 break; 1431 #endif 1432 #ifdef SYSVSEM 1433 case KERN_SYSVIPC_SEM_INFO: 1434 if (sema[i] != NULL) 1435 bcopy(sema[i], &semsi->semids[i], 1436 dssize); 1437 else 1438 bzero(&semsi->semids[i], dssize); 1439 break; 1440 #endif 1441 #ifdef SYSVSHM 1442 case KERN_SYSVIPC_SHM_INFO: 1443 if (shmsegs[i] != NULL) 1444 bcopy(shmsegs[i], &shmsi->shmids[i], 1445 dssize); 1446 else 1447 bzero(&shmsi->shmids[i], dssize); 1448 break; 1449 #endif 1450 } 1451 buflen -= dssize; 1452 } 1453 } 1454 *sizep -= buflen; 1455 error = copyout(buf, where, *sizep); 1456 free(buf, M_TEMP); 1457 /* If copyout succeeded, use return code set earlier. */ 1458 return (error ? error : ret); 1459 } 1460 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */ 1461 1462 int 1463 sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp) 1464 { 1465 extern int intrcnt[], eintrcnt[]; 1466 extern char intrnames[], eintrnames[]; 1467 char *intrname; 1468 int nintr, i; 1469 1470 nintr = (off_t)(eintrcnt - intrcnt); 1471 1472 if (name[0] != KERN_INTRCNT_NUM) { 1473 if (namelen != 2) 1474 return (ENOTDIR); 1475 if (name[1] < 0 || name[1] >= nintr) 1476 return (EINVAL); 1477 i = name[1]; 1478 } 1479 1480 switch (name[0]) { 1481 case KERN_INTRCNT_NUM: 1482 return (sysctl_rdint(oldp, oldlenp, NULL, nintr)); 1483 break; 1484 case KERN_INTRCNT_CNT: 1485 return (sysctl_rdint(oldp, oldlenp, NULL, intrcnt[i])); 1486 case KERN_INTRCNT_NAME: 1487 intrname = intrnames; 1488 while (i > 0) { 1489 intrname += strlen(intrname) + 1; 1490 i--; 1491 if (intrname > eintrnames) 1492 return (EINVAL); 1493 } 1494 return (sysctl_rdstring(oldp, oldlenp, NULL, intrname)); 1495 default: 1496 return (EOPNOTSUPP); 1497 } 1498 } 1499 1500 int nsensors = 0; 1501 struct sensors_head sensors = SLIST_HEAD_INITIALIZER(&sensors); 1502 1503 int 1504 sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1505 void *newp, size_t newlen) 1506 { 1507 struct sensor *s = NULL; 1508 int num; 1509 1510 if (namelen != 1) 1511 return (ENOTDIR); 1512 1513 num = name[0]; 1514 if (num >= nsensors) 1515 return (ENXIO); 1516 1517 SLIST_FOREACH(s, &sensors, list) 1518 if (s->num == num) 1519 break; 1520 1521 return (sysctl_rdstruct(oldp, oldlenp, newp, s, sizeof(struct sensor))); 1522 } 1523 1524 int 1525 sysctl_emul(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1526 void *newp, size_t newlen) 1527 { 1528 int enabled, error; 1529 struct emul *e; 1530 1531 if (name[0] == KERN_EMUL_NUM) { 1532 if (namelen != 1) 1533 return (ENOTDIR); 1534 return (sysctl_rdint(oldp, oldlenp, newp, nemuls)); 1535 } 1536 1537 if (namelen != 2) 1538 return (ENOTDIR); 1539 if (name[0] > nemuls || name[0] < 0) 1540 return (EINVAL); 1541 e = emulsw[name[0] - 1]; 1542 1543 switch (name[1]) { 1544 case KERN_EMUL_NAME: 1545 return (sysctl_rdstring(oldp, oldlenp, newp, e->e_name)); 1546 case KERN_EMUL_ENABLED: 1547 enabled = (e->e_flags & EMUL_ENABLED); 1548 error = sysctl_int(oldp, oldlenp, newp, newlen, 1549 &enabled); 1550 e->e_flags = (enabled & EMUL_ENABLED); 1551 return (error); 1552 default: 1553 return (EINVAL); 1554 } 1555 } 1556