[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.81

1.81    ! deraadt     1: /*     $OpenBSD: fstat.c,v 1.80 2015/01/16 06:40:08 deraadt 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:
1.80      deraadt    48: #include <sys/types.h>
1.68      millert    49: #include <sys/queue.h>
                     50: #include <sys/mount.h>
1.1       deraadt    51: #include <sys/stat.h>
                     52: #include <sys/vnode.h>
                     53: #include <sys/socket.h>
                     54: #include <sys/socketvar.h>
1.37      deraadt    55: #include <sys/eventvar.h>
1.1       deraadt    56: #include <sys/sysctl.h>
1.65      millert    57: #define _KERNEL /* for DTYPE_* */
1.1       deraadt    58: #include <sys/file.h>
                     59: #undef _KERNEL
1.61      thib       60:
1.1       deraadt    61: #include <net/route.h>
                     62: #include <netinet/in.h>
1.26      itojun     63:
                     64: #include <netdb.h>
1.5       deraadt    65: #include <arpa/inet.h>
                     66:
1.22      art        67: #include <sys/pipe.h>
                     68:
1.1       deraadt    69: #include <ctype.h>
                     70: #include <errno.h>
1.65      millert    71: #include <fcntl.h>
1.1       deraadt    72: #include <kvm.h>
1.2       niklas     73: #include <limits.h>
1.1       deraadt    74: #include <nlist.h>
                     75: #include <pwd.h>
1.72      guenther   76: #include <search.h>
1.68      millert    77: #include <signal.h>
1.1       deraadt    78: #include <stdio.h>
1.65      millert    79: #include <stdint.h>
1.1       deraadt    80: #include <stdlib.h>
                     81: #include <string.h>
1.11      millert    82: #include <unistd.h>
1.17      mickey     83: #include <err.h>
1.1       deraadt    84:
1.68      millert    85: #include "fstat.h"
                     86:
1.80      deraadt    87: #define MAXIMUM(a, b)  (((a) > (b)) ? (a) : (b))
                     88:
1.68      millert    89: struct fileargs fileargs = SLIST_HEAD_INITIALIZER(fileargs);
1.1       deraadt    90:
1.46      deraadt    91: int    fsflg;  /* show files on same filesystem as file(s) argument */
                     92: int    pflg;   /* show files open by a particular pid */
                     93: int    uflg;   /* show files open by a particular (effective) user */
1.38      deraadt    94: int    checkfile; /* true if restricting to particular files or filesystems */
1.1       deraadt    95: int    nflg;   /* (numerical) display f.s. and rdev as dev_t */
1.28      hugh       96: int    oflg;   /* display file offset */
1.56      mickey     97: int    sflg;   /* display file xfer/bytes counters */
1.1       deraadt    98: int    vflg;   /* display errors in locating kernel data objects etc... */
1.68      millert    99: int    cflg;   /* fuser only */
                    100:
                    101: int    fuser;  /* 1 if we are fuser, 0 if we are fstat */
                    102: int    signo;  /* signal to send (fuser only) */
1.1       deraadt   103:
                    104: kvm_t *kd;
1.62      deraadt   105: uid_t uid;
1.1       deraadt   106:
1.76      guenther  107: void fstat_dofile(struct kinfo_file *);
1.68      millert   108: void fstat_header(void);
1.35      millert   109: void getinetproto(int);
                    110: void usage(void);
                    111: int getfname(char *);
1.76      guenther  112: void kqueuetrans(struct kinfo_file *);
                    113: void pipetrans(struct kinfo_file *);
                    114: struct kinfo_file *splice_find(char, u_int64_t);
                    115: void splice_insert(char, u_int64_t, struct kinfo_file *);
                    116: void find_splices(struct kinfo_file *, int);
                    117: void print_inet_details(struct kinfo_file *);
1.72      guenther  118: #ifdef INET6
1.76      guenther  119: void print_inet6_details(struct kinfo_file *);
1.72      guenther  120: #endif
1.76      guenther  121: void print_sock_details(struct kinfo_file *);
                    122: void socktrans(struct kinfo_file *);
                    123: void systracetrans(struct kinfo_file *);
                    124: void vtrans(struct kinfo_file *);
1.47      deraadt   125: const char *inet6_addrstr(struct in6_addr *);
1.68      millert   126: int signame_to_signum(char *);
1.74      deraadt   127: void hide(void *p);
                    128:
                    129: int hideroot;
                    130:
                    131: void
                    132: hide(void *p)
                    133: {
                    134:        printf("%p", hideroot ? NULL : p);
                    135: }
1.1       deraadt   136:
1.11      millert   137: int
1.40      deraadt   138: main(int argc, char *argv[])
1.1       deraadt   139: {
1.32      mpech     140:        struct passwd *passwd;
1.76      guenther  141:        struct kinfo_file *kf, *kflast;
1.1       deraadt   142:        int arg, ch, what;
1.68      millert   143:        char *memf, *nlistf, *optstr;
1.2       niklas    144:        char buf[_POSIX2_LINE_MAX];
1.58      tedu      145:        const char *errstr;
1.65      millert   146:        int cnt, flags;
1.1       deraadt   147:
1.74      deraadt   148:        hideroot = getuid();
                    149:
1.65      millert   150:        arg = -1;
                    151:        what = KERN_FILE_BYPID;
1.1       deraadt   152:        nlistf = memf = NULL;
1.28      hugh      153:        oflg = 0;
1.68      millert   154:
                    155:        /* are we fstat(1) or fuser(1)? */
                    156:        if (strcmp(__progname, "fuser") == 0) {
                    157:                fuser = 1;
                    158:                optstr = "cfks:uM:N:";
                    159:        } else {
                    160:                fuser = 0;
                    161:                optstr = "fnop:su:vN:M:";
                    162:        }
                    163:
                    164:        /*
                    165:         * fuser and fstat share three flags: -f, -s and -u.  In both cases
                    166:         * -f is a boolean, but for -u fstat wants an argument while fuser
                    167:         * does not and for -s fuser wants an argument whereas fstat does not.
                    168:         */
                    169:        while ((ch = getopt(argc, argv, optstr)) != -1)
1.60      sobrado   170:                switch ((char)ch) {
1.68      millert   171:                case 'c':
                    172:                        if (fsflg)
                    173:                                usage();
                    174:                        cflg = 1;
                    175:                        break;
1.1       deraadt   176:                case 'f':
1.68      millert   177:                        if (cflg)
                    178:                                usage();
1.1       deraadt   179:                        fsflg = 1;
                    180:                        break;
1.68      millert   181:                case 'k':
                    182:                        sflg = 1;
                    183:                        signo = SIGKILL;
                    184:                        break;
1.1       deraadt   185:                case 'M':
                    186:                        memf = optarg;
                    187:                        break;
                    188:                case 'N':
                    189:                        nlistf = optarg;
                    190:                        break;
                    191:                case 'n':
                    192:                        nflg = 1;
                    193:                        break;
1.28      hugh      194:                case 'o':
                    195:                        oflg = 1;
                    196:                        break;
1.1       deraadt   197:                case 'p':
                    198:                        if (pflg++)
                    199:                                usage();
1.58      tedu      200:                        arg = strtonum(optarg, 0, INT_MAX, &errstr);
                    201:                        if (errstr != NULL) {
1.74      deraadt   202:                                warnx("-p requires a process id, %s: %s",
1.58      tedu      203:                                        errstr, optarg);
1.1       deraadt   204:                                usage();
                    205:                        }
1.65      millert   206:                        what = KERN_FILE_BYPID;
1.1       deraadt   207:                        break;
1.56      mickey    208:                case 's':
                    209:                        sflg = 1;
1.68      millert   210:                        if (fuser) {
                    211:                                signo = signame_to_signum(optarg);
                    212:                                if (signo == -1) {
                    213:                                        warnx("invalid signal %s", optarg);
                    214:                                        usage();
                    215:                                }
                    216:                        }
1.56      mickey    217:                        break;
1.1       deraadt   218:                case 'u':
                    219:                        if (uflg++)
                    220:                                usage();
1.68      millert   221:                        if (!fuser) {
1.69      nicm      222:                                if (!(passwd = getpwnam(optarg))) {
1.74      deraadt   223:                                        arg = strtonum(optarg, 0, UID_MAX,
1.69      nicm      224:                                            &errstr);
                    225:                                        if (errstr != NULL) {
                    226:                                                errx(1, "%s: unknown uid",
                    227:                                                    optarg);
                    228:                                        }
                    229:                                } else
                    230:                                        arg = passwd->pw_uid;
1.68      millert   231:                                what = KERN_FILE_BYUID;
                    232:                        }
1.1       deraadt   233:                        break;
                    234:                case 'v':
                    235:                        vflg = 1;
                    236:                        break;
                    237:                default:
                    238:                        usage();
                    239:                }
                    240:
1.41      deraadt   241:        /*
1.62      deraadt   242:         * get the uid, for oflg and sflg
                    243:         */
                    244:        uid = getuid();
                    245:
                    246:        /*
1.65      millert   247:         * Use sysctl unless inspecting an alternate kernel.
1.41      deraadt   248:         */
1.65      millert   249:        if (nlistf == NULL || memf == NULL)
                    250:                flags = KVM_NO_FILES;
                    251:        else
                    252:                flags = O_RDONLY;
1.41      deraadt   253:
1.65      millert   254:        if ((kd = kvm_openfiles(nlistf, memf, NULL, flags, buf)) == NULL)
1.41      deraadt   255:                errx(1, "%s", buf);
                    256:
1.1       deraadt   257:        if (*(argv += optind)) {
                    258:                for (; *argv; ++argv) {
                    259:                        if (getfname(*argv))
                    260:                                checkfile = 1;
                    261:                }
1.68      millert   262:                /* file(s) specified, but none accessible */
                    263:                if (!checkfile)
1.1       deraadt   264:                        exit(1);
1.68      millert   265:        } else if (fuser)
                    266:                usage();
1.1       deraadt   267:
1.68      millert   268:        if (!fuser && fsflg && !checkfile) {
                    269:                /* fstat -f with no files means use wd */
1.1       deraadt   270:                if (getfname(".") == 0)
                    271:                        exit(1);
                    272:                checkfile = 1;
                    273:        }
1.16      deraadt   274:
1.76      guenther  275:        if ((kf = kvm_getfiles(kd, what, arg, sizeof(*kf), &cnt)) == NULL)
1.21      deraadt   276:                errx(1, "%s", kvm_geterr(kd));
1.81    ! deraadt   277:
        !           278:        if (pledge("stdio rpath route", NULL) == -1)
        !           279:                err(1, "pledge");
1.68      millert   280:
1.72      guenther  281:        find_splices(kf, cnt);
1.68      millert   282:        if (!fuser)
                    283:                fstat_header();
                    284:        for (kflast = &kf[cnt]; kf < kflast; ++kf) {
                    285:                if (fuser)
                    286:                        fuser_check(kf);
                    287:                else
                    288:                        fstat_dofile(kf);
                    289:        }
                    290:        if (fuser)
                    291:                fuser_run();
                    292:
                    293:        exit(0);
                    294: }
                    295:
                    296: void
                    297: fstat_header(void)
                    298: {
1.1       deraadt   299:        if (nflg)
                    300:                printf("%s",
1.60      sobrado   301: "USER     CMD          PID   FD  DEV      INUM       MODE R/W    SZ|DV");
1.1       deraadt   302:        else
                    303:                printf("%s",
1.60      sobrado   304: "USER     CMD          PID   FD MOUNT        INUM MODE       R/W    SZ|DV");
1.28      hugh      305:        if (oflg)
                    306:                printf("%s", ":OFFSET  ");
1.1       deraadt   307:        if (checkfile && fsflg == 0)
1.56      mickey    308:                printf(" NAME");
                    309:        if (sflg)
                    310:                printf("    XFERS   KBYTES");
                    311:        putchar('\n');
1.1       deraadt   312: }
                    313:
                    314: char   *Uname, *Comm;
1.62      deraadt   315: uid_t  *procuid;
1.14      deraadt   316: pid_t  Pid;
1.1       deraadt   317:
1.34      deraadt   318: #define PREFIX(i) do { \
1.39      mpech     319:        printf("%-8.8s %-10s %5ld", Uname, Comm, (long)Pid); \
1.60      sobrado   320:        switch (i) { \
1.65      millert   321:        case KERN_FILE_TEXT: \
1.1       deraadt   322:                printf(" text"); \
                    323:                break; \
1.65      millert   324:        case KERN_FILE_CDIR: \
1.1       deraadt   325:                printf("   wd"); \
                    326:                break; \
1.65      millert   327:        case KERN_FILE_RDIR: \
1.1       deraadt   328:                printf(" root"); \
                    329:                break; \
1.65      millert   330:        case KERN_FILE_TRACE: \
1.1       deraadt   331:                printf("   tr"); \
                    332:                break; \
                    333:        default: \
                    334:                printf(" %4d", i); \
                    335:                break; \
1.34      deraadt   336:        } \
                    337: } while (0)
