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:  * Redistribution and use in source and binary forms, with or without
   9:  * modification, are permitted provided that the following conditions
  10:  * are met:
  11:  * 1. Redistributions of source code must retain the above copyright
  12:  *    notice, this list of conditions and the following disclaimer.
  13:  * 2. Redistributions in binary form must reproduce the above copyright
  14:  *    notice, this list of conditions and the following disclaimer in the
  15:  *    documentation and/or other materials provided with the distribution.
  16:  * 3. All advertising materials mentioning features or use of this software
  17:  *    must display the following acknowledgement:
  18:  *	This product includes software developed by the University of
  19:  *	California, Berkeley and its contributors.
  20:  * 4. Neither the name of the University nor the names of its contributors
  21:  *    may be used to endorse or promote products derived from this software
  22:  *    without specific prior written permission.
  23:  *
  24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34:  * SUCH DAMAGE.
  35:  *
  36:  *	@(#)kern_sysctl.c	8.4.11 (2.11BSD) 1999/8/11
  37:  */
  38: 
  39: /*
  40:  * sysctl system call.
  41:  */
  42: 
  43: #include <sys/param.h>
  44: #include <sys/user.h>
  45: #include <sys/systm.h>
  46: #include <sys/proc.h>
  47: #include <sys/buf.h>
  48: #include <sys/kernel.h>
  49: #include <sys/file.h>
  50: #include <sys/inode.h>
  51: #include <sys/ioctl.h>
  52: #include <sys/text.h>
  53: #include <sys/tty.h>
  54: #include <sys/vm.h>
  55: #include <sys/map.h>
  56: #include <machine/seg.h>
  57: #include <sys/sysctl.h>
  58: #include <machine/cpu.h>
  59: #include <conf.h>
  60: 
  61: sysctlfn kern_sysctl;
  62: sysctlfn hw_sysctl;
  63: #ifdef DEBUG
  64: sysctlfn debug_sysctl;
  65: #endif
  66: sysctlfn vm_sysctl;
  67: sysctlfn fs_sysctl;
  68: #ifdef  INET
  69: sysctlfn NET_SYSCTL;
  70: extern  int net_sysctl();   /* In supervisor space */
  71: #endif
  72: sysctlfn cpu_sysctl;
  73: 
  74: /*
  75:  * Locking and stats
  76:  */
  77: static struct sysctl_lock {
  78:     int sl_lock;
  79:     int sl_want;
  80:     int sl_locked;
  81: } memlock;
  82: 
  83: struct sysctl_args {
  84:     int *name;
  85:     u_int   namelen;
  86:     void    *old;
  87:     size_t  *oldlenp;
  88:     void    *new;
  89:     size_t  newlen;
  90: };
  91: 
  92: int
  93: __sysctl()
  94: {
  95:     register struct sysctl_args *uap = (struct sysctl_args *)u.u_ap;
  96:     int error;
  97:     u_int savelen, oldlen = 0;
  98:     sysctlfn *fn;
  99:     int name[CTL_MAXNAME];
 100: 
 101:     if (uap->new != NULL && !suser())
 102:         return (u.u_error); /* XXX */
 103:     /*
 104: 	 * all top-level sysctl names are non-terminal
 105: 	 */
 106:     if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
 107:         return (u.u_error = EINVAL);
 108:     if (error = copyin(uap->name, &name, uap->namelen * sizeof(int)))
 109:         return (u.u_error = error);
 110: 
 111:     switch (name[0]) {
 112:     case CTL_KERN:
 113:         fn = kern_sysctl;
 114:         break;
 115:     case CTL_HW:
 116:         fn = hw_sysctl;
 117:         break;
 118:     case CTL_VM:
 119:         fn = vm_sysctl;
 120:         break;
 121: #ifdef  INET
 122:     case CTL_NET:
 123:         fn = NET_SYSCTL;
 124:         break;
 125: #endif
 126: #ifdef notyet
 127:     case CTL_FS:
 128:         fn = fs_sysctl;
 129:         break;
 130: #endif
 131:     case CTL_MACHDEP:
 132:         fn = cpu_sysctl;
 133:         break;
 134: #ifdef DEBUG
 135:     case CTL_DEBUG:
 136:         fn = debug_sysctl;
 137:         break;
 138: #endif
 139:     default:
 140:         return (u.u_error = EOPNOTSUPP);
 141:     }
 142: 
 143:     if (uap->oldlenp &&
 144:         (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen))))
 145:         return (u.u_error = error);
 146:     if (uap->old != NULL) {
 147:         while (memlock.sl_lock) {
 148:             memlock.sl_want = 1;
 149:             sleep((caddr_t)&memlock, PRIBIO+1);
 150:             memlock.sl_locked++;
 151:         }
 152:         memlock.sl_lock = 1;
 153:         savelen = oldlen;
 154:     }
 155:     error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen,
 156:         uap->new, uap->newlen);
 157:     if (uap->old != NULL) {
 158:         memlock.sl_lock = 0;
 159:         if (memlock.sl_want) {
 160:             memlock.sl_want = 0;
 161:             wakeup((caddr_t)&memlock);
 162:         }
 163:     }
 164:     if (error)
 165:         return (u.u_error = error);
 166:     if (uap->oldlenp) {
 167:         error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen));
 168:         if (error)
 169:             return(u.u_error = error);
 170:     }
 171:     u.u_r.r_val1 = oldlen;
 172:     return (0);
 173: }
 174: 
 175: /*
 176:  * kernel related system variables.
 177:  */
 178: kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
 179:     int *name;
 180:     u_int namelen;
 181:     void *oldp;
 182:     size_t *oldlenp;
 183:     void *newp;
 184:     size_t newlen;
 185: {
 186:     int error, level;
 187:     u_long longhostid;
 188:     char bsd[10];
 189:     extern int Acctthresh;      /* kern_acct.c */
 190:     extern char version[];
 191: 
 192:     /* all sysctl names at this level are terminal */
 193:     if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF))
 194:         return (ENOTDIR);       /* overloaded */
 195: 
 196:     switch (name[0]) {
 197:     case KERN_OSTYPE:
 198:     case KERN_OSRELEASE:
 199:         /* code is cheaper than D space */
 200:         bsd[0]='2';bsd[1]='.';bsd[2]='1';bsd[3]='1';bsd[4]='B';
 201:         bsd[5]='S';bsd[6]='D';bsd[7]='\0';
 202:         return (sysctl_rdstring(oldp, oldlenp, newp, bsd));
 203:     case KERN_ACCTTHRESH:
 204:         level = Acctthresh;
 205:         error = sysctl_int(oldp, oldlenp, newp, newlen, &level);
 206:         if  (newp && !error)
 207:             {
 208:             if  (level < 0 || level > 128)
 209:                 error = EINVAL;
 210:             else
 211:                 Acctthresh = level;
 212:             }
 213:         return(error);
 214:     case KERN_OSREV:
 215:         return (sysctl_rdlong(oldp, oldlenp, newp, (long)BSD));
 216:     case KERN_VERSION:
 217:         return (sysctl_rdstring(oldp, oldlenp, newp, version));
 218:     case KERN_MAXINODES:
 219:         return(sysctl_rdint(oldp, oldlenp, newp, ninode));
 220:     case KERN_MAXPROC:
 221:         return (sysctl_rdint(oldp, oldlenp, newp, nproc));
 222:     case KERN_MAXFILES:
 223:         return (sysctl_rdint(oldp, oldlenp, newp, nfile));
 224:     case KERN_MAXTEXTS:
 225:         return (sysctl_rdint(oldp, oldlenp, newp, ntext));
 226:     case KERN_ARGMAX:
 227:         return (sysctl_rdint(oldp, oldlenp, newp, NCARGS));
 228:     case KERN_SECURELVL:
 229:         level = securelevel;
 230:         if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
 231:             newp == NULL)
 232:             return (error);
 233:         if (level < securelevel && u.u_procp->p_pid != 1)
 234:             return (EPERM);
 235:         securelevel = level;
 236:         return (0);
 237:     case KERN_HOSTNAME:
 238:         error = sysctl_string(oldp, oldlenp, newp, newlen,
 239:             hostname, sizeof(hostname));
 240:         if (newp && !error)
 241:             hostnamelen = newlen;
 242:         return (error);
 243:     case KERN_HOSTID:
 244:         longhostid = hostid;
 245:         error =  sysctl_long(oldp, oldlenp, newp, newlen, &longhostid);
 246:         hostid = longhostid;
 247:         return (error);
 248:     case KERN_CLOCKRATE:
 249:         return (sysctl_clockrate(oldp, oldlenp));
 250:     case KERN_BOOTTIME:
 251:         return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
 252:             sizeof(struct timeval)));
 253:     case KERN_INODE:
 254:         return (sysctl_inode(oldp, oldlenp));
 255:     case KERN_PROC:
 256:         return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
 257:     case KERN_FILE:
 258:         return (sysctl_file(oldp, oldlenp));
 259:     case KERN_TEXT:
 260:         return (sysctl_text(oldp, oldlenp));
 261: #ifdef GPROF
 262:     case KERN_PROF:
 263:         return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
 264:             newp, newlen));
 265: #endif
 266:     case KERN_NGROUPS:
 267:         return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS));
 268:     case KERN_JOB_CONTROL:
 269:         return (sysctl_rdint(oldp, oldlenp, newp, 1));
 270:     case KERN_POSIX1:
 271:     case KERN_SAVED_IDS:
 272:         return (sysctl_rdint(oldp, oldlenp, newp, 0));
 273:     default:
 274:         return (EOPNOTSUPP);
 275:     }
 276:     /* NOTREACHED */
 277: }
 278: 
 279: /*
 280:  * hardware related system variables.
 281:  */
 282: hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
 283:     int *name;
 284:     u_int namelen;
 285:     void *oldp;
 286:     size_t *oldlenp;
 287:     void *newp;
 288:     size_t newlen;
 289: {
 290:     char c[10];
 291:     char *cpu2str();
 292:     extern  size_t physmem;         /* machdep2.c */
 293: 
 294:     /* all sysctl names at this level are terminal */
 295:     if (namelen != 1)
 296:         return (ENOTDIR);       /* overloaded */
 297: 
 298:     switch (name[0]) {
 299:     case HW_MACHINE:
 300:         return (sysctl_rdstring(oldp, oldlenp, newp, "pdp11"));
 301:     case HW_MODEL:
 302:         return (sysctl_rdstring(oldp, oldlenp, newp,
 303:                 cpu2str(c,sizeof (c))));
 304:     case HW_NCPU:
 305:         return (sysctl_rdint(oldp, oldlenp, newp, 1));  /* XXX */
 306:     case HW_BYTEORDER:
 307:         return (sysctl_rdint(oldp, oldlenp, newp, ENDIAN));
 308:     case HW_PHYSMEM:
 309:         return (sysctl_rdlong(oldp, oldlenp, newp,ctob((long)physmem)));
 310:     case HW_USERMEM:
 311:         return (sysctl_rdlong(oldp, oldlenp, newp,ctob((long)freemem)));
 312:     case HW_PAGESIZE:
 313:         return (sysctl_rdint(oldp, oldlenp, newp, NBPG*CLSIZE));
 314:     default:
 315:         return (EOPNOTSUPP);
 316:     }
 317:     /* NOTREACHED */
 318: }
 319: 
 320: static char *
 321: cpu2str(buf, len)
 322:     char    *buf;
 323:     int len;
 324:     {
 325:     register char *cp = buf + len;
 326:     register int i = cputype;
 327: 
 328:     *--cp = '\0';
 329:     do
 330:         {
 331:         *--cp = (i % 10) + '0';
 332:         } while (i /= 10);
 333:     return(cp);
 334:     }
 335: 
 336: #ifdef DEBUG
 337: /*
 338:  * Debugging related system variables.
 339:  */
 340: struct ctldebug debug0, debug1, debug2, debug3, debug4;
 341: struct ctldebug debug5, debug6, debug7, debug8, debug9;
 342: struct ctldebug debug10, debug11, debug12, debug13, debug14;
 343: struct ctldebug debug15, debug16, debug17, debug18, debug19;
 344: static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
 345:     &debug0, &debug1, &debug2, &debug3, &debug4,
 346:     &debug5, &debug6, &debug7, &debug8, &debug9,
 347:     &debug10, &debug11, &debug12, &debug13, &debug14,
 348:     &debug15, &debug16, &debug17, &debug18, &debug19,
 349: };
 350: int
 351: debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
 352:     int *name;
 353:     u_int namelen;
 354:     void *oldp;
 355:     size_t *oldlenp;
 356:     void *newp;
 357:     size_t newlen;
 358: {
 359:     struct ctldebug *cdp;
 360: 
 361:     /* all sysctl names at this level are name and field */
 362:     if (namelen != 2)
 363:         return (ENOTDIR);       /* overloaded */
 364:     cdp = debugvars[name[0]];
 365:     if (cdp->debugname == 0)
 366:         return (EOPNOTSUPP);
 367:     switch (name[1]) {
 368:     case CTL_DEBUG_NAME:
 369:         return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
 370:     case CTL_DEBUG_VALUE:
 371:         return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
 372:     default:
 373:         return (EOPNOTSUPP);
 374:     }
 375:     /* NOTREACHED */
 376: }
 377: #endif /* DEBUG */
 378: 
 379: #ifdef  INET
 380: /*
 381:  * In 4.4BSD-Lite these functions were scattered amoungst the various
 382:  * subsystems they dealt with.
 383:  *
 384:  * In 2.11BSD the kernel is overlaid and adding code to multiple
 385:  * files would have caused existing overlay structures to break.
 386:  * This module will be large enough that it will end up in an overlay
 387:  * by itself.  Thus centralizing all sysctl handling in one place makes
 388:  * a lot of sense.  The one exception is the networking related syctl
 389:  * functions.  Because the networking code is not overlaid and runs
 390:  * in supervisor mode the sysctl handling can not be done here and
 391:  * will be implemented in the 4.4BSD manner (by modifying the networking
 392:  * modules).
 393: */
 394: 
 395: int
 396: NET_SYSCTL(name, namelen, oldp, oldlenp, newp, newlen)
 397:     int *name;
 398:     u_int namelen;
 399:     void *oldp;
 400:     size_t *oldlenp;
 401:     void *newp;
 402:     size_t newlen;
 403: {
 404:     return(KScall(net_sysctl, 6 * sizeof (int),
 405:             name, namelen, oldp, oldlenp, newp, newlen));
 406: }
 407: #endif
 408: 
 409: /*
 410:  * Bit of a hack.  2.11 currently uses 'short avenrun[3]' and a fixed scale
 411:  * of 256.  In order not to break all the applications which nlist() for
 412:  * 'avenrun' we build a local 'averunnable' structure here to return to the
 413:  * user.  Eventually (after all applications which look up the load average
 414:  * the old way) have been converted we can change things.
 415:  *
 416:  * We do not call vmtotal(), that could get rather expensive, rather we rely
 417:  * on the 5 second update.
 418:  *
 419:  * The coremap and swapmap cases are 2.11BSD extensions.
 420: */
 421: 
 422: int
 423: vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
 424:     int *name;
 425:     u_int namelen;
 426:     void *oldp;
 427:     size_t *oldlenp;
 428:     void *newp;
 429:     size_t newlen;
 430: {
 431:     struct  loadavg averunnable;    /* loadavg in resource.h */
 432: 
 433:     /* all sysctl names at this level are terminal */
 434:     if (namelen != 1)
 435:         return (ENOTDIR);       /* overloaded */
 436: 
 437:     switch (name[0]) {
 438:     case VM_LOADAVG:
 439:         averunnable.fscale = 256;
 440:         averunnable.ldavg[0] = avenrun[0];
 441:         averunnable.ldavg[1] = avenrun[1];
 442:         averunnable.ldavg[2] = avenrun[2];
 443:         return (sysctl_rdstruct(oldp, oldlenp, newp, &averunnable,
 444:             sizeof(averunnable)));
 445:     case VM_METER:
 446: #ifdef  notsure
 447:         vmtotal();  /* could be expensive to do this every time */
 448: #endif
 449:         return (sysctl_rdstruct(oldp, oldlenp, newp, &total,
 450:             sizeof(total)));
 451:     case VM_SWAPMAP:
 452:         if (oldp == NULL) {
 453:             *oldlenp = (char *)swapmap[0].m_limit -
 454:                     (char *)swapmap[0].m_map;
 455:             return(0);
 456:         }
 457:         return (sysctl_rdstruct(oldp, oldlenp, newp, swapmap,
 458:             (int)swapmap[0].m_limit - (int)swapmap[0].m_map));
 459:     case VM_COREMAP:
 460:         if (oldp == NULL) {
 461:             *oldlenp = (char *)coremap[0].m_limit -
 462:                     (char *)coremap[0].m_map;
 463:             return(0);
 464:         }
 465:         return (sysctl_rdstruct(oldp, oldlenp, newp, coremap,
 466:             (int)coremap[0].m_limit - (int)coremap[0].m_map));
 467:     default:
 468:         return (EOPNOTSUPP);
 469:     }
 470:     /* NOTREACHED */
 471: }
 472: 
 473: /*
 474:  * Validate parameters and get old / set new parameters
 475:  * for an integer-valued sysctl function.
 476:  */
 477: sysctl_int(oldp, oldlenp, newp, newlen, valp)
 478:     void *oldp;
 479:     size_t *oldlenp;
 480:     void *newp;
 481:     size_t newlen;
 482:     int *valp;
 483: {
 484:     int error = 0;
 485: 
 486:     if (oldp && *oldlenp < sizeof(int))
 487:         return (ENOMEM);
 488:     if (newp && newlen != sizeof(int))
 489:         return (EINVAL);
 490:     *oldlenp = sizeof(int);
 491:     if (oldp)
 492:         error = copyout(valp, oldp, sizeof(int));
 493:     if (error == 0 && newp)
 494:         error = copyin(newp, valp, sizeof(int));
 495:     return (error);
 496: }
 497: 
 498: /*
 499:  * As above, but read-only.
 500:  */
 501: sysctl_rdint(oldp, oldlenp, newp, val)
 502:     void *oldp;
 503:     size_t *oldlenp;
 504:     void *newp;
 505:     int val;
 506: {
 507:     int error = 0;
 508: 
 509:     if (oldp && *oldlenp < sizeof(int))
 510:         return (ENOMEM);
 511:     if (newp)
 512:         return (EPERM);
 513:     *oldlenp = sizeof(int);
 514:     if (oldp)
 515:         error = copyout((caddr_t)&val, oldp, sizeof(int));
 516:     return (error);
 517: }
 518: 
 519: /*
 520:  * Validate parameters and get old / set new parameters
 521:  * for an long-valued sysctl function.
 522:  */
 523: sysctl_long(oldp, oldlenp, newp, newlen, valp)
 524:     void *oldp;
 525:     size_t *oldlenp;
 526:     void *newp;
 527:     size_t newlen;
 528:     long *valp;
 529: {
 530:     int error = 0;
 531: 
 532:     if (oldp && *oldlenp < sizeof(long))
 533:         return (ENOMEM);
 534:     if (newp && newlen != sizeof(long))
 535:         return (EINVAL);
 536:     *oldlenp = sizeof(long);
 537:     if (oldp)
 538:         error = copyout(valp, oldp, sizeof(long));
 539:     if (error == 0 && newp)
 540:         error = copyin(newp, valp, sizeof(long));
 541:     return (error);
 542: }
 543: 
 544: /*
 545:  * As above, but read-only.
 546:  */
 547: sysctl_rdlong(oldp, oldlenp, newp, val)
 548:     void *oldp;
 549:     size_t *oldlenp;
 550:     void *newp;
 551:     long val;
 552: {
 553:     int error = 0;
 554: 
 555:     if (oldp && *oldlenp < sizeof(long))
 556:         return (ENOMEM);
 557:     if (newp)
 558:         return (EPERM);
 559:     *oldlenp = sizeof(long);
 560:     if (oldp)
 561:         error = copyout((caddr_t)&val, oldp, sizeof(long));
 562:     return (error);
 563: }
 564: 
 565: /*
 566:  * Validate parameters and get old / set new parameters
 567:  * for a string-valued sysctl function.
 568:  */
 569: sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
 570:     void *oldp;
 571:     size_t *oldlenp;
 572:     void *newp;
 573:     size_t newlen;
 574:     char *str;
 575:     int maxlen;
 576: {
 577:     int len, error = 0;
 578: 
 579:     len = strlen(str) + 1;
 580:     if (oldp && *oldlenp < len)
 581:         return (ENOMEM);
 582:     if (newp && newlen >= maxlen)
 583:         return (EINVAL);
 584:     if (oldp) {
 585:         *oldlenp = len;
 586:         error = vcopyout(str, oldp, len);
 587:     }
 588:     if (error == 0 && newp) {
 589:         error = vcopyin(newp, str, newlen);
 590:         str[newlen] = 0;
 591:     }
 592:     return (error);
 593: }
 594: 
 595: /*
 596:  * As above, but read-only.
 597:  */
 598: sysctl_rdstring(oldp, oldlenp, newp, str)
 599:     void *oldp;
 600:     size_t *oldlenp;
 601:     void *newp;
 602:     char *str;
 603: {
 604:     int len, error = 0;
 605: 
 606:     len = strlen(str) + 1;
 607:     if (oldp && *oldlenp < len)
 608:         return (ENOMEM);
 609:     if (newp)
 610:         return (EPERM);
 611:     *oldlenp = len;
 612:     if (oldp)
 613:         error = vcopyout(str, oldp, len);
 614:     return (error);
 615: }
 616: 
 617: /*
 618:  * Validate parameters and get old / set new parameters
 619:  * for a structure oriented sysctl function.
 620:  */
 621: sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
 622:     void *oldp;
 623:     size_t *oldlenp;
 624:     void *newp;
 625:     size_t newlen;
 626:     void *sp;
 627:     int len;
 628: {
 629:     int error = 0;
 630: 
 631:     if (oldp && *oldlenp < len)
 632:         return (ENOMEM);
 633:     if (newp && newlen > len)
 634:         return (EINVAL);
 635:     if (oldp) {
 636:         *oldlenp = len;
 637:         error = copyout(sp, oldp, len);
 638:     }
 639:     if (error == 0 && newp)
 640:         error = copyin(newp, sp, len);
 641:     return (error);
 642: }
 643: 
 644: /*
 645:  * Validate parameters and get old parameters
 646:  * for a structure oriented sysctl function.
 647:  */
 648: sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
 649:     void *oldp;
 650:     size_t *oldlenp;
 651:     void *newp, *sp;
 652:     int len;
 653: {
 654:     int error = 0;
 655: 
 656:     if (oldp && *oldlenp < len)
 657:         return (ENOMEM);
 658:     if (newp)
 659:         return (EPERM);
 660:     *oldlenp = len;
 661:     if (oldp)
 662:         error = copyout(sp, oldp, len);
 663:     return (error);
 664: }
 665: 
 666: /*
 667:  * Get file structures.
 668:  */
 669: sysctl_file(where, sizep)
 670:     char *where;
 671:     size_t *sizep;
 672: {
 673:     int buflen, error;
 674:     register struct file *fp;
 675:     struct  file *fpp;
 676:     char *start = where;
 677:     register int i;
 678: 
 679:     buflen = *sizep;
 680:     if (where == NULL) {
 681:         for (i = 0, fp = file; fp < fileNFILE; fp++)
 682:             if (fp->f_count) i++;
 683: 
 684: #define FPTRSZ  sizeof (struct file *)
 685: #define FILESZ  sizeof (struct file)
 686:         /*
 687: 		 * overestimate by 5 files
 688: 		 */
 689:         *sizep = (i + 5) * (FILESZ + FPTRSZ);
 690:         return (0);
 691:     }
 692: 
 693:     /*
 694: 	 * array of extended file structures: first the address then the
 695: 	 * file structure.
 696: 	 */
 697:     for (fp = file; fp < fileNFILE; fp++) {
 698:         if (fp->f_count == 0)
 699:             continue;
 700:         if (buflen < (FPTRSZ + FILESZ)) {
 701:             *sizep = where - start;
 702:             return (ENOMEM);
 703:         }
 704:         fpp = fp;
 705:         if ((error = copyout(&fpp, where, FPTRSZ)) ||
 706:             (error = copyout(fp, where + FPTRSZ, FILESZ)))
 707:             return (error);
 708:         buflen -= (FPTRSZ + FILESZ);
 709:         where += (FPTRSZ + FILESZ);
 710:     }
 711:     *sizep = where - start;
 712:     return (0);
 713: }
 714: 
 715: /*
 716:  * This one is in kern_clock.c in 4.4 but placed here for the reasons
 717:  * given earlier (back around line 367).
 718: */
 719: 
 720: int
 721: sysctl_clockrate(where, sizep)
 722:     char *where;
 723:     size_t *sizep;
 724: {
 725:     struct  clockinfo clkinfo;
 726: 
 727:     /*
 728: 	 * Construct clockinfo structure.
 729: 	*/
 730:     clkinfo.hz = hz;
 731:     clkinfo.tick = mshz;
 732:     clkinfo.profhz = 0;
 733:     clkinfo.stathz = hz;
 734:     return(sysctl_rdstruct(where, sizep, NULL, &clkinfo, sizeof (clkinfo)));
 735: }
 736: 
 737: /*
 738:  * Dump inode list (via sysctl).
 739:  * Copyout address of inode followed by inode.
 740:  */
 741: /* ARGSUSED */
 742: sysctl_inode(where, sizep)
 743:     char *where;
 744:     size_t *sizep;
 745: {
 746:     register struct inode *ip;
 747:     register char *bp = where;
 748:     struct inode *ipp;
 749:     char *ewhere;
 750:     int error, numi;
 751: 
 752:     for (numi = 0, ip = inode; ip < inodeNINODE; ip++)
 753:         if (ip->i_count) numi++;
 754: 
 755: #define IPTRSZ  sizeof (struct inode *)
 756: #define INODESZ sizeof (struct inode)
 757:     if (where == NULL) {
 758:         *sizep = (numi + 5) * (IPTRSZ + INODESZ);
 759:         return (0);
 760:     }
 761:     ewhere = where + *sizep;
 762: 
 763:     for (ip = inode; ip < inodeNINODE; ip++) {
 764:         if (ip->i_count == 0)
 765:             continue;
 766:         if (bp + IPTRSZ + INODESZ > ewhere) {
 767:             *sizep = bp - where;
 768:             return (ENOMEM);
 769:         }
 770:         ipp = ip;
 771:         if ((error = copyout((caddr_t)&ipp, bp, IPTRSZ)) ||
 772:               (error = copyout((caddr_t)ip, bp + IPTRSZ, INODESZ)))
 773:             return (error);
 774:         bp += IPTRSZ + INODESZ;
 775:     }
 776: 
 777:     *sizep = bp - where;
 778:     return (0);
 779: }
 780: 
 781: /*
 782:  * Get text structures.  This is a 2.11BSD extension.  sysctl() is supposed
 783:  * to be extensible...
 784:  */
 785: sysctl_text(where, sizep)
 786:     char *where;
 787:     size_t *sizep;
 788: {
 789:     int buflen, error;
 790:     register struct text *xp;
 791:     struct  text *xpp;
 792:     char *start = where;
 793:     register int i;
 794: 
 795:     buflen = *sizep;
 796:     if (where == NULL) {
 797:         for (i = 0, xp = text; xp < textNTEXT; xp++)
 798:             if (xp->x_count) i++;
 799: 
 800: #define TPTRSZ  sizeof (struct text *)
 801: #define TEXTSZ  sizeof (struct text)
 802:         /*
 803: 		 * overestimate by 3 text structures
 804: 		 */
 805:         *sizep = (i + 3) * (TEXTSZ + TPTRSZ);
 806:         return (0);
 807:     }
 808: 
 809:     /*
 810: 	 * array of extended file structures: first the address then the
 811: 	 * file structure.
 812: 	 */
 813:     for (xp = text; xp < textNTEXT; xp++) {
 814:         if (xp->x_count == 0)
 815:             continue;
 816:         if (buflen < (TPTRSZ + TEXTSZ)) {
 817:             *sizep = where - start;
 818:             return (ENOMEM);
 819:         }
 820:         xpp = xp;
 821:         if ((error = copyout(&xpp, where, TPTRSZ)) ||
 822:             (error = copyout(xp, where + TPTRSZ, TEXTSZ)))
 823:             return (error);
 824:         buflen -= (TPTRSZ + TEXTSZ);
 825:         where += (TPTRSZ + TEXTSZ);
 826:     }
 827:     *sizep = where - start;
 828:     return (0);
 829: }
 830: 
 831: /*
 832:  * try over estimating by 5 procs
 833:  */
 834: #define KERN_PROCSLOP   (5 * sizeof (struct kinfo_proc))
 835: 
 836: sysctl_doproc(name, namelen, where, sizep)
 837:     int *name;
 838:     u_int namelen;
 839:     char *where;
 840:     size_t *sizep;
 841: {
 842:     register struct proc *p;
 843:     register struct kinfo_proc *dp = (struct kinfo_proc *)where;
 844:     int needed = 0;
 845:     int buflen = where != NULL ? *sizep : 0;
 846:     int doingzomb;
 847:     struct eproc eproc;
 848:     int error = 0;
 849:     dev_t ttyd;
 850:     uid_t ruid;
 851:     struct tty *ttyp;
 852: 
 853:     if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
 854:         return (EINVAL);
 855:     p = (struct proc *)allproc;
 856:     doingzomb = 0;
 857: again:
 858:     for (; p != NULL; p = p->p_nxt) {
 859:         /*
 860: 		 * Skip embryonic processes.
 861: 		 */
 862:         if (p->p_stat == SIDL)
 863:             continue;
 864:         /*
 865: 		 * TODO - make more efficient (see notes below).
 866: 		 * do by session.
 867: 		 */
 868:         switch (name[0]) {
 869: 
 870:         case KERN_PROC_PID:
 871:             /* could do this with just a lookup */
 872:             if (p->p_pid != (pid_t)name[1])
 873:                 continue;
 874:             break;
 875: 
 876:         case KERN_PROC_PGRP:
 877:             /* could do this by traversing pgrp */
 878:             if (p->p_pgrp != (pid_t)name[1])
 879:                 continue;
 880:             break;
 881: 
 882:         case KERN_PROC_TTY:
 883:             fill_from_u(p, &ruid, &ttyp, &ttyd);
 884:             if (!ttyp || ttyd != (dev_t)name[1])
 885:                 continue;
 886:             break;
 887: 
 888:         case KERN_PROC_UID:
 889:             if (p->p_uid != (uid_t)name[1])
 890:                 continue;
 891:             break;
 892: 
 893:         case KERN_PROC_RUID:
 894:             fill_from_u(p, &ruid, &ttyp, &ttyd);
 895:             if (ruid != (uid_t)name[1])
 896:                 continue;
 897:             break;
 898: 
 899:         case KERN_PROC_ALL:
 900:             break;
 901:         default:
 902:             return(EINVAL);
 903:         }
 904:         if (buflen >= sizeof(struct kinfo_proc)) {
 905:             fill_eproc(p, &eproc);
 906:             if (error = copyout((caddr_t)p, &dp->kp_proc,
 907:                 sizeof(struct proc)))
 908:                 return (error);
 909:             if (error = copyout((caddr_t)&eproc, &dp->kp_eproc,
 910:                 sizeof(eproc)))
 911:                 return (error);
 912:             dp++;
 913:             buflen -= sizeof(struct kinfo_proc);
 914:         }
 915:         needed += sizeof(struct kinfo_proc);
 916:     }
 917:     if (doingzomb == 0) {
 918:         p = zombproc;
 919:         doingzomb++;
 920:         goto again;
 921:     }
 922:     if (where != NULL) {
 923:         *sizep = (caddr_t)dp - where;
 924:         if (needed > *sizep)
 925:             return (ENOMEM);
 926:     } else {
 927:         needed += KERN_PROCSLOP;
 928:         *sizep = needed;
 929:     }
 930:     return (0);
 931: }
 932: 
 933: /*
 934:  * Fill in an eproc structure for the specified process.  Slightly
 935:  * inefficient because we have to access the u area again for the
 936:  * information not kept in the proc structure itself.  Can't afford
 937:  * to expand the proc struct so we take a slight speed hit here.
 938:  */
 939: void
 940: fill_eproc(p, ep)
 941:     register struct proc *p;
 942:     register struct eproc *ep;
 943: {
 944:     struct  tty *ttyp;
 945: 
 946:     ep->e_paddr = p;
 947:     fill_from_u(p, &ep->e_ruid, &ttyp, &ep->e_tdev);
 948:     if  (ttyp)
 949:         ep->e_tpgid = ttyp->t_pgrp;
 950:     else
 951:         ep->e_tpgid = 0;
 952: }
 953: 
 954: /*
 955:  * Three pieces of information we need about a process are not kept in
 956:  * the proc table: real uid, controlling terminal device, and controlling
 957:  * terminal tty struct pointer.  For these we must look in either the u
 958:  * area or the swap area.  If the process is still in memory this is
 959:  * easy but if the process has been swapped out we have to read in the
 960:  * u area.
 961:  *
 962:  * XXX - We rely on the fact that u_ttyp, u_ttyd, and u_ruid are all within
 963:  * XXX - the first 1kb of the u area.  If this ever changes the logic below
 964:  * XXX - will break (and badly).  At the present time (97/9/2) the u area
 965:  * XXX - is 856 bytes long.
 966: */
 967: 
 968: fill_from_u(p, rup, ttp, tdp)
 969:     struct  proc    *p;
 970:     uid_t   *rup;
 971:     struct  tty **ttp;
 972:     dev_t   *tdp;
 973:     {
 974:     register struct buf *bp;
 975:     dev_t   ttyd;
 976:     uid_t   ruid;
 977:     struct  tty *ttyp;
 978:     struct  user    *up;
 979: 
 980:     if  (p->p_stat == SZOMB)
 981:         {
 982:         ruid = (uid_t)-2;
 983:         ttyp = NULL;
 984:         ttyd = NODEV;
 985:         goto out;
 986:         }
 987:     if  (p->p_flag & SLOAD)
 988:         {
 989:         mapseg5(p->p_addr, (((USIZE - 1) << 8) | RO));
 990:         ttyd = ((struct user *)SEG5)->u_ttyd;
 991:         ttyp = ((struct user *)SEG5)->u_ttyp;
 992:         ruid = ((struct user *)SEG5)->u_ruid;
 993:         normalseg5();
 994:         }
 995:     else
 996:         {
 997:         bp = geteblk();
 998:         bp->b_dev = swapdev;
 999:         bp->b_blkno = (daddr_t)p->p_addr;
1000:         bp->b_bcount = DEV_BSIZE;   /* XXX */
1001:         bp->b_flags = B_READ;
1002: 
1003:         (*bdevsw[major(swapdev)].d_strategy)(bp);
1004:         biowait(bp);
1005: 
1006:         if  (u.u_error)
1007:             {
1008:             ttyd = NODEV;
1009:             ttyp = NULL;
1010:             ruid = (uid_t)-2;
1011:             }
1012:         else
1013:             {
1014:             up = (struct user *)mapin(bp);
1015:             ruid = up->u_ruid;  /* u_ruid = offset 164 */
1016:             ttyd = up->u_ttyd;  /* u_ttyd = offset 654 */
1017:             ttyp = up->u_ttyp;  /* u_ttyp = offset 652 */
1018:             mapout(bp);
1019:             }
1020:         bp->b_flags |= B_AGE;
1021:         brelse(bp);
1022:         u.u_error = 0;      /* XXX */
1023:         }
1024: out:
1025:     if  (rup)
1026:         *rup = ruid;
1027:     if  (ttp)
1028:         *ttp = ttyp;
1029:     if  (tdp)
1030:         *tdp = ttyd;
1031:     }

