[BACK]Return to fstat.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / fstat

Annotation of src/usr.bin/fstat/fstat.c, Revision 1.69

1.69    ! nicm        1: /*     $OpenBSD: fstat.c,v 1.68 2009/07/08 16:04:00 millert Exp $      */
1.65      millert     2:
                      3: /*
                      4:  * Copyright (c) 2009 Todd C. Miller <Todd.Miller@courtesan.com>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
1.2       niklas     18:
1.1       deraadt    19: /*-
                     20:  * Copyright (c) 1988, 1993
                     21:  *     The Regents of the University of California.  All rights reserved.
                     22:  *
                     23:  * Redistribution and use in source and binary forms, with or without
                     24:  * modification, are permitted provided that the following conditions
                     25:  * are met:
                     26:  * 1. Redistributions of source code must retain the above copyright
                     27:  *    notice, this list of conditions and the following disclaimer.
                     28:  * 2. Redistributions in binary form must reproduce the above copyright
                     29:  *    notice, this list of conditions and the following disclaimer in the
                     30:  *    documentation and/or other materials provided with the distribution.
1.43      millert    31:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    32:  *    may be used to endorse or promote products derived from this software
                     33:  *    without specific prior written permission.
                     34:  *
                     35:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     36:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     37:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     38:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     39:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     40:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     41:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     42:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     43:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     44:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     45:  * SUCH DAMAGE.
                     46:  */
                     47:
                     48: #ifndef lint
1.68      millert    49: static const char copyright[] =
1.1       deraadt    50: "@(#) Copyright (c) 1988, 1993\n\
                     51:        The Regents of the University of California.  All rights reserved.\n";
                     52: #endif /* not lint */
                     53:
                     54: #ifndef lint
1.68      millert    55: /*static const char sccsid[] = "from: @(#)fstat.c      8.1 (Berkeley) 6/6/93";*/
1.69    ! nicm       56: static const char rcsid[] = "$OpenBSD: fstat.c,v 1.68 2009/07/08 16:04:00 millert Exp $";
1.1       deraadt    57: #endif /* not lint */
                     58:
                     59: #include <sys/param.h>
1.68      millert    60: #include <sys/queue.h>
                     61: #include <sys/mount.h>
1.1       deraadt    62: #include <sys/stat.h>
                     63: #include <sys/vnode.h>
                     64: #include <sys/socket.h>
                     65: #include <sys/socketvar.h>
1.37      deraadt    66: #include <sys/eventvar.h>
1.1       deraadt    67: #include <sys/sysctl.h>
1.65      millert    68: #define _KERNEL /* for DTYPE_* */
1.1       deraadt    69: #include <sys/file.h>
                     70: #undef _KERNEL
1.61      thib       71:
1.1       deraadt    72: #include <net/route.h>
                     73: #include <netinet/in.h>
1.26      itojun     74:
                     75: #include <netdb.h>
1.5       deraadt    76: #include <arpa/inet.h>
                     77:
1.22      art        78: #include <sys/pipe.h>
                     79:
1.1       deraadt    80: #include <ctype.h>
                     81: #include <errno.h>
1.65      millert    82: #include <fcntl.h>
1.1       deraadt    83: #include <kvm.h>
1.2       niklas     84: #include <limits.h>
1.1       deraadt    85: #include <nlist.h>
                     86: #include <pwd.h>
1.68      millert    87: #include <signal.h>
1.1       deraadt    88: #include <stdio.h>
1.65      millert    89: #include <stdint.h>
1.1       deraadt    90: #include <stdlib.h>
                     91: #include <string.h>
1.11      millert    92: #include <unistd.h>
1.17      mickey     93: #include <err.h>
1.1       deraadt    94:
1.68      millert    95: #include "fstat.h"
                     96:
                     97: struct fileargs fileargs = SLIST_HEAD_INITIALIZER(fileargs);
1.1       deraadt    98:
1.46      deraadt    99: int    fsflg;  /* show files on same filesystem as file(s) argument */
                    100: int    pflg;   /* show files open by a particular pid */
                    101: int    uflg;   /* show files open by a particular (effective) user */
1.38      deraadt   102: int    checkfile; /* true if restricting to particular files or filesystems */
1.1       deraadt   103: int    nflg;   /* (numerical) display f.s. and rdev as dev_t */
1.28      hugh      104: int    oflg;   /* display file offset */
1.56      mickey    105: int    sflg;   /* display file xfer/bytes counters */
1.1       deraadt   106: int    vflg;   /* display errors in locating kernel data objects etc... */
1.68      millert   107: int    cflg;   /* fuser only */
                    108:
                    109: int    fuser;  /* 1 if we are fuser, 0 if we are fstat */
                    110: int    signo;  /* signal to send (fuser only) */
1.1       deraadt   111:
                    112: kvm_t *kd;