1.1       deraadt   338:
                    339: /*
                    340:  * print open files attributed to this process
                    341:  */
                    342: void
1.76      guenther  343: fstat_dofile(struct kinfo_file *kf)
1.1       deraadt   344: {
                    345:
1.65      millert   346:        Uname = user_from_uid(kf->p_uid, 0);
                    347:        procuid = &kf->p_uid;
                    348:        Pid = kf->p_pid;
                    349:        Comm = kf->p_comm;
1.56      mickey    350:
1.65      millert   351:        switch (kf->f_type) {
                    352:        case DTYPE_VNODE:
                    353:                vtrans(kf);
                    354:                break;
                    355:        case DTYPE_SOCKET:
1.67      miod      356:                if (checkfile == 0)
                    357:                        socktrans(kf);
1.65      millert   358:                break;
                    359:        case DTYPE_PIPE:
1.67      miod      360:                if (checkfile == 0)
                    361:                        pipetrans(kf);
1.65      millert   362:                break;
                    363:        case DTYPE_KQUEUE:
1.67      miod      364:                if (checkfile == 0)
                    365:                        kqueuetrans(kf);
1.65      millert   366:                break;
                    367:        case DTYPE_SYSTRACE:
1.67      miod      368:                if (checkfile == 0)
                    369:                        systracetrans(kf);
1.65      millert   370:                break;
                    371:        default:
                    372:                if (vflg) {
                    373:                        warnx("unknown file type %d for file %d of pid %ld",
                    374:                            kf->f_type, kf->fd_fd, (long)Pid);
1.1       deraadt   375:                }
1.65      millert   376:                break;
1.1       deraadt   377:        }
                    378: }
                    379:
                    380: void
