| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: fstat.c,v 1.106 2013/12/15 18:56:59 mlelstv Exp $ */ | | 1 | /* $NetBSD: fstat.c,v 1.107 2014/01/17 03:28:01 christos Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1988, 1993 | | 4 | * Copyright (c) 1988, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -29,27 +29,27 @@ | | | @@ -29,27 +29,27 @@ |
29 | * SUCH DAMAGE. | | 29 | * SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | #ifndef lint | | 33 | #ifndef lint |
34 | __COPYRIGHT("@(#) Copyright (c) 1988, 1993\ | | 34 | __COPYRIGHT("@(#) Copyright (c) 1988, 1993\ |
35 | The Regents of the University of California. All rights reserved."); | | 35 | The Regents of the University of California. All rights reserved."); |
36 | #endif /* not lint */ | | 36 | #endif /* not lint */ |
37 | | | 37 | |
38 | #ifndef lint | | 38 | #ifndef lint |
39 | #if 0 | | 39 | #if 0 |
40 | static char sccsid[] = "@(#)fstat.c 8.3 (Berkeley) 5/2/95"; | | 40 | static char sccsid[] = "@(#)fstat.c 8.3 (Berkeley) 5/2/95"; |
41 | #else | | 41 | #else |
42 | __RCSID("$NetBSD: fstat.c,v 1.106 2013/12/15 18:56:59 mlelstv Exp $"); | | 42 | __RCSID("$NetBSD: fstat.c,v 1.107 2014/01/17 03:28:01 christos Exp $"); |
43 | #endif | | 43 | #endif |
44 | #endif /* not lint */ | | 44 | #endif /* not lint */ |
45 | | | 45 | |
46 | #include <sys/types.h> | | 46 | #include <sys/types.h> |
47 | #include <sys/param.h> | | 47 | #include <sys/param.h> |
48 | #include <sys/time.h> | | 48 | #include <sys/time.h> |
49 | #include <sys/proc.h> | | 49 | #include <sys/proc.h> |
50 | #include <sys/stat.h> | | 50 | #include <sys/stat.h> |
51 | #include <sys/vnode.h> | | 51 | #include <sys/vnode.h> |
52 | #include <sys/socket.h> | | 52 | #include <sys/socket.h> |
53 | #include <sys/socketvar.h> | | 53 | #include <sys/socketvar.h> |
54 | #include <sys/domain.h> | | 54 | #include <sys/domain.h> |
55 | #include <sys/protosw.h> | | 55 | #include <sys/protosw.h> |
| @@ -500,28 +500,27 @@ ftrans(fdfile_t *fp, int i) | | | @@ -500,28 +500,27 @@ ftrans(fdfile_t *fp, int i) |
500 | if (!KVM_READ(fdfile.ff_file, &file, sizeof(file))) { | | 500 | if (!KVM_READ(fdfile.ff_file, &file, sizeof(file))) { |
501 | dprintf("can't read file %d at %p for pid %d", | | 501 | dprintf("can't read file %d at %p for pid %d", |
502 | i, fdfile.ff_file, Pid); | | 502 | i, fdfile.ff_file, Pid); |
503 | return; | | 503 | return; |
504 | } | | 504 | } |
505 | if (Aflg && file.f_type != DTYPE_VNODE && checkfile == 0) | | 505 | if (Aflg && file.f_type != DTYPE_VNODE && checkfile == 0) |
506 | (void)printf("%*lx ", | | 506 | (void)printf("%*lx ", |
507 | 2*(int)(sizeof(void*)), (long)fdfile.ff_file); | | 507 | 2*(int)(sizeof(void*)), (long)fdfile.ff_file); |
508 | switch (file.f_type) { | | 508 | switch (file.f_type) { |
509 | case DTYPE_VNODE: | | 509 | case DTYPE_VNODE: |
510 | vtrans(file.f_data, i, file.f_flag, (long)fdfile.ff_file); | | 510 | vtrans(file.f_data, i, file.f_flag, (long)fdfile.ff_file); |
511 | break; | | 511 | break; |
512 | case DTYPE_SOCKET: | | 512 | case DTYPE_SOCKET: |
513 | if (checkfile == 0) | | 513 | socktrans(file.f_data, i); |
514 | socktrans(file.f_data, i); | | | |
515 | break; | | 514 | break; |
516 | case DTYPE_PIPE: | | 515 | case DTYPE_PIPE: |
517 | if (checkfile == 0) | | 516 | if (checkfile == 0) |
518 | ptrans(&file, file.f_data, i); | | 517 | ptrans(&file, file.f_data, i); |
519 | break; | | 518 | break; |
520 | case DTYPE_MISC: | | 519 | case DTYPE_MISC: |
521 | case DTYPE_KQUEUE: | | 520 | case DTYPE_KQUEUE: |
522 | case DTYPE_CRYPTO: | | 521 | case DTYPE_CRYPTO: |
523 | case DTYPE_MQUEUE: | | 522 | case DTYPE_MQUEUE: |
524 | case DTYPE_SEM: | | 523 | case DTYPE_SEM: |
525 | if (checkfile == 0) | | 524 | if (checkfile == 0) |
526 | misctrans(&file, i); | | 525 | misctrans(&file, i); |
527 | break; | | 526 | break; |
| @@ -588,57 +587,69 @@ vfilestat(struct vnode *vp, struct files | | | @@ -588,57 +587,69 @@ vfilestat(struct vnode *vp, struct files |
588 | badtype = layer_filestat(vp, fsp); | | 587 | badtype = layer_filestat(vp, fsp); |
589 | break; | | 588 | break; |
590 | default: { | | 589 | default: { |
591 | static char unknown[10]; | | 590 | static char unknown[10]; |
592 | (void)snprintf(unknown, sizeof unknown, | | 591 | (void)snprintf(unknown, sizeof unknown, |
593 | "?(%x)", vp->v_tag); | | 592 | "?(%x)", vp->v_tag); |
594 | badtype = unknown; | | 593 | badtype = unknown; |
595 | break; | | 594 | break; |
596 | } | | 595 | } |
597 | } | | 596 | } |
598 | return badtype; | | 597 | return badtype; |
599 | } | | 598 | } |
600 | | | 599 | |
601 | static void | | 600 | static int |
602 | vtrans(struct vnode *vp, int i, int flag, long addr) | | 601 | checkfs(struct vnode *vp, struct vnode *vn, struct filestat *fst, |
| | | 602 | const char **type, const char **fname) |
603 | { | | 603 | { |
604 | struct vnode vn; | | 604 | *fname = NULL; |
605 | struct filestat fst; | | 605 | if (!KVM_READ(vp, vn, sizeof(*vn))) { |
606 | char mode[15], rw[3]; | | | |
607 | const char *badtype, *filename; | | | |
608 | | | | |
609 | filename = NULL; | | | |
610 | if (!KVM_READ(vp, &vn, sizeof(struct vnode))) { | | | |
611 | dprintf("can't read vnode at %p for pid %d", vp, Pid); | | 606 | dprintf("can't read vnode at %p for pid %d", vp, Pid); |
612 | return; | | 607 | return 0; |
613 | } | | 608 | } |
614 | badtype = vfilestat(&vn, &fst); | | 609 | *type = vfilestat(vn, fst); |
615 | if (checkfile) { | | 610 | if (checkfile) { |
616 | int fsmatch = 0; | | 611 | int fsmatch = 0; |
617 | DEVS *d; | | 612 | DEVS *d; |
618 | | | 613 | #if 0 |
619 | if (badtype && badtype != dead) | | 614 | if (*type && *type != dead) |
620 | return; | | 615 | return 0; |
621 | for (d = devs; d != NULL; d = d->next) | | 616 | #endif |
622 | if (d->fsid == fst.fsid) { | | 617 | for (d = devs; d != NULL; d = d->next) { |
| | | 618 | if (d->fsid == fst->fsid) { |
623 | fsmatch = 1; | | 619 | fsmatch = 1; |
624 | if (d->ino == fst.fileid) { | | 620 | if (d->ino == fst->fileid) { |
625 | filename = d->name; | | 621 | *fname = d->name; |
626 | break; | | 622 | break; |
627 | } | | 623 | } |
628 | } | | 624 | } |
629 | if (fsmatch == 0 || (filename == NULL && fsflg == 0)) | | 625 | } |
630 | return; | | 626 | if (fsmatch == 0 || (*fname == NULL && fsflg == 0)) |
| | | 627 | return 0; |
631 | } | | 628 | } |
| | | 629 | return 1; |
| | | 630 | } |
| | | 631 | |
| | | 632 | static void |
| | | 633 | vtrans(struct vnode *vp, int i, int flag, long addr) |
| | | 634 | { |
| | | 635 | struct vnode vn; |
| | | 636 | char mode[15], rw[3]; |
| | | 637 | const char *badtype, *filename; |
| | | 638 | struct filestat fst; |
| | | 639 | |
| | | 640 | if (!checkfs(vp, &vn, &fst, &badtype, &filename)) |
| | | 641 | return; |
| | | 642 | |
632 | if (Aflg) | | 643 | if (Aflg) |
633 | (void)printf("%*lx ", 2*(int)(sizeof(void*)), addr); | | 644 | (void)printf("%*lx ", 2*(int)(sizeof(void*)), addr); |
634 | PREFIX(i); | | 645 | PREFIX(i); |
635 | if (badtype == dead) { | | 646 | if (badtype == dead) { |
636 | char buf[1024]; | | 647 | char buf[1024]; |
637 | (void)snprintb(buf, sizeof(buf), VNODE_FLAGBITS, | | 648 | (void)snprintb(buf, sizeof(buf), VNODE_FLAGBITS, |
638 | vn.v_iflag | vn.v_vflag | vn.v_uflag); | | 649 | vn.v_iflag | vn.v_vflag | vn.v_uflag); |
639 | (void)printf(" flags %s\n", buf); | | 650 | (void)printf(" flags %s\n", buf); |
640 | return; | | 651 | return; |
641 | } else if (badtype) { | | 652 | } else if (badtype) { |
642 | (void)printf(" - - %10s -\n", badtype); | | 653 | (void)printf(" - - %10s -\n", badtype); |
643 | return; | | 654 | return; |
644 | } | | 655 | } |
| @@ -989,59 +1000,56 @@ socktrans(struct socket *sock, int i) | | | @@ -989,59 +1000,56 @@ socktrans(struct socket *sock, int i) |
989 | #define STYPEMAX 5 | | 1000 | #define STYPEMAX 5 |
990 | struct socket so; | | 1001 | struct socket so; |
991 | struct protosw proto; | | 1002 | struct protosw proto; |
992 | struct domain dom; | | 1003 | struct domain dom; |
993 | struct inpcb inpcb; | | 1004 | struct inpcb inpcb; |
994 | #ifdef INET6 | | 1005 | #ifdef INET6 |
995 | struct in6pcb in6pcb; | | 1006 | struct in6pcb in6pcb; |
996 | #endif | | 1007 | #endif |
997 | struct unpcb unpcb; | | 1008 | struct unpcb unpcb; |
998 | struct ddpcb ddpcb; | | 1009 | struct ddpcb ddpcb; |
999 | int len; | | 1010 | int len; |
1000 | char dname[32]; | | 1011 | char dname[32]; |
1001 | char lbuf[512], fbuf[512]; | | 1012 | char lbuf[512], fbuf[512]; |
1002 | PREFIX(i); | | | |
1003 | | | 1013 | |
1004 | /* fill in socket */ | | 1014 | /* fill in socket */ |
1005 | if (!KVM_READ(sock, &so, sizeof(struct socket))) { | | 1015 | if (!KVM_READ(sock, &so, sizeof(struct socket))) { |
1006 | dprintf("can't read sock at %p", sock); | | 1016 | dprintf("can't read sock at %p", sock); |
1007 | goto bad; | | 1017 | goto bad; |
1008 | } | | 1018 | } |
1009 | | | 1019 | |
1010 | /* fill in protosw entry */ | | 1020 | /* fill in protosw entry */ |
1011 | if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) { | | 1021 | if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) { |
1012 | dprintf("can't read protosw at %p", so.so_proto); | | 1022 | dprintf("can't read protosw at %p", so.so_proto); |
1013 | goto bad; | | 1023 | goto bad; |
1014 | } | | 1024 | } |
1015 | | | 1025 | |
1016 | /* fill in domain */ | | 1026 | /* fill in domain */ |
1017 | if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) { | | 1027 | if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) { |
1018 | dprintf("can't read domain at %p", proto.pr_domain); | | 1028 | dprintf("can't read domain at %p", proto.pr_domain); |
1019 | goto bad; | | 1029 | goto bad; |
1020 | } | | 1030 | } |
1021 | | | 1031 | |
| | | 1032 | if (checkfile && dom.dom_family != AF_LOCAL) |
| | | 1033 | return; |
| | | 1034 | |
1022 | if ((len = kvm_read(kd, (u_long)dom.dom_name, dname, | | 1035 | if ((len = kvm_read(kd, (u_long)dom.dom_name, dname, |
1023 | sizeof(dname) - 1)) != sizeof(dname) -1) { | | 1036 | sizeof(dname) - 1)) != sizeof(dname) -1) { |
1024 | dprintf("can't read domain name at %p", dom.dom_name); | | 1037 | dprintf("can't read domain name at %p", dom.dom_name); |
1025 | dname[0] = '\0'; | | 1038 | dname[0] = '\0'; |
1026 | } | | 1039 | } |
1027 | else | | 1040 | else |
1028 | dname[len] = '\0'; | | 1041 | dname[len] = '\0'; |
1029 | | | 1042 | |
1030 | if ((u_short)so.so_type > STYPEMAX) | | | |
1031 | (void)printf("* %s ?%d", dname, so.so_type); | | | |
1032 | else | | | |
1033 | (void)printf("* %s %s", dname, stypename[so.so_type]); | | | |
1034 | | | | |
1035 | /* | | 1043 | /* |
1036 | * protocol specific formatting | | 1044 | * protocol specific formatting |
1037 | * | | 1045 | * |
1038 | * Try to find interesting things to print. For TCP, the interesting | | 1046 | * Try to find interesting things to print. For TCP, the interesting |
1039 | * thing is the address of the tcpcb, for UDP and others, just the | | 1047 | * thing is the address of the tcpcb, for UDP and others, just the |
1040 | * inpcb (socket pcb). For UNIX domain, its the address of the socket | | 1048 | * inpcb (socket pcb). For UNIX domain, its the address of the socket |
1041 | * pcb and the address of the connected pcb (if connected). Otherwise | | 1049 | * pcb and the address of the connected pcb (if connected). Otherwise |
1042 | * just print the protocol number and address of the socket itself. | | 1050 | * just print the protocol number and address of the socket itself. |
1043 | * The idea is not to duplicate netstat, but to make available enough | | 1051 | * The idea is not to duplicate netstat, but to make available enough |
1044 | * information for further analysis. | | 1052 | * information for further analysis. |
1045 | */ | | 1053 | */ |
1046 | fbuf[0] = '\0'; | | 1054 | fbuf[0] = '\0'; |
1047 | lbuf[0] = '\0'; | | 1055 | lbuf[0] = '\0'; |
| @@ -1102,26 +1110,36 @@ socktrans(struct socket *sock, int i) | | | @@ -1102,26 +1110,36 @@ socktrans(struct socket *sock, int i) |
1102 | cp = shoconn; | | 1110 | cp = shoconn; |
1103 | if (!(so.so_state & SS_CANTRCVMORE)) | | 1111 | if (!(so.so_state & SS_CANTRCVMORE)) |
1104 | *cp++ = '<'; | | 1112 | *cp++ = '<'; |
1105 | *cp++ = '-'; | | 1113 | *cp++ = '-'; |
1106 | if (!(so.so_state & SS_CANTSENDMORE)) | | 1114 | if (!(so.so_state & SS_CANTSENDMORE)) |
1107 | *cp++ = '>'; | | 1115 | *cp++ = '>'; |
1108 | *cp = '\0'; | | 1116 | *cp = '\0'; |
1109 | again: | | 1117 | again: |
1110 | if (kvm_read(kd, (u_long)pcb[p], (char *)&unpcb, | | 1118 | if (kvm_read(kd, (u_long)pcb[p], (char *)&unpcb, |
1111 | sizeof(struct unpcb)) != sizeof(struct unpcb)){ | | 1119 | sizeof(struct unpcb)) != sizeof(struct unpcb)){ |
1112 | dprintf("can't read unpcb at %p", so.so_pcb); | | 1120 | dprintf("can't read unpcb at %p", so.so_pcb); |
1113 | goto bad; | | 1121 | goto bad; |
1114 | } | | 1122 | } |
| | | 1123 | if (checkfile) { |
| | | 1124 | struct vnode vn; |
| | | 1125 | struct filestat fst; |
| | | 1126 | const char *badtype, *filename; |
| | | 1127 | if (unpcb.unp_vnode == NULL) |
| | | 1128 | return; |
| | | 1129 | if (!checkfs(unpcb.unp_vnode, &vn, &fst, |
| | | 1130 | &badtype, &filename)) |
| | | 1131 | return; |
| | | 1132 | } |
1115 | | | 1133 | |
1116 | if (unpcb.unp_addr) { | | 1134 | if (unpcb.unp_addr) { |
1117 | struct sockaddr_un *sun = | | 1135 | struct sockaddr_un *sun = |
1118 | malloc(unpcb.unp_addrlen); | | 1136 | malloc(unpcb.unp_addrlen); |
1119 | if (sun == NULL) | | 1137 | if (sun == NULL) |
1120 | err(1, "malloc(%zu)", | | 1138 | err(1, "malloc(%zu)", |
1121 | unpcb.unp_addrlen); | | 1139 | unpcb.unp_addrlen); |
1122 | if (kvm_read(kd, (u_long)unpcb.unp_addr, | | 1140 | if (kvm_read(kd, (u_long)unpcb.unp_addr, |
1123 | sun, unpcb.unp_addrlen) != | | 1141 | sun, unpcb.unp_addrlen) != |
1124 | (ssize_t)unpcb.unp_addrlen) { | | 1142 | (ssize_t)unpcb.unp_addrlen) { |
1125 | dprintf("can't read sun at %p", | | 1143 | dprintf("can't read sun at %p", |
1126 | unpcb.unp_addr); | | 1144 | unpcb.unp_addr); |
1127 | free(sun); | | 1145 | free(sun); |
| @@ -1152,26 +1170,32 @@ again: | | | @@ -1152,26 +1170,32 @@ again: |
1152 | dprintf("can't read ddpcb at %p", so.so_pcb); | | 1170 | dprintf("can't read ddpcb at %p", so.so_pcb); |
1153 | goto bad; | | 1171 | goto bad; |
1154 | } | | 1172 | } |
1155 | at_addrstr(fbuf, sizeof(fbuf), &ddpcb.ddp_fsat); | | 1173 | at_addrstr(fbuf, sizeof(fbuf), &ddpcb.ddp_fsat); |
1156 | at_addrstr(lbuf, sizeof(lbuf), &ddpcb.ddp_lsat); | | 1174 | at_addrstr(lbuf, sizeof(lbuf), &ddpcb.ddp_lsat); |
1157 | } | | 1175 | } |
1158 | break; | | 1176 | break; |
1159 | default: | | 1177 | default: |
1160 | /* print protocol number and socket address */ | | 1178 | /* print protocol number and socket address */ |
1161 | snprintf(fbuf, sizeof(fbuf), " %d %jx", proto.pr_protocol, | | 1179 | snprintf(fbuf, sizeof(fbuf), " %d %jx", proto.pr_protocol, |
1162 | (uintmax_t)(uintptr_t)sock); | | 1180 | (uintmax_t)(uintptr_t)sock); |
1163 | break; | | 1181 | break; |
1164 | } | | 1182 | } |
| | | 1183 | PREFIX(i); |
| | | 1184 | if ((u_short)so.so_type > STYPEMAX) |
| | | 1185 | (void)printf("* %s ?%d", dname, so.so_type); |
| | | 1186 | else |
| | | 1187 | (void)printf("* %s %s", dname, stypename[so.so_type]); |
| | | 1188 | |
1165 | if (fbuf[0] || lbuf[0]) | | 1189 | if (fbuf[0] || lbuf[0]) |
1166 | printf(" %s%s%s", fbuf, (fbuf[0] && lbuf[0]) ? " <-> " : "", | | 1190 | printf(" %s%s%s", fbuf, (fbuf[0] && lbuf[0]) ? " <-> " : "", |
1167 | lbuf); | | 1191 | lbuf); |
1168 | else if (so.so_pcb) | | 1192 | else if (so.so_pcb) |
1169 | printf(" %jx", (uintmax_t)(uintptr_t)so.so_pcb); | | 1193 | printf(" %jx", (uintmax_t)(uintptr_t)so.so_pcb); |
1170 | (void)printf("\n"); | | 1194 | (void)printf("\n"); |
1171 | return; | | 1195 | return; |
1172 | bad: | | 1196 | bad: |
1173 | (void)printf("* error\n"); | | 1197 | (void)printf("* error\n"); |
1174 | } | | 1198 | } |
1175 | | | 1199 | |
1176 | static void | | 1200 | static void |
1177 | ptrans(struct file *fp, struct pipe *cpipe, int i) | | 1201 | ptrans(struct file *fp, struct pipe *cpipe, int i) |