1.62      deraadt   113: uid_t uid;
1.1       deraadt   114:
1.68      millert   115: void fstat_dofile(struct kinfo_file2 *);
                    116: void fstat_header(void);
                    117: void fuser_dofile(struct kinfo_file2 *);
1.35      millert   118: void getinetproto(int);
                    119: void usage(void);
                    120: int getfname(char *);
1.65      millert   121: void cryptotrans(struct kinfo_file2 *);
                    122: void kqueuetrans(struct kinfo_file2 *);
                    123: void pipetrans(struct kinfo_file2 *);
                    124: void socktrans(struct kinfo_file2 *);
                    125: void systracetrans(struct kinfo_file2 *);
                    126: void vtrans(struct kinfo_file2 *);
1.47      deraadt   127: const char *inet6_addrstr(struct in6_addr *);
1.68      millert   128: int signame_to_signum(char *);
1.1       deraadt   129:
1.11      millert   130: int
1.40      deraadt   131: main(int argc, char *argv[])
1.1       deraadt   132: {
1.32      mpech     133:        struct passwd *passwd;
1.65      millert   134:        struct kinfo_file2 *kf, *kflast;
1.1       deraadt   135:        int arg, ch, what;
1.68      millert   136:        char *memf, *nlistf, *optstr;
1.2       niklas    137:        char buf[_POSIX2_LINE_MAX];
1.58      tedu      138:        const char *errstr;
1.65      millert   139:        int cnt, flags;
1.1       deraadt   140:
1.65      millert   141:        arg = -1;
                    142:        what = KERN_FILE_BYPID;
1.1       deraadt   143:        nlistf = memf = NULL;
1.28      hugh      144:        oflg = 0;
1.68      millert   145:
                    146:        /* are we fstat(1) or fuser(1)? */
                    147:        if (strcmp(__progname, "fuser") == 0) {
                    148:                fuser = 1;
                    149:                optstr = "cfks:uM:N:";
                    150:        } else {
                    151:                fuser = 0;
                    152:                optstr = "fnop:su:vN:M:";
                    153:        }
                    154:
                    155:        /*
                    156:         * fuser and fstat share three flags: -f, -s and -u.  In both cases
                    157:         * -f is a boolean, but for -u fstat wants an argument while fuser
                    158:         * does not and for -s fuser wants an argument whereas fstat does not.
                    159:         */
                    160:        while ((ch = getopt(argc, argv, optstr)) != -1)
1.60      sobrado   161:                switch ((char)ch) {
1.68      millert   162:                case 'c':
                    163:                        if (fsflg)
                    164:                                usage();
                    165:                        cflg = 1;
                    166:                        break;
1.1       deraadt   167:                case 'f':
1.68      millert   168:                        if (cflg)
                    169:                                usage();
1.1       deraadt   170:                        fsflg = 1;
                    171:                        break;
1.68      millert   172:                case 'k':
                    173:                        sflg = 1;
                    174:                        signo = SIGKILL;
                    175:                        break;
1.1       deraadt   176:                case 'M':
                    177:                        memf = optarg;
                    178:                        break;
                    179:                case 'N':
                    180:                        nlistf = optarg;
                    181:                        break;
                    182:                case 'n':
                    183:                        nflg = 1;
                    184:                        break;
1.28      hugh      185:                case 'o':
                    186:                        oflg = 1;
                    187:                        break;
1.1       deraadt   188:                case 'p':
                    189:                        if (pflg++)
                    190:                                usage();
1.58      tedu      191:                        arg = strtonum(optarg, 0, INT_MAX, &errstr);
                    192:                        if (errstr != NULL) {
                    193:                                warnx("-p requires a process id, %s: %s",
                    194:                                        errstr, optarg);
1.1       deraadt   195:                                usage();
                    196:                        }
1.65      millert   197:                        what = KERN_FILE_BYPID;
1.1       deraadt   198:                        break;
1.56      mickey    199:                case 's':
                    200:                        sflg = 1;
1.68      millert   201:                        if (fuser) {
                    202:                                signo = signame_to_signum(optarg);
                    203:                                if (signo == -1) {
                    204:                                        warnx("invalid signal %s", optarg);
                    205:                                        usage();
                    206:                                }
                    207:                        }
1.56      mickey    208:                        break;
1.1       deraadt   209:                case 'u':
                    210:                        if (uflg++)
                    211:                                usage();
1.68      millert   212:                        if (!fuser) {
1.69    ! nicm      213:                                if (!(passwd = getpwnam(optarg))) {
        !           214:                                        arg = strtonum(optarg, 0, UID_MAX,
        !           215:                                            &errstr);
        !           216:                                        if (errstr != NULL) {
        !           217:                                                errx(1, "%s: unknown uid",
        !           218:                                                    optarg);
        !           219:                                        }
        !           220:                                } else
        !           221:                                        arg = passwd->pw_uid;
1.68      millert   222:                                what = KERN_FILE_BYUID;
                    223:                        }
1.1       deraadt   224:                        break;
                    225:                case 'v':
                    226:                        vflg = 1;
                    227:                        break;
                    228:                default:
                    229:                        usage();
                    230:                }
                    231:
1.41      deraadt   232:        /*
1.62      deraadt   233:         * get the uid, for oflg and sflg
                    234:         */
                    235:        uid = getuid();
                    236:
                    237:        /*
1.65      millert   238:         * Use sysctl unless inspecting an alternate kernel.
1.41      deraadt   239:         */
1.65      millert   240:        if (nlistf == NULL || memf == NULL)
                    241:                flags = KVM_NO_FILES;
                    242:        else
                    243:                flags = O_RDONLY;
1.41      deraadt   244:
1.65      millert   245:        if ((kd = kvm_openfiles(nlistf, memf, NULL, flags, buf)) == NULL)
1.41      deraadt   246:                errx(1, "%s", buf);
                    247:
1.1       deraadt   248:        if (*(argv += optind)) {
                    249:                for (; *argv; ++argv) {
                    250:                        if (getfname(*argv))
                    251:                                checkfile = 1;
                    252:                }
1.68      millert   253:                /* file(s) specified, but none accessible */
                    254:                if (!checkfile)
1.1       deraadt   255:                        exit(1);
1.68      millert   256:        } else if (fuser)
                    257:                usage();
1.1       deraadt   258:
1.68      millert   259:        if (!fuser && fsflg && !checkfile) {
                    260:                /* fstat -f with no files means use wd */
1.1       deraadt   261:                if (getfname(".") == 0)
                    262:                        exit(1);
                    263:                checkfile = 1;
                    264:        }
1.16      deraadt   265:
1.65      millert   266:        if ((kf = kvm_getfile2(kd, what, arg, sizeof(*kf), &cnt)) == NULL)
1.21      deraadt   267:                errx(1, "%s", kvm_geterr(kd));
1.68      millert   268:
                    269:        if (!fuser)
                    270:                fstat_header();
                    271:        for (kflast = &kf[cnt]; kf < kflast; ++kf) {
                    272:                if (fuser)
                    273:                        fuser_check(kf);
                    274:                else
                    275:                        fstat_dofile(kf);
                    276:        }
                    277:        if (fuser)
                    278:                fuser_run();
                    279:
                    280:        exit(0);
                    281: }
                    282:
                    283: void
                    284: fstat_header(void)
                    285: {
1.1       deraadt   286:        if (nflg)
                    287:                printf("%s",
1.60      sobrado   288: "USER     CMD          PID   FD  DEV      INUM       MODE R/W    SZ|DV");
1.1       deraadt   289:        else
                    290:                printf("%s",
1.60      sobrado   291: "USER     CMD          PID   FD MOUNT        INUM MODE       R/W    SZ|DV");
1.28      hugh      292:        if (oflg)
                    293:                printf("%s", ":OFFSET  ");
1.1       deraadt   294:        if (checkfile && fsflg == 0)
1.56      mickey    295:                printf(" NAME");
                    296:        if (sflg)
                    297:                printf("    XFERS   KBYTES");
                    298:        putchar('\n');
1.1       deraadt   299: }
                    300:
                    301: char   *Uname, *Comm;