1.76      guenther  381: vtrans(struct kinfo_file *kf)
1.1       deraadt   382: {
1.65      millert   383:        const char *badtype = NULL;
                    384:        char rw[3], mode[12];
                    385:        char *filename = NULL;
                    386:
                    387:        if (kf->v_type == VNON)
1.1       deraadt   388:                badtype = "none";
1.65      millert   389:        else if (kf->v_type == VBAD)
1.1       deraadt   390:                badtype = "bad";
1.65      millert   391:        else if (kf->v_tag == VT_NON && !(kf->v_flag & VCLONE))
                    392:                badtype = "none";       /* not a clone */
                    393:
1.1       deraadt   394:        if (checkfile) {
                    395:                int fsmatch = 0;
1.68      millert   396:                struct filearg *fa;
1.1       deraadt   397:
                    398:                if (badtype)
                    399:                        return;
1.68      millert   400:                SLIST_FOREACH(fa, &fileargs, next) {
                    401:                        if (fa->dev == kf->va_fsid) {
1.1       deraadt   402:                                fsmatch = 1;
1.68      millert   403:                                if (fa->ino == kf->va_fileid) {
                    404:                                        filename = fa->name;
1.1       deraadt   405:                                        break;
                    406:                                }
                    407:                        }
1.65      millert   408:                }
1.1       deraadt   409:                if (fsmatch == 0 || (filename == NULL && fsflg == 0))
                    410:                        return;
                    411:        }
1.65      millert   412:        PREFIX(kf->fd_fd);
1.1       deraadt   413:        if (badtype) {
1.53      mickey    414:                (void)printf(" -           -  %10s    -\n", badtype);
1.1       deraadt   415:                return;
                    416:        }
1.61      thib      417:
1.1       deraadt   418:        if (nflg)
1.65      millert   419:                (void)printf(" %2ld,%-2ld", (long)major(kf->va_fsid),
                    420:                    (long)minor(kf->va_fsid));
                    421:        else if (!(kf->v_flag & VCLONE))
                    422:                (void)printf(" %-8s", kf->f_mntonname);
1.1       deraadt   423:        else
1.73      mikeb     424:                (void)printf(" clone   ");
1.1       deraadt   425:        if (nflg)
1.65      millert   426:                (void)snprintf(mode, sizeof(mode), "%o", kf->va_mode);
1.1       deraadt   427:        else
1.65      millert   428:                strmode(kf->va_mode, mode);
                    429:        printf(" %8llu %11s", kf->va_fileid, mode);
1.28      hugh      430:        rw[0] = '\0';
1.65      millert   431:        if (kf->f_flag & FREAD)
1.34      deraadt   432:                strlcat(rw, "r", sizeof rw);
1.65      millert   433:        if (kf->f_flag & FWRITE)
1.34      deraadt   434:                strlcat(rw, "w", sizeof rw);
1.28      hugh      435:        printf(" %2s", rw);
1.65      millert   436:        switch (kf->v_type) {
1.1       deraadt   437:        case VBLK:
                    438:        case VCHR: {
                    439:                char *name;
                    440:
1.65      millert   441:                if (nflg || ((name = devname(kf->va_rdev,
                    442:                    kf->v_type == VCHR ?  S_IFCHR : S_IFBLK)) == NULL))
                    443:                        printf("   %2d,%-3d", major(kf->va_rdev), minor(kf->va_rdev));
1.1       deraadt   444:                else
1.28      hugh      445:                        printf("  %7s", name);
                    446:                if (oflg)
                    447:                        printf("         ");
1.1       deraadt   448:                break;
                    449:        }
                    450:        default:
1.65      millert   451:                printf(" %8llu", kf->va_size);
1.62      deraadt   452:                if (oflg) {
                    453:                        if (uid == 0 || uid == *procuid)
1.65      millert   454:                                printf(":%-8llu", kf->f_offset);
1.74      deraadt   455:                        else
1.62      deraadt   456:                                printf(":%-8s", "*");
                    457:                }
                    458:        }
                    459:        if (sflg) {
                    460:                if (uid == 0 || uid == *procuid) {
1.65      millert   461:                        printf(" %8llu %8llu",
1.74      deraadt   462:                            (kf->f_rxfer + kf->f_rwfer),
                    463:                            (kf->f_rbytes + kf->f_wbytes) / 1024);
1.62      deraadt   464:                } else {
                    465:                        printf(" %8s %8s", "*", "*");
                    466:                }
1.1       deraadt   467:        }
                    468:        if (filename && !fsflg)
1.28      hugh      469:                printf(" %s", filename);
1.1       deraadt   470:        putchar('\n');
                    471: }
                    472:
1.22      art       473: void
1.76      guenther  474: pipetrans(struct kinfo_file *kf)
1.22      art       475: {
                    476:        void *maxaddr;
                    477:
1.65      millert   478:        PREFIX(kf->fd_fd);
1.22      art       479:
                    480:        printf(" ");
                    481:
                    482:        /*
                    483:         * We don't have enough space to fit both peer and own address, so
                    484:         * we select the higher address so both ends of the pipe have the
                    485:         * same visible addr. (it's the higher address because when the other
                    486:         * end closes, it becomes 0)
                    487:         */
1.80      deraadt   488:        maxaddr = (void *)(uintptr_t)MAXIMUM(kf->f_data, kf->pipe_peer);
1.22      art       489:
1.74      deraadt   490:        printf("pipe ");
                    491:        hide(maxaddr);
1.75      bluhm     492:        printf(" state: %s%s%s",
1.65      millert   493:            (kf->pipe_state & PIPE_WANTR) ? "R" : "",
                    494:            (kf->pipe_state & PIPE_WANTW) ? "W" : "",
                    495:            (kf->pipe_state & PIPE_EOF) ? "E" : "");
1.56      mickey    496:        if (sflg)
1.65      millert   497:                printf("\t%8llu %8llu",
                    498:                    (kf->f_rxfer + kf->f_rwfer),
                    499:                    (kf->f_rbytes + kf->f_wbytes) / 1024);
1.56      mickey    500:        printf("\n");
1.37      deraadt   501:        return;
                    502: }
                    503:
                    504: void