Defined functions

NET_SYSCTL defined in line 395; used 2 times
__sysctl defined in line 92; used 2 times
cpu2str defined in line 320; used 2 times
debug_sysctl defined in line 350; used 2 times
fill_eproc defined in line 939; used 2 times
fill_from_u defined in line 968; used 4 times
hw_sysctl defined in line 282; used 2 times
kern_sysctl defined in line 178; used 2 times
sysctl_clockrate defined in line 720; used 1 times
sysctl_doproc defined in line 836; used 1 times
sysctl_file defined in line 669; used 1 times
sysctl_inode defined in line 742; used 1 times
sysctl_long defined in line 523; used 1 times
sysctl_rdint defined in line 501; used 12 times
sysctl_rdlong defined in line 547; used 3 times
sysctl_rdstring defined in line 598; used 6 times
sysctl_rdstruct defined in line 648; used 8 times
sysctl_string defined in line 569; used 2 times
sysctl_struct defined in line 621; never used
sysctl_text defined in line 785; used 1 times
vm_sysctl defined in line 422; used 2 times

Defined variables

debug0 defined in line 340; used 2 times
debug1 defined in line 340; used 2 times
debug10 defined in line 342; used 2 times
debug11 defined in line 342; used 2 times
debug12 defined in line 342; used 2 times
debug13 defined in line 342; used 2 times
debug14 defined in line 342; used 2 times
debug15 defined in line 343; used 2 times
debug16 defined in line 343; used 2 times
debug17 defined in line 343; used 2 times
debug18 defined in line 343; used 2 times
debug19 defined in line 343; used 2 times
debug2 defined in line 340; used 2 times
debug3 defined in line 340; used 2 times
debug4 defined in line 340; used 2 times
debug5 defined in line 341; used 2 times
debug6 defined in line 341; used 2 times
debug7 defined in line 341; used 2 times
debug8 defined in line 341; used 2 times
debug9 defined in line 341; used 2 times
debugvars defined in line 344; used 1 times
memlock defined in line 81; used 9 times

Defined struct's

sysctl_args defined in line 83; used 4 times
  • in line 95(4)
sysctl_lock defined in line 77; never used

Defined macros

FILESZ defined in line 685; used 5 times
FPTRSZ defined in line 684; used 6 times
INODESZ defined in line 756; used 4 times
IPTRSZ defined in line 755; used 5 times
KERN_PROCSLOP defined in line 834; used 1 times
TEXTSZ defined in line 801; used 5 times
TPTRSZ defined in line 800; used 6 times
Last modified: 1999-08-12
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5844
Valid CSS Valid XHTML 1.0 Strict