1.62      deraadt   302: uid_t  *procuid;
1.14      deraadt   303: pid_t  Pid;
1.1       deraadt   304:
1.34      deraadt   305: #define PREFIX(i) do { \
1.39      mpech     306:        printf("%-8.8s %-10s %5ld", Uname, Comm, (long)Pid); \
1.60      sobrado   307:        switch (i) { \
1.65      millert   308:        case KERN_FILE_TEXT: \
1.1       deraadt   309:                printf(" text"); \
                    310:                break; \
1.65      millert   311:        case KERN_FILE_CDIR: \
1.1       deraadt   312:                printf("   wd"); \
                    313:                break; \
1.65      millert   314:        case KERN_FILE_RDIR: \
1.1       deraadt   315:                printf(" root"); \
                    316:                break; \
1.65      millert   317:        case KERN_FILE_TRACE: \
1.1       deraadt   318:                printf("   tr"); \
                    319:                break; \
                    320:        default: \
                    321:                printf(" %4d", i); \
                    322:                break; \
1.34      deraadt   323:        } \
                    324: } while (0)
1.1       deraadt   325:
                    326: /*
                    327:  * print open files attributed to this process
                    328:  */
                    329: void
1.68      millert   330: fstat_dofile(struct kinfo_file2 *kf)
1.1       deraadt   331: {
                    332:
1.65      millert   333:        Uname = user_from_uid(kf->p_uid, 0);
                    334:        procuid = &kf->p_uid;
                    335:        Pid = kf->p_pid;
                    336:        Comm = kf->p_comm;
1.56      mickey    337:
1.65      millert   338:        switch (kf->f_type) {
                    339:        case DTYPE_VNODE:
                    340:                vtrans(kf);
                    341:                break;
                    342:        case DTYPE_SOCKET:
1.67      miod      343:                if (checkfile == 0)
                    344:                        socktrans(kf);
1.65      millert   345:                break;
                    346:        case DTYPE_PIPE:
1.67      miod      347:                if (checkfile == 0)
                    348:                        pipetrans(kf);
1.65      millert   349:                break;
                    350:        case DTYPE_KQUEUE:
1.67      miod      351:                if (checkfile == 0)
                    352:                        kqueuetrans(kf);
1.65      millert   353:                break;
                    354:        case DTYPE_CRYPTO:
1.67      miod      355:                if (checkfile == 0)
                    356:                        cryptotrans(kf);
1.65      millert   357:                break;
                    358:        case DTYPE_SYSTRACE:
1.67      miod      359:                if (checkfile == 0)
                    360:                        systracetrans(kf);
1.65      millert   361:                break;
                    362:        default:
                    363:                if (vflg) {
                    364:                        warnx("unknown file type %d for file %d of pid %ld",
                    365:                            kf->f_type, kf->fd_fd, (long)Pid);
1.1       deraadt   366:                }
1.65      millert   367:                break;
1.1       deraadt   368:        }
                    369: }
                    370:
                    371: void