1.76      guenther  505: kqueuetrans(struct kinfo_file *kf)
1.37      deraadt   506: {
1.65      millert   507:        PREFIX(kf->fd_fd);
1.37      deraadt   508:
                    509:        printf(" ");
                    510:
1.74      deraadt   511:        printf("kqueue ");
                    512:        hide((void *)(uintptr_t)kf->f_data);
                    513:        printf(" %d state: %s%s\n",
1.65      millert   514:            kf->kq_count,
                    515:            (kf->kq_state & KQ_SEL) ? "S" : "",
                    516:            (kf->kq_state & KQ_SLEEP) ? "W" : "");
1.37      deraadt   517:        return;
                    518: }
                    519:
                    520: void
1.76      guenther  521: systracetrans(struct kinfo_file *kf)
1.37      deraadt   522: {
1.65      millert   523:        PREFIX(kf->fd_fd);
1.37      deraadt   524:
                    525:        printf(" ");
                    526:
1.74      deraadt   527:        printf("systrace ");
                    528:        hide((void *)(uintptr_t)kf->f_data);
                    529:        printf(" npol %d\n", kf->str_npolicies);
1.22      art       530:        return;
1.1       deraadt   531: }
                    532:
1.26      itojun    533: #ifdef INET6
                    534: const char *
1.40      deraadt   535: inet6_addrstr(struct in6_addr *p)
1.26      itojun    536: {
                    537:        struct sockaddr_in6 sin6;
                    538:        static char hbuf[NI_MAXHOST];
1.50      itojun    539:        const int niflags = NI_NUMERICHOST;
1.26      itojun    540:
                    541:        memset(&sin6, 0, sizeof(sin6));
                    542:        sin6.sin6_family = AF_INET6;
                    543:        sin6.sin6_len = sizeof(struct sockaddr_in6);
                    544:        sin6.sin6_addr = *p;
                    545:        if (IN6_IS_ADDR_LINKLOCAL(p) &&
                    546:            *(u_int16_t *)&sin6.sin6_addr.s6_addr[2] != 0) {
                    547:                sin6.sin6_scope_id =
1.38      deraadt   548:                    ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
1.26      itojun    549:                sin6.sin6_addr.s6_addr[2] = sin6.sin6_addr.s6_addr[3] = 0;
                    550:        }
                    551:
                    552:        if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
1.38      deraadt   553:            hbuf, sizeof(hbuf), NULL, 0, niflags))
1.26      itojun    554:                return "invalid";
                    555:
                    556:        return hbuf;
                    557: }
                    558: #endif
                    559:
1.1       deraadt   560: void
1.76      guenther  561: splice_insert(char type, u_int64_t ptr, struct kinfo_file *data)
1.72      guenther  562: {
                    563:        ENTRY entry, *found;
                    564:
1.74      deraadt   565:        if (asprintf(&entry.key, "%c%llx", type, hideroot ? 0 : ptr) == -1)
1.72      guenther  566:                err(1, NULL);
                    567:        entry.data = data;
                    568:        if ((found = hsearch(entry, ENTER)) == NULL)
                    569:                err(1, "hsearch");
                    570:        /* if it's ambiguous, set the data to NULL */
                    571:        if (found->data != data)
                    572:                found->data = NULL;
                    573: }
                    574:
1.76      guenther  575: struct kinfo_file *
1.72      guenther  576: splice_find(char type, u_int64_t ptr)
                    577: {
                    578:        ENTRY entry, *found;
                    579:        char buf[20];
                    580:
1.74      deraadt   581:        snprintf(buf, sizeof(buf), "%c%llx", type, hideroot ? 0 : ptr);
1.72      guenther  582:        entry.key = buf;
                    583:        found = hsearch(entry, FIND);
                    584:        return (found != NULL ? found->data : NULL);
                    585: }
                    586:
                    587: void
