# 2.11BSD#431 - /usr/src/sys/sys/kern_sysctl.c

##### Functions

    NET_SYSCTL        X
    __sysctl          X
    debug_sysctl      X
    fill_eproc        X
    fill_from_u       X
    hw_sysctl         X
    kern_sysctl       X
    sysctl_clockrate  X
    sysctl_doproc     X
    sysctl_file       X
    sysctl_inode      X
    sysctl_int        X
    sysctl_long       X
    sysctl_rdint      X
    sysctl_rdlong     X
    sysctl_rdstring   X
    sysctl_rdstruct   X
    sysctl_string     X
    sysctl_struct     X
    sysctl_text       X
    vm_sysctl         X

##### Variables

    debug0            X
    debug1            X
    debug10           X
    debug11           X
    debug12           X
    debug13           X
    debug14           X
    debug15           X
    debug16           X
    debug17           X
    debug18           X
    debug19           X
    debug2            X
    debug3            X
    debug4            X
    debug5            X
    debug6            X
    debug7            X
    debug8            X
    debug9            X

##### Macros

    FILESZ            X
    FPTRSZ            X
    INODESZ           X
    IPTRSZ            X
    KERN_PROCSLOP     X
    TEXTSZ            X
    TPTRSZ            X

##### struct's

    sysctl_args       X
    sysctl_lock       X

       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

- in line 69, 123

__sysctl defined in line 92; used 2 times

- in /usr/src/sys/sys/init_sysent.c line 51, 133

cpu2str defined in line 320; used 2 times

- in line 291, 303

debug_sysctl defined in line 350; used 2 times

- in line 64, 136

fill_eproc defined in line 939; used 2 times

- in line 905
- in /usr/src/sys/h/sysctl.h line 349

fill_from_u defined in line 968; used 4 times

- in line 883, 894, 947
- in /usr/src/sys/sys/kern_sig.c line 44

hw_sysctl defined in line 282; used 2 times

- in line 62, 116

kern_sysctl defined in line 178; used 2 times

- in line 61, 113

sysctl_clockrate defined in line 720; used 1 times

- in line 249

sysctl_doproc defined in line 836; used 1 times

- in line 256

sysctl_file defined in line 669; used 1 times

- in line 258

sysctl_inode defined in line 742; used 1 times

- in line 254

sysctl_int defined in line 477; used 14 times

- in line 205, 230, 371
- in /usr/src/sys/h/sysctl.h line 344
- in /usr/src/sys/netinet/ip_icmp.c line 473
- in /usr/src/sys/netinet/ip_input.c line 1017-1028(5)
- in /usr/src/sys/netinet/udp_usrreq.c line 441
- in /usr/src/sys/pdp/kern_pdp.c line 236-239(2), 253

sysctl_long defined in line 523; used 1 times

- in line 245

sysctl_rdint defined in line 501; used 12 times

- in line 219-227(5), 267-272(3), 305-307(2), 313
- in /usr/src/sys/h/sysctl.h line 345

sysctl_rdlong defined in line 547; used 3 times

- in line 215, 309-311(2)

sysctl_rdstring defined in line 598; used 6 times

- in line 202, 217, 300-302(2), 369
- in /usr/src/sys/h/sysctl.h line 347

sysctl_rdstruct defined in line 648; used 8 times

- in line 251, 443, 449, 457, 465, 734
- in /usr/src/sys/h/sysctl.h line 348
- in /usr/src/sys/pdp/kern_pdp.c line 226

sysctl_string defined in line 569; used 2 times

- in line 238
- in /usr/src/sys/h/sysctl.h line 346

sysctl_struct defined in line 621; never used
sysctl_text defined in line 785; used 1 times

- in line 260

vm_sysctl defined in line 422; used 2 times

- in line 66, 119

#### Defined variables

debug0 defined in line 340; used 2 times

- in line 345
- in /usr/src/sys/sys/kern_sysctl.c line 345

debug1 defined in line 340; used 2 times

- in line 345
- in /usr/src/sys/sys/kern_sysctl.c line 345

debug10 defined in line 342; used 2 times

- in line 347
- in /usr/src/sys/sys/kern_sysctl.c line 347

debug11 defined in line 342; used 2 times

- in line 347
- in /usr/src/sys/sys/kern_sysctl.c line 347

debug12 defined in line 342; used 2 times

- in line 347
- in /usr/src/sys/sys/kern_sysctl.c line 347

debug13 defined in line 342; used 2 times

- in line 347
- in /usr/src/sys/sys/kern_sysctl.c line 347

debug14 defined in line 342; used 2 times

- in line 347
- in /usr/src/sys/sys/kern_sysctl.c line 347

debug15 defined in line 343; used 2 times

- in line 348
- in /usr/src/sys/sys/kern_sysctl.c line 348

debug16 defined in line 343; used 2 times

- in line 348
- in /usr/src/sys/sys/kern_sysctl.c line 348

debug17 defined in line 343; used 2 times

- in line 348
- in /usr/src/sys/sys/kern_sysctl.c line 348

debug18 defined in line 343; used 2 times

- in line 348
- in /usr/src/sys/sys/kern_sysctl.c line 348

debug19 defined in line 343; used 2 times

- in line 348
- in /usr/src/sys/sys/kern_sysctl.c line 348

debug2 defined in line 340; used 2 times

- in line 345
- in /usr/src/sys/sys/kern_sysctl.c line 345

debug3 defined in line 340; used 2 times

- in line 345
- in /usr/src/sys/sys/kern_sysctl.c line 345

debug4 defined in line 340; used 2 times

- in line 345
- in /usr/src/sys/sys/kern_sysctl.c line 345

debug5 defined in line 341; used 2 times

- in line 346
- in /usr/src/sys/sys/kern_sysctl.c line 346

debug6 defined in line 341; used 2 times

- in line 346
- in /usr/src/sys/sys/kern_sysctl.c line 346

debug7 defined in line 341; used 2 times

- in line 346
- in /usr/src/sys/sys/kern_sysctl.c line 346

debug8 defined in line 341; used 2 times

- in line 346
- in /usr/src/sys/sys/kern_sysctl.c line 346

debug9 defined in line 341; used 2 times

- in line 346
- in /usr/src/sys/sys/kern_sysctl.c line 346

debugvars defined in line 344; used 1 times

- in line 364

memlock defined in line 81; used 9 times

- in line 147-152(5), 158-161(4)

#### 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

- in line 689, 700, 706-709(3)

FPTRSZ defined in line 684; used 6 times

- in line 689, 700-709(5)

INODESZ defined in line 756; used 4 times

- in line 758, 766, 772-774(2)

IPTRSZ defined in line 755; used 5 times

- in line 758, 766-774(4)

KERN_PROCSLOP defined in line 834; used 1 times

- in line 927

TEXTSZ defined in line 801; used 5 times

- in line 805, 816, 822-825(3)

TPTRSZ defined in line 800; used 6 times

- in line 805, 816-825(5)

Last modified: 1999-08-12 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2389 |