1.65      millert   372: vtrans(struct kinfo_file2 *kf)
1.1       deraadt   373: {
1.65      millert   374:        const char *badtype = NULL;
                    375:        char rw[3], mode[12];
                    376:        char *filename = NULL;
                    377:
                    378:        if (kf->v_type == VNON)
1.1       deraadt   379:                badtype = "none";
1.65      millert   380:        else if (kf->v_type == VBAD)
1.1       deraadt   381:                badtype = "bad";
1.65      millert   382:        else if (kf->v_tag == VT_NON && !(kf->v_flag & VCLONE))
                    383:                badtype = "none";       /* not a clone */
                    384:
1.1       deraadt   385:        if (checkfile) {
                    386:                int fsmatch = 0;
1.68      millert   387:                struct filearg *fa;
1.1       deraadt   388:
                    389:                if (badtype)
                    390:                        return;
1.68      millert   391:                SLIST_FOREACH(fa, &fileargs, next) {
                    392:                        if (fa->dev == kf->va_fsid) {
1.1       deraadt   393:                                fsmatch = 1;
1.68      millert   394:                                if (fa->ino == kf->va_fileid) {
                    395:                                        filename = fa->name;
1.1       deraadt   396:                                        break;
                    397:                                }
                    398:                        }
1.65      millert   399:                }
1.1       deraadt   400:                if (fsmatch == 0 || (filename == NULL && fsflg == 0))
                    401:                        return;
                    402:        }
1.65      millert   403:        PREFIX(kf->fd_fd);
1.1       deraadt   404:        if (badtype) {
1.53      mickey    405:                (void)printf(" -           -  %10s    -\n", badtype);
1.1       deraadt   406:                return;
                    407:        }
1.61      thib      408:
1.1       deraadt   409:        if (nflg)
1.65      millert   410:                (void)printf(" %2ld,%-2ld", (long)major(kf->va_fsid),
                    411:                    (long)minor(kf->va_fsid));
                    412:        else if (!(kf->v_flag & VCLONE))
                    413:                (void)printf(" %-8s", kf->f_mntonname);
1.1       deraadt   414:        else
1.61      thib      415:                (void)printf(" clone");
1.1       deraadt   416:        if (nflg)
1.65      millert   417:                (void)snprintf(mode, sizeof(mode), "%o", kf->va_mode);
1.1       deraadt   418:        else
1.65      millert   419:                strmode(kf->va_mode, mode);
                    420:        printf(" %8llu %11s", kf->va_fileid, mode);
1.28      hugh      421:        rw[0] = '\0';
1.65      millert   422:        if (kf->f_flag & FREAD)
1.34      deraadt   423:                strlcat(rw, "r", sizeof rw);
1.65      millert   424:        if (kf->f_flag & FWRITE)
1.34      deraadt   425:                strlcat(rw, "w", sizeof rw);
1.28      hugh      426:        printf(" %2s", rw);
1.65      millert   427:        switch (kf->v_type) {
1.1       deraadt   428:        case VBLK:
                    429:        case VCHR: {
                    430:                char *name;
                    431:
1.65      millert   432:                if (nflg || ((name = devname(kf->va_rdev,
                    433:                    kf->v_type == VCHR ?  S_IFCHR : S_IFBLK)) == NULL))
                    434:                        printf("   %2d,%-3d", major(kf->va_rdev), minor(kf->va_rdev));
1.1       deraadt   435:                else
1.28      hugh      436:                        printf("  %7s", name);
                    437:                if (oflg)
                    438:                        printf("         ");
1.1       deraadt   439:                break;
                    440:        }
                    441:        default:
1.65      millert   442:                printf(" %8llu", kf->va_size);
1.62      deraadt   443:                if (oflg) {
                    444:                        if (uid == 0 || uid == *procuid)
1.65      millert   445:                                printf(":%-8llu", kf->f_offset);
1.62      deraadt   446:                        else
                    447:                                printf(":%-8s", "*");
                    448:                }
                    449:        }
                    450:        if (sflg) {
                    451:                if (uid == 0 || uid == *procuid) {
1.65      millert   452:                        printf(" %8llu %8llu",
                    453:                        (kf->f_rxfer + kf->f_rwfer),
                    454:                        (kf->f_rbytes + kf->f_wbytes) / 1024);
1.62      deraadt   455:                } else {
                    456:                        printf(" %8s %8s", "*", "*");
                    457:                }
1.1       deraadt   458:        }
                    459:        if (filename && !fsflg)
1.28      hugh      460:                printf(" %s", filename);
1.1       deraadt   461:        putchar('\n');
                    462: }
                    463:
1.22      art       464: void
1.65      millert   465: pipetrans(struct kinfo_file2 *kf)
1.22      art       466: {
                    467:        void *maxaddr;
                    468:
1.65      millert   469:        PREFIX(kf->fd_fd);
1.22      art       470:
                    471:        printf(" ");
                    472:
                    473:        /*
                    474:         * We don't have enough space to fit both peer and own address, so
                    475:         * we select the higher address so both ends of the pipe have the
                    476:         * same visible addr. (it's the higher address because when the other
                    477:         * end closes, it becomes 0)
                    478:         */
1.65      millert   479:        maxaddr = (void *)(uintptr_t)MAX(kf->f_data, kf->pipe_peer);
1.22      art       480:
1.56      mickey    481:        printf("pipe %p state: %s%s%s", maxaddr,
1.65      millert   482:            (kf->pipe_state & PIPE_WANTR) ? "R" : "",
                    483:            (kf->pipe_state & PIPE_WANTW) ? "W" : "",
                    484:            (kf->pipe_state & PIPE_EOF) ? "E" : "");
1.56      mickey    485:        if (sflg)
1.65      millert   486:                printf("\t%8llu %8llu",
                    487:                    (kf->f_rxfer + kf->f_rwfer),
                    488:                    (kf->f_rbytes + kf->f_wbytes) / 1024);
1.56      mickey    489:        printf("\n");
1.37      deraadt   490:        return;
                    491: }
                    492:
                    493: void
1.65      millert   494: kqueuetrans(struct kinfo_file2 *kf)
1.37      deraadt   495: {
1.65      millert   496:        PREFIX(kf->fd_fd);
1.37      deraadt   497:
                    498:        printf(" ");
                    499:
1.65      millert   500:        printf("kqueue %p %d state: %s%s\n", (void *)(uintptr_t)kf->f_data,
                    501:            kf->kq_count,
                    502:            (kf->kq_state & KQ_SEL) ? "S" : "",
                    503:            (kf->kq_state & KQ_SLEEP) ? "W" : "");
1.37      deraadt   504:        return;
                    505: }
                    506:
                    507: void
1.65      millert   508: cryptotrans(struct kinfo_file2 *kf)
1.37      deraadt   509: {
1.65      millert   510:        PREFIX(kf->fd_fd);
1.37      deraadt   511:
                    512:        printf(" ");
                    513:
1.65      millert   514:        printf("crypto %p\n", (void *)(uintptr_t)kf->f_data);
1.37      deraadt   515: }
                    516:
                    517: void
1.65      millert   518: systracetrans(struct kinfo_file2 *kf)
1.37      deraadt   519: {
1.65      millert   520:        PREFIX(kf->fd_fd);
1.37      deraadt   521:
                    522:        printf(" ");
                    523:
1.65      millert   524:        printf("systrace %p npol %d\n", (void *)(uintptr_t)kf->f_data,
                    525:            kf->str_npolicies);
1.22      art       526:        return;
1.1       deraadt   527: }
                    528:
1.26      itojun    529: #ifdef INET6
                    530: const char *