1.76      guenther  588: find_splices(struct kinfo_file *kf, int cnt)
1.72      guenther  589: {
                    590:        int i, created;
                    591:
                    592:        created = 0;
                    593:        for (i = 0; i < cnt; i++) {
                    594:                if (kf[i].f_type != DTYPE_SOCKET ||
                    595:                    (kf[i].so_splice == 0 && kf[i].so_splicelen != -1))
                    596:                        continue;
                    597:                if (created++ == 0) {
                    598:                        if (hcreate(1000) == 0)
                    599:                                err(1, "hcreate");
                    600:                }
                    601:                splice_insert('>', kf[i].f_data, &kf[i]);
                    602:                if (kf[i].so_splice != 0)
                    603:                        splice_insert('<', kf[i].so_splice, &kf[i]);
                    604:        }
                    605: }
                    606:
                    607: void
1.76      guenther  608: print_inet_details(struct kinfo_file *kf)
1.72      guenther  609: {
                    610:        struct in_addr laddr, faddr;
                    611:
                    612:        memcpy(&laddr, kf->inp_laddru, sizeof(laddr));
                    613:        memcpy(&faddr, kf->inp_faddru, sizeof(faddr));
                    614:        if (kf->so_protocol == IPPROTO_TCP) {
1.74      deraadt   615:                printf(" ");
                    616:                hide((void *)(uintptr_t)kf->inp_ppcb);
1.72      guenther  617:                printf(" %s:%d", laddr.s_addr == INADDR_ANY ? "*" :
                    618:                    inet_ntoa(laddr), ntohs(kf->inp_lport));
                    619:                if (kf->inp_fport) {
                    620:                        if (kf->so_state & SS_CONNECTOUT)
                    621:                                printf(" --> ");
                    622:                        else
                    623:                                printf(" <-- ");
                    624:                        printf("%s:%d",
                    625:                            faddr.s_addr == INADDR_ANY ? "*" :
                    626:                            inet_ntoa(faddr), ntohs(kf->inp_fport));
                    627:                }
                    628:        } else if (kf->so_protocol == IPPROTO_UDP) {
                    629:                printf(" %s:%d", laddr.s_addr == INADDR_ANY ? "*" :
                    630:                    inet_ntoa(laddr), ntohs(kf->inp_lport));
                    631:                if (kf->inp_fport) {
                    632:                        printf(" <-> %s:%d",
                    633:                            faddr.s_addr == INADDR_ANY ? "*" :
                    634:                            inet_ntoa(faddr), ntohs(kf->inp_fport));
                    635:                }
1.74      deraadt   636:        } else if (kf->so_pcb) {
                    637:                printf(" ");
                    638:                hide((void *)(uintptr_t)kf->so_pcb);
                    639:        }
1.72      guenther  640: }
                    641:
                    642: #ifdef INET6
                    643: void
1.76      guenther  644: print_inet6_details(struct kinfo_file *kf)
1.72      guenther  645: {
                    646:        char xaddrbuf[NI_MAXHOST + 2];
                    647:        struct in6_addr laddr6, faddr6;
                    648:
                    649:        memcpy(&laddr6, kf->inp_laddru, sizeof(laddr6));
                    650:        memcpy(&faddr6, kf->inp_faddru, sizeof(faddr6));
                    651:        if (kf->so_protocol == IPPROTO_TCP) {
1.74      deraadt   652:                printf(" ");
                    653:                hide((void *)(uintptr_t)kf->inp_ppcb);
1.72      guenther  654:                snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
                    655:                    inet6_addrstr(&laddr6));
                    656:                printf(" %s:%d",
                    657:                    IN6_IS_ADDR_UNSPECIFIED(&laddr6) ? "*" :
                    658:                    xaddrbuf, ntohs(kf->inp_lport));
                    659:                if (kf->inp_fport) {
                    660:                        if (kf->so_state & SS_CONNECTOUT)
                    661:                                printf(" --> ");
                    662:                        else
                    663:                                printf(" <-- ");
                    664:                        snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
                    665:                            inet6_addrstr(&faddr6));
                    666:                        printf("%s:%d",
                    667:                            IN6_IS_ADDR_UNSPECIFIED(&faddr6) ? "*" :
                    668:                            xaddrbuf, ntohs(kf->inp_fport));
                    669:                }
                    670:        } else if (kf->so_protocol == IPPROTO_UDP) {
                    671:                snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
                    672:                    inet6_addrstr(&laddr6));
                    673:                printf(" %s:%d",
                    674:                    IN6_IS_ADDR_UNSPECIFIED(&laddr6) ? "*" :
                    675:                    xaddrbuf, ntohs(kf->inp_lport));
                    676:                if (kf->inp_fport) {
                    677:                        snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
                    678:                            inet6_addrstr(&faddr6));
                    679:                        printf(" <-> %s:%d",
                    680:                            IN6_IS_ADDR_UNSPECIFIED(&faddr6) ? "*" :
                    681:                            xaddrbuf, ntohs(kf->inp_fport));
                    682:                }
1.74      deraadt   683:        } else if (kf->so_pcb) {
                    684:                printf(" ");
                    685:                hide((void *)(uintptr_t)kf->so_pcb);
                    686:        }
