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

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