1.40      deraadt   531: inet6_addrstr(struct in6_addr *p)
1.26      itojun    532: {
                    533:        struct sockaddr_in6 sin6;
                    534:        static char hbuf[NI_MAXHOST];
1.50      itojun    535:        const int niflags = NI_NUMERICHOST;
1.26      itojun    536:
                    537:        memset(&sin6, 0, sizeof(sin6));
                    538:        sin6.sin6_family = AF_INET6;
                    539:        sin6.sin6_len = sizeof(struct sockaddr_in6);
                    540:        sin6.sin6_addr = *p;
                    541:        if (IN6_IS_ADDR_LINKLOCAL(p) &&
                    542:            *(u_int16_t *)&sin6.sin6_addr.s6_addr[2] != 0) {
                    543:                sin6.sin6_scope_id =
1.38      deraadt   544:                    ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
1.26      itojun    545:                sin6.sin6_addr.s6_addr[2] = sin6.sin6_addr.s6_addr[3] = 0;
                    546:        }
                    547:
                    548:        if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
1.38      deraadt   549:            hbuf, sizeof(hbuf), NULL, 0, niflags))
1.26      itojun    550:                return "invalid";
                    551:
                    552:        return hbuf;
                    553: }
                    554: #endif
                    555:
1.1       deraadt   556: void
1.65      millert   557: socktrans(struct kinfo_file2 *kf)
1.1       deraadt   558: {
                    559:        static char *stypename[] = {
                    560:                "unused",       /* 0 */
1.38      deraadt   561:                "stream",       /* 1 */
1.1       deraadt   562:                "dgram",        /* 2 */
                    563:                "raw",          /* 3 */
                    564:                "rdm",          /* 4 */
                    565:                "seqpak"        /* 5 */
                    566:        };
                    567: #define        STYPEMAX 5
1.66      chl       568:        char *stype, stypebuf[24];
1.65      millert   569:        struct in_addr laddr, faddr;
1.26      itojun    570: #ifdef INET6
                    571:        char xaddrbuf[NI_MAXHOST + 2];
1.65      millert   572:        struct in6_addr laddr6, faddr6;
1.26      itojun    573: #endif
1.1       deraadt   574:
1.65      millert   575:        PREFIX(kf->fd_fd);
1.1       deraadt   576:
1.65      millert   577:        if (kf->so_type > STYPEMAX) {
                    578:                snprintf(stypebuf, sizeof(stypebuf), "?%d", kf->so_type);
                    579:                stype = stypebuf;
                    580:        } else {
                    581:                stype = stypename[kf->so_type];
1.1       deraadt   582:        }
                    583:
1.34      deraadt   584:        /*
1.1       deraadt   585:         * protocol specific formatting
                    586:         *
                    587:         * Try to find interesting things to print.  For tcp, the interesting
                    588:         * thing is the address of the tcpcb, for udp and others, just the
                    589:         * inpcb (socket pcb).  For unix domain, its the address of the socket
                    590:         * pcb and the address of the connected pcb (if connected).  Otherwise
                    591:         * just print the protocol number and address of the socket itself.
                    592:         * The idea is not to duplicate netstat, but to make available enough
                    593:         * information for further analysis.
                    594:         */
1.65      millert   595:        switch (kf->so_family) {
1.1       deraadt   596:        case AF_INET:
1.65      millert   597:                printf("* internet %s", stype);
                    598:                memcpy(&laddr, kf->inp_laddru, sizeof(laddr));
                    599:                memcpy(&faddr, kf->inp_faddru, sizeof(faddr));
                    600:                getinetproto(kf->so_protocol);
                    601:                if (kf->so_protocol == IPPROTO_TCP) {
1.68      millert   602:                        printf(" %p", (void *)(uintptr_t)kf->inp_ppcb);
1.65      millert   603:                        printf(" %s:%d", laddr.s_addr == INADDR_ANY ? "*" :
                    604:                            inet_ntoa(laddr), ntohs(kf->inp_lport));
                    605:                        if (kf->inp_fport) {
                    606:                                if (kf->so_state & SS_CONNECTOUT)
1.13      deraadt   607:                                        printf(" --> ");
                    608:                                else
                    609:                                        printf(" <-- ");
                    610:                                printf("%s:%d",
1.65      millert   611:                                    faddr.s_addr == INADDR_ANY ? "*" :
                    612:                                    inet_ntoa(faddr), ntohs(kf->inp_fport));
1.17      mickey    613:                        }
1.65      millert   614:                } else if (kf->so_protocol == IPPROTO_UDP) {
                    615:                        printf(" %s:%d", laddr.s_addr == INADDR_ANY ? "*" :
                    616:                            inet_ntoa(laddr), ntohs(kf->inp_lport));
                    617:                        if (kf->inp_fport) {
                    618:                                printf(" <-> %s:%d",
                    619:                                    faddr.s_addr == INADDR_ANY ? "*" :
                    620:                                    inet_ntoa(faddr), ntohs(kf->inp_fport));
1.1       deraadt   621:                        }
1.65      millert   622:                } else if (kf->so_pcb)
1.68      millert   623:                        printf(" %p", (void *)(uintptr_t)kf->so_pcb);
1.1       deraadt   624:                break;
1.26      itojun    625: #ifdef INET6
                    626:        case AF_INET6:
1.65      millert   627:                printf("* internet6 %s", stype);
                    628:                memcpy(&laddr6, kf->inp_laddru, sizeof(laddr6));
                    629:                memcpy(&faddr6, kf->inp_faddru, sizeof(faddr6));
                    630:                getinetproto(kf->so_protocol);
                    631:                if (kf->so_protocol == IPPROTO_TCP) {
1.68      millert   632:                        printf(" %p", (void *)(uintptr_t)kf->inp_ppcb);
1.26      itojun    633:                        snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
1.65      millert   634:                            inet6_addrstr(&laddr6));
1.26      itojun    635:                        printf(" %s:%d",
1.65      millert   636:                            IN6_IS_ADDR_UNSPECIFIED(&laddr6) ? "*" :
                    637:                            xaddrbuf, ntohs(kf->inp_lport));
                    638:                        if (kf->inp_fport) {
                    639:                                if (kf->so_state & SS_CONNECTOUT)
1.26      itojun    640:                                        printf(" --> ");
                    641:                                else
                    642:                                        printf(" <-- ");
                    643:                                snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
1.65      millert   644:                                    inet6_addrstr(&faddr6));
1.26      itojun    645:                                printf("%s:%d",
1.65      millert   646:                                    IN6_IS_ADDR_UNSPECIFIED(&faddr6) ? "*" :
                    647:                                    xaddrbuf, ntohs(kf->inp_fport));
1.26      itojun    648:                        }
1.65      millert   649:                } else if (kf->so_protocol == IPPROTO_UDP) {
1.26      itojun    650:                        snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
1.65      millert   651:                            inet6_addrstr(&laddr6));
1.26      itojun    652:                        printf(" %s:%d",
1.65      millert   653:                            IN6_IS_ADDR_UNSPECIFIED(&laddr6) ? "*" :
                    654:                            xaddrbuf, ntohs(kf->inp_lport));
                    655:                        if (kf->inp_fport) {
1.26      itojun    656:                                snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
1.65      millert   657:                                    inet6_addrstr(&faddr6));
1.26      itojun    658:                                printf(" <-> %s:%d",
1.65      millert   659:                                    IN6_IS_ADDR_UNSPECIFIED(&faddr6) ? "*" :
                    660:                                    xaddrbuf, ntohs(kf->inp_fport));