1.72      guenther  687: }
                    688: #endif
                    689:
                    690: void
1.76      guenther  691: print_sock_details(struct kinfo_file *kf)
1.72      guenther  692: {
                    693:        if (kf->so_family == AF_INET)
                    694:                print_inet_details(kf);
                    695: #ifdef INET6
                    696:        else if (kf->so_family == AF_INET6)
                    697:                print_inet6_details(kf);
                    698: #endif
                    699: }
                    700:
                    701: void
1.76      guenther  702: socktrans(struct kinfo_file *kf)
1.1       deraadt   703: {
                    704:        static char *stypename[] = {
                    705:                "unused",       /* 0 */
1.38      deraadt   706:                "stream",       /* 1 */
1.1       deraadt   707:                "dgram",        /* 2 */
                    708:                "raw",          /* 3 */
                    709:                "rdm",          /* 4 */
                    710:                "seqpak"        /* 5 */
                    711:        };
                    712: #define        STYPEMAX 5
1.66      chl       713:        char *stype, stypebuf[24];
1.1       deraadt   714:
1.65      millert   715:        PREFIX(kf->fd_fd);
1.1       deraadt   716:
1.65      millert   717:        if (kf->so_type > STYPEMAX) {
                    718:                snprintf(stypebuf, sizeof(stypebuf), "?%d", kf->so_type);
                    719:                stype = stypebuf;
                    720:        } else {
                    721:                stype = stypename[kf->so_type];
1.1       deraadt   722:        }
                    723:
1.34      deraadt   724:        /*
1.1       deraadt   725:         * protocol specific formatting
                    726:         *
                    727:         * Try to find interesting things to print.  For tcp, the interesting
                    728:         * thing is the address of the tcpcb, for udp and others, just the
                    729:         * inpcb (socket pcb).  For unix domain, its the address of the socket
                    730:         * pcb and the address of the connected pcb (if connected).  Otherwise
                    731:         * just print the protocol number and address of the socket itself.
                    732:         * The idea is not to duplicate netstat, but to make available enough
                    733:         * information for further analysis.
                    734:         */
1.65      millert   735:        switch (kf->so_family) {
1.1       deraadt   736:        case AF_INET:
1.65      millert   737:                printf("* internet %s", stype);
                    738:                getinetproto(kf->so_protocol);
1.72      guenther  739:                print_inet_details(kf);
1.1       deraadt   740:                break;
1.26      itojun    741: #ifdef INET6
                    742:        case AF_INET6:
1.65      millert   743:                printf("* internet6 %s", stype);
                    744:                getinetproto(kf->so_protocol);
1.72      guenther  745:                print_inet6_details(kf);
1.26      itojun    746:                break;
                    747: #endif
1.1       deraadt   748:        case AF_UNIX:
                    749:                /* print address of pcb and connected pcb */
1.65      millert   750:                printf("* unix %s", stype);
                    751:                if (kf->so_pcb) {
1.74      deraadt   752:                        printf(" ");
                    753:                        hide((void *)(uintptr_t)kf->so_pcb);
1.65      millert   754:                        if (kf->unp_conn) {
1.1       deraadt   755:                                char shoconn[4], *cp;
                    756:
                    757:                                cp = shoconn;
1.65      millert   758:                                if (!(kf->so_state & SS_CANTRCVMORE))
1.1       deraadt   759:                                        *cp++ = '<';
                    760:                                *cp++ = '-';
1.65      millert   761:                                if (!(kf->so_state & SS_CANTSENDMORE))
1.1       deraadt   762:                                        *cp++ = '>';
                    763:                                *cp = '\0';
1.74      deraadt   764:                                printf(" %s ", shoconn);
                    765:                                hide((void *)(uintptr_t)kf->unp_conn);
1.1       deraadt   766:                        }
                    767:                }
                    768:                break;
1.65      millert   769:        case AF_MPLS:
                    770:                /* print protocol number and socket address */
                    771:                printf("* mpls %s", stype);
1.74      deraadt   772:                printf(" %d ", kf->so_protocol);
                    773:                hide((void *)(uintptr_t)kf->f_data);
1.65      millert   774:                break;
                    775:        case AF_ROUTE:
                    776:                /* print protocol number and socket address */
                    777:                printf("* route %s", stype);
1.74      deraadt   778:                printf(" %d ", kf->so_protocol);
                    779:                hide((void *)(uintptr_t)kf->f_data);
1.65      millert   780:                break;
1.1       deraadt   781:        default:
                    782:                /* print protocol number and socket address */
1.65      millert   783:                printf("* %d %s", kf->so_family, stype);
1.74      deraadt   784:                printf(" %d ", kf->so_protocol);
                    785:                hide((void *)(uintptr_t)kf->f_data);
1.72      guenther  786:        }
                    787:        if (kf->so_splice != 0 || kf->so_splicelen == -1) {
1.76      guenther  788:                struct kinfo_file *from, *to;
1.72      guenther  789:
                    790:                from = splice_find('<', kf->f_data);
                    791:                to = NULL;
                    792:                if (kf->so_splice != 0)
                    793:                        to = splice_find('>', kf->so_splice);
                    794:
                    795:                if (to != NULL && from == to) {
                    796:                        printf(" <==>");
                    797:                        print_sock_details(to);
                    798:                } else if (kf->so_splice != 0) {
                    799:                        printf(" ==>");
                    800:                        if (to != NULL)
                    801:                                print_sock_details(to);
                    802:                } else if (kf->so_splicelen == -1) {
                    803:                        printf(" <==");
                    804:                        if (from != NULL)
                    805:                                print_sock_details(from);
                    806:                }
1.1       deraadt   807:        }
1.56      mickey    808:        if (sflg)
1.65      millert   809:                printf("\t%8llu %8llu",
                    810:                    (kf->f_rxfer + kf->f_rwfer),
                    811:                    (kf->f_rbytes + kf->f_wbytes) / 1024);
1.1       deraadt   812:        printf("\n");
                    813: }
                    814:
                    815: /*
                    816:  * getinetproto --
                    817:  *     print name of protocol number
                    818:  */
                    819: void
                    820: getinetproto(number)
                    821:        int number;
                    822: {
1.24      deraadt   823:        static int isopen;
1.32      mpech     824:        struct protoent *pe;
1.1       deraadt   825:
1.24      deraadt   826:        if (!isopen)
                    827:                setprotoent(++isopen);
                    828:        if ((pe = getprotobynumber(number)) != NULL)
                    829:                printf(" %s", pe->p_name);
                    830:        else
1.1       deraadt   831:                printf(" %d", number);
                    832: }
                    833:
1.11      millert   834: int
1.40      deraadt   835: getfname(char *filename)
1.1       deraadt   836: {
1.68      millert   837:        static struct statfs *mntbuf;
                    838:        static int nmounts;
                    839:        int i;
                    840:        struct stat sb;
                    841:        struct filearg *cur;
1.1       deraadt   842:
1.68      millert   843:        if (stat(filename, &sb)) {
1.27      millert   844:                warn("%s", filename);
1.68      millert   845:                return (0);
1.1       deraadt   846:        }
                    847:
1.68      millert   848:        /*
                    849:         * POSIX specifies "For block special devices, all processes using any
                    850:         * file on that device are listed".  However the -f flag description
                    851:         * states "The report shall be only for the named files", so we only
                    852:         * look up a block device if the -f flag has not be specified.
                    853:         */
                    854:        if (fuser && !fsflg && S_ISBLK(sb.st_mode)) {
                    855:                if (mntbuf == NULL) {
                    856:                        nmounts = getmntinfo(&mntbuf, MNT_NOWAIT);
                    857:                        if (nmounts == -1)
                    858:                                err(1, "getmntinfo");
                    859:                }
                    860:                for (i = 0; i < nmounts; i++) {
                    861:                        if (!strcmp(mntbuf[i].f_mntfromname, filename)) {
                    862:                                if (stat(mntbuf[i].f_mntonname, &sb) == -1) {
                    863:                                        warn("%s", filename);
                    864:                                        return (0);
                    865:                                }
                    866:                                cflg = 1;
                    867:                                break;
                    868:                        }
                    869:                }
                    870:        }
                    871:
                    872:        if ((cur = malloc(sizeof(*cur))) == NULL)
                    873:                err(1, NULL);
                    874:
                    875:        cur->ino = sb.st_ino;
                    876:        cur->dev = sb.st_dev & 0xffff;
1.1       deraadt   877:        cur->name = filename;
1.68      millert   878:        TAILQ_INIT(&cur->fusers);
                    879:        SLIST_INSERT_HEAD(&fileargs, cur, next);
                    880:        return (1);
                    881: }
                    882:
                    883: int
                    884: signame_to_signum(char *sig)
                    885: {
                    886:        int n;
                    887:        const char *errstr = NULL;
                    888:
                    889:        if (isdigit((unsigned char)*sig)) {
                    890:                n = strtonum(sig, 0, NSIG - 1, &errstr);
                    891:                return (errstr ? -1 : n);
                    892:        }
                    893:        if (!strncasecmp(sig, "sig", 3))
                    894:                sig += 3;
                    895:        for (n = 1; n < NSIG; n++) {
                    896:                if (!strcasecmp(sys_signame[n], sig))
                    897:                        return (n);
                    898:        }
                    899:        return (-1);
1.1       deraadt   900: }
                    901:
                    902: void
1.40      deraadt   903: usage(void)
1.1       deraadt   904: {
1.68      millert   905:        if (fuser) {
                    906:                fprintf(stderr, "usage: fuser [-cfku] [-M core] "
                    907:                    "[-N system] [-s signal] file ...\n");
                    908:        } else {
                    909:                fprintf(stderr, "usage: fstat [-fnosv] [-M core] [-N system] "
                    910:                    "[-p pid] [-u user] [file ...]\n");
                    911:        }
1.1       deraadt   912:        exit(1);
                    913: }