1.33      itojun    661:                        }
1.65      millert   662:                } else if (kf->so_pcb)
1.68      millert   663:                        printf(" %p", (void *)(uintptr_t)kf->so_pcb);
1.26      itojun    664:                break;
                    665: #endif
1.1       deraadt   666:        case AF_UNIX:
                    667:                /* print address of pcb and connected pcb */
1.65      millert   668:                printf("* unix %s", stype);
                    669:                if (kf->so_pcb) {
1.68      millert   670:                        printf(" %p", (void *)(uintptr_t)kf->so_pcb);
1.65      millert   671:                        if (kf->unp_conn) {
1.1       deraadt   672:                                char shoconn[4], *cp;
                    673:
                    674:                                cp = shoconn;
1.65      millert   675:                                if (!(kf->so_state & SS_CANTRCVMORE))
1.1       deraadt   676:                                        *cp++ = '<';
                    677:                                *cp++ = '-';
1.65      millert   678:                                if (!(kf->so_state & SS_CANTSENDMORE))
1.1       deraadt   679:                                        *cp++ = '>';
                    680:                                *cp = '\0';
1.11      millert   681:                                printf(" %s %p", shoconn,
1.65      millert   682:                                    (void *)(uintptr_t)kf->unp_conn);
1.1       deraadt   683:                        }
                    684:                }
                    685:                break;
1.65      millert   686:        case AF_MPLS:
                    687:                /* print protocol number and socket address */
                    688:                printf("* mpls %s", stype);
                    689:                printf(" %d %p", kf->so_protocol,
                    690:                    (void *)(uintptr_t)kf->f_data);
                    691:                break;
                    692:        case AF_ROUTE:
                    693:                /* print protocol number and socket address */
                    694:                printf("* route %s", stype);
                    695:                printf(" %d %p", kf->so_protocol,
                    696:                    (void *)(uintptr_t)kf->f_data);
                    697:                break;
                    698:        case AF_BLUETOOTH:
                    699:                /* print protocol number and socket address */
                    700:                printf("* bluetooth %s", stype);
                    701:                printf(" %d %p", kf->so_protocol,
                    702:                    (void *)(uintptr_t)kf->f_data);
                    703:                break;
                    704:        case AF_NATM:
                    705:                /* print protocol number and socket address */
                    706:                printf("* natm %s", stype);
                    707:                printf(" %d %p", kf->so_protocol,
                    708:                    (void *)(uintptr_t)kf->f_data);
                    709:                break;
                    710:        case AF_APPLETALK:
                    711:                /* print protocol number and socket address */
                    712:                printf("* appletalk %s", stype);
                    713:                printf(" %d %p", kf->so_protocol,
                    714:                    (void *)(uintptr_t)kf->f_data);
                    715:                break;
1.1       deraadt   716:        default:
                    717:                /* print protocol number and socket address */
1.65      millert   718:                printf("* %d %s", kf->so_family, stype);
                    719:                printf(" %d %p", kf->so_protocol,
                    720:                    (void *)(uintptr_t)kf->f_data);
1.1       deraadt   721:        }
1.56      mickey    722:        if (sflg)
1.65      millert   723:                printf("\t%8llu %8llu",
                    724:                    (kf->f_rxfer + kf->f_rwfer),
                    725:                    (kf->f_rbytes + kf->f_wbytes) / 1024);
1.1       deraadt   726:        printf("\n");
                    727: }
                    728:
                    729: /*
                    730:  * getinetproto --
                    731:  *     print name of protocol number
                    732:  */
                    733: void
                    734: getinetproto(number)
                    735:        int number;
                    736: {
1.24      deraadt   737:        static int isopen;
1.32      mpech     738:        struct protoent *pe;
1.1       deraadt   739:
1.24      deraadt   740:        if (!isopen)
                    741:                setprotoent(++isopen);
                    742:        if ((pe = getprotobynumber(number)) != NULL)
                    743:                printf(" %s", pe->p_name);
                    744:        else
1.1       deraadt   745:                printf(" %d", number);
                    746: }
                    747:
1.11      millert   748: int
1.40      deraadt   749: getfname(char *filename)
1.1       deraadt   750: {
1.68      millert   751:        static struct statfs *mntbuf;
                    752:        static int nmounts;
                    753:        int i;
                    754:        struct stat sb;
                    755:        struct filearg *cur;
1.1       deraadt   756:
1.68      millert   757:        if (stat(filename, &sb)) {
1.27      millert   758:                warn("%s", filename);
1.68      millert   759:                return (0);
1.1       deraadt   760:        }
                    761:
1.68      millert   762:        /*
                    763:         * POSIX specifies "For block special devices, all processes using any
                    764:         * file on that device are listed".  However the -f flag description
                    765:         * states "The report shall be only for the named files", so we only
                    766:         * look up a block device if the -f flag has not be specified.
                    767:         */
                    768:        if (fuser && !fsflg && S_ISBLK(sb.st_mode)) {
                    769:                if (mntbuf == NULL) {
                    770:                        nmounts = getmntinfo(&mntbuf, MNT_NOWAIT);
                    771:                        if (nmounts == -1)
                    772:                                err(1, "getmntinfo");
                    773:                }
                    774:                for (i = 0; i < nmounts; i++) {
                    775:                        if (!strcmp(mntbuf[i].f_mntfromname, filename)) {
                    776:                                if (stat(mntbuf[i].f_mntonname, &sb) == -1) {
                    777:                                        warn("%s", filename);
                    778:                                        return (0);
                    779:                                }
                    780:                                cflg = 1;
                    781:                                break;
                    782:                        }
                    783:                }
                    784:        }
                    785:
                    786:        if ((cur = malloc(sizeof(*cur))) == NULL)
                    787:                err(1, NULL);
                    788:
                    789:        cur->ino = sb.st_ino;
                    790:        cur->dev = sb.st_dev & 0xffff;
1.1       deraadt   791:        cur->name = filename;
1.68      millert   792:        TAILQ_INIT(&cur->fusers);
                    793:        SLIST_INSERT_HEAD(&fileargs, cur, next);
                    794:        return (1);
                    795: }
                    796:
                    797: int
                    798: signame_to_signum(char *sig)
                    799: {
                    800:        int n;
                    801:        const char *errstr = NULL;
                    802:
                    803:        if (isdigit((unsigned char)*sig)) {
                    804:                n = strtonum(sig, 0, NSIG - 1, &errstr);
                    805:                return (errstr ? -1 : n);
                    806:        }
                    807:        if (!strncasecmp(sig, "sig", 3))
                    808:                sig += 3;
                    809:        for (n = 1; n < NSIG; n++) {
                    810:                if (!strcasecmp(sys_signame[n], sig))
                    811:                        return (n);
                    812:        }
                    813:        return (-1);
1.1       deraadt   814: }
                    815:
                    816: void
1.40      deraadt   817: usage(void)
1.1       deraadt   818: {
1.68      millert   819:        if (fuser) {
                    820:                fprintf(stderr, "usage: fuser [-cfku] [-M core] "
                    821:                    "[-N system] [-s signal] file ...\n");
                    822:        } else {
                    823:                fprintf(stderr, "usage: fstat [-fnosv] [-M core] [-N system] "
                    824:                    "[-p pid] [-u user] [file ...]\n");
                    825:        }
1.1       deraadt   826:        exit(1);
                    827: }