| @@ -1,1310 +1,1330 @@ | | | @@ -1,1310 +1,1330 @@ |
1 | /* $NetBSD: fstat.c,v 1.113 2019/09/06 17:08:22 christos Exp $ */ | | 1 | /* $NetBSD: fstat.c,v 1.114 2020/08/26 23:08:29 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. |
15 | * 3. Neither the name of the University nor the names of its contributors | | 15 | * 3. Neither the name of the University nor the names of its contributors |
16 | * may be used to endorse or promote products derived from this software | | 16 | * may be used to endorse or promote products derived from this software |
17 | * without specific prior written permission. | | 17 | * without specific prior written permission. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
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.113 2019/09/06 17:08:22 christos Exp $"); | | 42 | __RCSID("$NetBSD: fstat.c,v 1.114 2020/08/26 23:08:29 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> |
56 | #include <sys/unpcb.h> | | 56 | #include <sys/unpcb.h> |
57 | #include <sys/sysctl.h> | | 57 | #include <sys/sysctl.h> |
58 | #include <sys/filedesc.h> | | 58 | #include <sys/filedesc.h> |
59 | #include <sys/pipe.h> | | 59 | #include <sys/pipe.h> |
60 | #define _KERNEL | | 60 | #define _KERNEL |
61 | #include <sys/mount.h> | | 61 | #include <sys/mount.h> |
62 | #undef _KERNEL | | 62 | #undef _KERNEL |
63 | #define _KERNEL | | 63 | #define _KERNEL |
64 | #include <sys/file.h> | | 64 | #include <sys/file.h> |
65 | #include <ufs/ufs/inode.h> | | 65 | #include <ufs/ufs/inode.h> |
66 | #include <ufs/ufs/ufsmount.h> | | 66 | #include <ufs/ufs/ufsmount.h> |
67 | #undef _KERNEL | | 67 | #undef _KERNEL |
68 | #define NFS | | 68 | #define NFS |
69 | #include <nfs/nfsproto.h> | | 69 | #include <nfs/nfsproto.h> |
70 | #include <nfs/rpcv2.h> | | 70 | #include <nfs/rpcv2.h> |
71 | #include <nfs/nfs.h> | | 71 | #include <nfs/nfs.h> |
72 | #include <nfs/nfsnode.h> | | 72 | #include <nfs/nfsnode.h> |
73 | #undef NFS | | 73 | #undef NFS |
74 | #include <msdosfs/denode.h> | | 74 | #include <msdosfs/denode.h> |
75 | #include <msdosfs/bpb.h> | | 75 | #include <msdosfs/bpb.h> |
76 | #define _KERNEL | | 76 | #define _KERNEL |
77 | #include <msdosfs/msdosfsmount.h> | | 77 | #include <msdosfs/msdosfsmount.h> |
78 | #undef _KERNEL | | 78 | #undef _KERNEL |
79 | #define _KERNEL | | 79 | #define _KERNEL |
80 | #include <miscfs/genfs/layer.h> | | 80 | #include <miscfs/genfs/layer.h> |
81 | #undef _KERNEL | | 81 | #undef _KERNEL |
82 | | | 82 | |
83 | #include <net/route.h> | | 83 | #include <net/route.h> |
84 | #include <netinet/in.h> | | 84 | #include <netinet/in.h> |
85 | #include <netinet/in_systm.h> | | 85 | #include <netinet/in_systm.h> |
86 | #include <netinet/ip.h> | | 86 | #include <netinet/ip.h> |
87 | #include <netinet/in_pcb.h> | | 87 | #include <netinet/in_pcb.h> |
88 | | | 88 | |
89 | #ifdef INET6 | | 89 | #ifdef INET6 |
90 | #include <netinet/ip6.h> | | 90 | #include <netinet/ip6.h> |
91 | #include <netinet6/in6.h> | | 91 | #include <netinet6/in6.h> |
92 | #include <netinet6/ip6_var.h> | | 92 | #include <netinet6/ip6_var.h> |
93 | #include <netinet6/in6_pcb.h> | | 93 | #include <netinet6/in6_pcb.h> |
94 | #endif | | 94 | #endif |
95 | | | 95 | |
96 | #include <netatalk/at.h> | | 96 | #include <netatalk/at.h> |
97 | #include <netatalk/ddp_var.h> | | 97 | #include <netatalk/ddp_var.h> |
98 | | | 98 | |
99 | #include <netdb.h> | | 99 | #include <netdb.h> |
100 | #include <arpa/inet.h> | | 100 | #include <arpa/inet.h> |
101 | | | 101 | |
102 | #include <ctype.h> | | 102 | #include <ctype.h> |
103 | #include <errno.h> | | 103 | #include <errno.h> |
104 | #include <kvm.h> | | 104 | #include <kvm.h> |
105 | #include <limits.h> | | 105 | #include <limits.h> |
106 | #include <nlist.h> | | 106 | #include <nlist.h> |
107 | #include <paths.h> | | 107 | #include <paths.h> |
108 | #include <pwd.h> | | 108 | #include <pwd.h> |
109 | #include <stdio.h> | | 109 | #include <stdio.h> |
110 | #include <stdlib.h> | | 110 | #include <stdlib.h> |
111 | #include <string.h> | | 111 | #include <string.h> |
112 | #include <unistd.h> | | 112 | #include <unistd.h> |
113 | #include <err.h> | | 113 | #include <err.h> |
114 | #include <util.h> | | 114 | #include <util.h> |
115 | | | 115 | |
116 | #include "fstat.h" | | 116 | #include "fstat.h" |
117 | | | 117 | |
118 | #define TEXT -1 | | 118 | #define TEXT -1 |
119 | #define CDIR -2 | | 119 | #define CDIR -2 |
120 | #define RDIR -3 | | 120 | #define RDIR -3 |
121 | #define TRACE -4 | | 121 | #define TRACE -4 |
122 | | | 122 | |
123 | typedef struct devs { | | 123 | typedef struct devs { |
124 | struct devs *next; | | 124 | struct devs *next; |
125 | long fsid; | | 125 | long fsid; |
126 | ino_t ino; | | 126 | ino_t ino; |
127 | const char *name; | | 127 | const char *name; |
128 | } DEVS; | | 128 | } DEVS; |
129 | static DEVS *devs; | | 129 | static DEVS *devs; |
130 | | | 130 | |
131 | static int fsflg, /* show files on same filesystem as file(s) argument */ | | 131 | static int fsflg, /* show files on same filesystem as file(s) argument */ |
132 | pflg, /* show files open by a particular pid */ | | 132 | pflg, /* show files open by a particular pid */ |
133 | uflg; /* show files open by a particular (effective) user */ | | 133 | uflg; /* show files open by a particular (effective) user */ |
134 | static int checkfile; /* true if restricting to particular files or filesystems */ | | 134 | static int checkfile; /* true if restricting to particular files or filesystems */ |
135 | static int nflg; /* (numerical) display f.s. and rdev as dev_t */ | | 135 | static int nflg; /* (numerical) display f.s. and rdev as dev_t */ |
136 | static int Aflg; /* prefix with address of file structure */ | | 136 | static int Aflg; /* prefix with address of file structure */ |
137 | static int Oflg; /* print offset instead of size */ | | 137 | static int Oflg; /* print offset instead of size */ |
138 | int vflg; /* display errors in locating kernel data objects etc... */ | | 138 | int vflg; /* display errors in locating kernel data objects etc... */ |
139 | | | 139 | |
140 | static fdfile_t **ofiles; /* buffer of pointers to file structures */ | | 140 | static fdfile_t **ofiles; /* buffer of pointers to file structures */ |
141 | static int fstat_maxfiles; | | 141 | static int fstat_maxfiles; |
142 | #define ALLOC_OFILES(d) \ | | 142 | #define ALLOC_OFILES(d) \ |
143 | if ((d) > fstat_maxfiles) { \ | | 143 | if ((d) > fstat_maxfiles) { \ |
144 | size_t len = (d) * sizeof(fdfile_t *); \ | | 144 | size_t len = (d) * sizeof(fdfile_t *); \ |
145 | free(ofiles); \ | | 145 | free(ofiles); \ |
146 | ofiles = malloc(len); \ | | 146 | ofiles = malloc(len); \ |
147 | if (ofiles == NULL) { \ | | 147 | if (ofiles == NULL) { \ |
148 | err(1, "malloc(%zu)", len); \ | | 148 | err(1, "malloc(%zu)", len); \ |
149 | } \ | | 149 | } \ |
150 | fstat_maxfiles = (d); \ | | 150 | fstat_maxfiles = (d); \ |
151 | } | | 151 | } |
152 | | | 152 | |
153 | kvm_t *kd; | | 153 | kvm_t *kd; |
154 | | | 154 | |
155 | static const char *const dtypes[] = { | | 155 | static const char *const dtypes[] = { |
156 | DTYPE_NAMES | | 156 | DTYPE_NAMES |
157 | }; | | 157 | }; |
158 | | | 158 | |
159 | static void dofiles(struct kinfo_proc2 *); | | 159 | static void dofiles(struct kinfo_proc2 *); |
160 | static int ext2fs_filestat(struct vnode *, struct filestat *); | | 160 | static int ext2fs_filestat(struct vnode *, struct filestat *); |
161 | static int getfname(const char *); | | 161 | static int getfname(const char *); |
162 | static void getinetproto(char *, size_t, int); | | 162 | static void getinetproto(char *, size_t, int); |
163 | static void getatproto(char *, size_t, int); | | 163 | static void getatproto(char *, size_t, int); |
164 | static char *getmnton(struct mount *); | | 164 | static char *getmnton(struct mount *); |
165 | static const char *layer_filestat(struct vnode *, struct filestat *); | | 165 | static const char *layer_filestat(struct vnode *, struct filestat *); |
166 | static int msdosfs_filestat(struct vnode *, struct filestat *); | | 166 | static int msdosfs_filestat(struct vnode *, struct filestat *); |
167 | static int nfs_filestat(struct vnode *, struct filestat *); | | 167 | static int nfs_filestat(struct vnode *, struct filestat *); |
168 | static const char *inet_addrstr(char *, size_t, const struct in_addr *, | | 168 | static const char *inet_addrstr(char *, size_t, const struct in_addr *, |
169 | uint16_t, bool); | | 169 | uint16_t, bool); |
170 | #ifdef INET6 | | 170 | #ifdef INET6 |
171 | static const char *inet6_addrstr(char *, size_t, const struct in6_addr *, | | 171 | static const char *inet6_addrstr(char *, size_t, const struct in6_addr *, |
172 | uint16_t, bool); | | 172 | uint16_t, bool); |
173 | #endif | | 173 | #endif |
174 | static const char *at_addrstr(char *, size_t, const struct sockaddr_at *); | | 174 | static const char *at_addrstr(char *, size_t, const struct sockaddr_at *); |
175 | static void socktrans(struct file *, struct socket *, int); | | 175 | static void socktrans(struct file *, struct socket *, int); |
176 | static void misctrans(struct file *, int); | | 176 | static void misctrans(struct file *, int); |
177 | static int ufs_filestat(struct vnode *, struct filestat *); | | 177 | static int ufs_filestat(struct vnode *, struct filestat *); |
178 | static void usage(void) __dead; | | 178 | static void usage(void) __dead; |
179 | static const char *vfilestat(struct vnode *, struct filestat *); | | 179 | static const char *vfilestat(struct vnode *, struct filestat *); |
180 | static void vtrans(struct file *, struct vnode *, int, int, long); | | 180 | static void vtrans(struct file *, struct vnode *, int, int, long); |
181 | static void ftrans(fdfile_t *, int); | | 181 | static void ftrans(fdfile_t *, int); |
182 | static void ptrans(struct file *, struct pipe *, int); | | 182 | static void ptrans(struct file *, struct pipe *, int); |
183 | static void kdriver_init(void); | | 183 | static void kdriver_init(void); |
| | | 184 | static void check_privs(void); |
184 | | | 185 | |
185 | int | | 186 | int |
186 | main(int argc, char **argv) | | 187 | main(int argc, char **argv) |
187 | { | | 188 | { |
188 | struct passwd *passwd; | | 189 | struct passwd *passwd; |
189 | struct kinfo_proc2 *p, *plast; | | 190 | struct kinfo_proc2 *p, *plast; |
190 | int arg, ch, what; | | 191 | int arg, ch, what; |
191 | char *memf, *nlistf; | | 192 | char *memf, *nlistf; |
192 | char buf[_POSIX2_LINE_MAX]; | | 193 | char buf[_POSIX2_LINE_MAX]; |
193 | int cnt; | | 194 | int cnt; |
194 | gid_t egid = getegid(); | | 195 | gid_t egid = getegid(); |
195 | | | 196 | |
196 | (void)setegid(getgid()); | | 197 | (void)setegid(getgid()); |
197 | arg = 0; | | 198 | arg = 0; |
198 | what = KERN_PROC_ALL; | | 199 | what = KERN_PROC_ALL; |
199 | nlistf = memf = NULL; | | 200 | nlistf = memf = NULL; |
200 | while ((ch = getopt(argc, argv, "fnAOp:u:vN:M:")) != -1) | | 201 | while ((ch = getopt(argc, argv, "fnAOp:u:vN:M:")) != -1) |
201 | switch((char)ch) { | | 202 | switch((char)ch) { |
202 | case 'f': | | 203 | case 'f': |
203 | fsflg = 1; | | 204 | fsflg = 1; |
204 | break; | | 205 | break; |
205 | case 'M': | | 206 | case 'M': |
206 | memf = optarg; | | 207 | memf = optarg; |
207 | break; | | 208 | break; |
208 | case 'N': | | 209 | case 'N': |
209 | nlistf = optarg; | | 210 | nlistf = optarg; |
210 | break; | | 211 | break; |
211 | case 'n': | | 212 | case 'n': |
212 | nflg = 1; | | 213 | nflg = 1; |
213 | break; | | 214 | break; |
214 | case 'A': | | 215 | case 'A': |
215 | Aflg = 1; | | 216 | Aflg = 1; |
216 | break; | | 217 | break; |
217 | case 'O': | | 218 | case 'O': |
218 | Oflg = 1; | | 219 | Oflg = 1; |
219 | break; | | 220 | break; |
220 | case 'p': | | 221 | case 'p': |
221 | if (pflg++) | | 222 | if (pflg++) |
222 | usage(); | | 223 | usage(); |
223 | if (!isdigit((unsigned char)*optarg)) { | | 224 | if (!isdigit((unsigned char)*optarg)) { |
224 | warnx("-p requires a process id"); | | 225 | warnx("-p requires a process id"); |
225 | usage(); | | 226 | usage(); |
226 | } | | 227 | } |
227 | what = KERN_PROC_PID; | | 228 | what = KERN_PROC_PID; |
228 | arg = atoi(optarg); | | 229 | arg = atoi(optarg); |
229 | break; | | 230 | break; |
230 | case 'u': | | 231 | case 'u': |
231 | if (uflg++) | | 232 | if (uflg++) |
232 | usage(); | | 233 | usage(); |
233 | if (!(passwd = getpwnam(optarg))) { | | 234 | if (!(passwd = getpwnam(optarg))) { |
234 | errx(1, "%s: unknown uid", optarg); | | 235 | errx(1, "%s: unknown uid", optarg); |
235 | } | | 236 | } |
236 | what = KERN_PROC_UID; | | 237 | what = KERN_PROC_UID; |
237 | arg = passwd->pw_uid; | | 238 | arg = passwd->pw_uid; |
238 | break; | | 239 | break; |
239 | case 'v': | | 240 | case 'v': |
240 | vflg = 1; | | 241 | vflg = 1; |
241 | break; | | 242 | break; |
242 | case '?': | | 243 | case '?': |
243 | default: | | 244 | default: |
244 | usage(); | | 245 | usage(); |
245 | } | | 246 | } |
246 | | | 247 | |
| | | 248 | check_privs(); |
| | | 249 | |
247 | kdriver_init(); | | 250 | kdriver_init(); |
248 | | | 251 | |
249 | if (*(argv += optind)) { | | 252 | if (*(argv += optind)) { |
250 | for (; *argv; ++argv) { | | 253 | for (; *argv; ++argv) { |
251 | if (getfname(*argv)) | | 254 | if (getfname(*argv)) |
252 | checkfile = 1; | | 255 | checkfile = 1; |
253 | } | | 256 | } |
254 | if (!checkfile) /* file(s) specified, but none accessible */ | | 257 | if (!checkfile) /* file(s) specified, but none accessible */ |
255 | exit(1); | | 258 | exit(1); |
256 | } | | 259 | } |
257 | | | 260 | |
258 | ALLOC_OFILES(256); /* reserve space for file pointers */ | | 261 | ALLOC_OFILES(256); /* reserve space for file pointers */ |
259 | | | 262 | |
260 | if (fsflg && !checkfile) { | | 263 | if (fsflg && !checkfile) { |
261 | /* -f with no files means use wd */ | | 264 | /* -f with no files means use wd */ |
262 | if (getfname(".") == 0) | | 265 | if (getfname(".") == 0) |
263 | exit(1); | | 266 | exit(1); |
264 | checkfile = 1; | | 267 | checkfile = 1; |
265 | } | | 268 | } |
266 | | | 269 | |
267 | /* | | 270 | /* |
268 | * Discard setgid privileges. If not the running kernel, we toss | | 271 | * Discard setgid privileges. If not the running kernel, we toss |
269 | * them away totally so that bad guys can't print interesting stuff | | 272 | * them away totally so that bad guys can't print interesting stuff |
270 | * from kernel memory, otherwise switch back to kmem for the | | 273 | * from kernel memory, otherwise switch back to kmem for the |
271 | * duration of the kvm_openfiles() call. | | 274 | * duration of the kvm_openfiles() call. |
272 | */ | | 275 | */ |
273 | if (nlistf != NULL || memf != NULL) | | 276 | if (nlistf != NULL || memf != NULL) |
274 | (void)setgid(getgid()); | | 277 | (void)setgid(getgid()); |
275 | else | | 278 | else |
276 | (void)setegid(egid); | | 279 | (void)setegid(egid); |
277 | | | 280 | |
278 | if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) | | 281 | if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) |
279 | errx(1, "%s", buf); | | 282 | errx(1, "%s", buf); |
280 | | | 283 | |
281 | /* get rid of it now anyway */ | | 284 | /* get rid of it now anyway */ |
282 | if (nlistf == NULL && memf == NULL) | | 285 | if (nlistf == NULL && memf == NULL) |
283 | (void)setgid(getgid()); | | 286 | (void)setgid(getgid()); |
284 | | | 287 | |
285 | if ((p = kvm_getproc2(kd, what, arg, sizeof *p, &cnt)) == NULL) { | | 288 | if ((p = kvm_getproc2(kd, what, arg, sizeof *p, &cnt)) == NULL) { |
286 | errx(1, "%s", kvm_geterr(kd)); | | 289 | errx(1, "%s", kvm_geterr(kd)); |
287 | } | | 290 | } |
288 | if (Aflg) | | 291 | if (Aflg) |
289 | (void)printf("%-*s ", 2*(int)(sizeof(void*)), "ADDR"); | | 292 | (void)printf("%-*s ", 2*(int)(sizeof(void*)), "ADDR"); |
290 | if (nflg) | | 293 | if (nflg) |
291 | (void)printf( | | 294 | (void)printf( |
292 | "USER CMD PID FD DEV INUM MODE %s R/W", | | 295 | "USER CMD PID FD DEV INUM MODE %s R/W", |
293 | Oflg ? " OFFS" : "SZ|DV" ); | | 296 | Oflg ? " OFFS" : "SZ|DV" ); |
294 | else | | 297 | else |
295 | (void)printf( | | 298 | (void)printf( |
296 | "USER CMD PID FD MOUNT INUM MODE %s R/W", | | 299 | "USER CMD PID FD MOUNT INUM MODE %s R/W", |
297 | Oflg ? " OFFS" : "SZ|DV" ); | | 300 | Oflg ? " OFFS" : "SZ|DV" ); |
298 | | | 301 | |
299 | if (checkfile && fsflg == 0) | | 302 | if (checkfile && fsflg == 0) |
300 | (void)printf(" NAME\n"); | | 303 | (void)printf(" NAME\n"); |
301 | else | | 304 | else |
302 | (void)putchar('\n'); | | 305 | (void)putchar('\n'); |
303 | | | 306 | |
304 | for (plast = &p[cnt]; p < plast; ++p) { | | 307 | for (plast = &p[cnt]; p < plast; ++p) { |
305 | if (p->p_stat == SZOMB) | | 308 | if (p->p_stat == SZOMB) |
306 | continue; | | 309 | continue; |
307 | dofiles(p); | | 310 | dofiles(p); |
308 | } | | 311 | } |
309 | return 0; | | 312 | return 0; |
310 | } | | 313 | } |
311 | | | 314 | |
| | | 315 | static void |
| | | 316 | check_privs(void) |
| | | 317 | { |
| | | 318 | int expaddr; |
| | | 319 | size_t expsize = sizeof(expaddr); |
| | | 320 | const char *expname = "kern.expose_address"; |
| | | 321 | |
| | | 322 | if (geteuid() == 0) |
| | | 323 | return; |
| | | 324 | |
| | | 325 | if (sysctlbyname(expname, &expaddr, &expsize, NULL, 0) == -1) |
| | | 326 | err(EXIT_FAILURE, "Can't get sysctl `%s'", expname); |
| | | 327 | if (expaddr == 0) |
| | | 328 | errx(EXIT_FAILURE, "This program does not work without " |
| | | 329 | "sysctl `%s' being set", expname); |
| | | 330 | } |
| | | 331 | |
312 | static const char *Uname, *Comm; | | 332 | static const char *Uname, *Comm; |
313 | pid_t Pid; | | 333 | pid_t Pid; |
314 | | | 334 | |
315 | #define PREFIX(i) (void)printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \ | | 335 | #define PREFIX(i) (void)printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \ |
316 | switch(i) { \ | | 336 | switch(i) { \ |
317 | case TEXT: \ | | 337 | case TEXT: \ |
318 | (void)printf(" text"); \ | | 338 | (void)printf(" text"); \ |
319 | break; \ | | 339 | break; \ |
320 | case CDIR: \ | | 340 | case CDIR: \ |
321 | (void)printf(" wd"); \ | | 341 | (void)printf(" wd"); \ |
322 | break; \ | | 342 | break; \ |
323 | case RDIR: \ | | 343 | case RDIR: \ |
324 | (void)printf(" root"); \ | | 344 | (void)printf(" root"); \ |
325 | break; \ | | 345 | break; \ |
326 | case TRACE: \ | | 346 | case TRACE: \ |
327 | (void)printf(" tr"); \ | | 347 | (void)printf(" tr"); \ |
328 | break; \ | | 348 | break; \ |
329 | default: \ | | 349 | default: \ |
330 | (void)printf(" %4d", i); \ | | 350 | (void)printf(" %4d", i); \ |
331 | break; \ | | 351 | break; \ |
332 | } | | 352 | } |
333 | | | 353 | |
334 | static struct kinfo_drivers *kdriver; | | 354 | static struct kinfo_drivers *kdriver; |
335 | static size_t kdriverlen; | | 355 | static size_t kdriverlen; |
336 | | | 356 | |
337 | static int | | 357 | static int |
338 | kdriver_comp(const void *a, const void *b) | | 358 | kdriver_comp(const void *a, const void *b) |
339 | { | | 359 | { |
340 | const struct kinfo_drivers *ka = a; | | 360 | const struct kinfo_drivers *ka = a; |
341 | const struct kinfo_drivers *kb = b; | | 361 | const struct kinfo_drivers *kb = b; |
342 | int kac = ka->d_cmajor == -1 ? 0 : ka->d_cmajor; | | 362 | int kac = ka->d_cmajor == -1 ? 0 : ka->d_cmajor; |
343 | int kbc = kb->d_cmajor == -1 ? 0 : kb->d_cmajor; | | 363 | int kbc = kb->d_cmajor == -1 ? 0 : kb->d_cmajor; |
344 | int kab = ka->d_bmajor == -1 ? 0 : ka->d_bmajor; | | 364 | int kab = ka->d_bmajor == -1 ? 0 : ka->d_bmajor; |
345 | int kbb = kb->d_bmajor == -1 ? 0 : kb->d_bmajor; | | 365 | int kbb = kb->d_bmajor == -1 ? 0 : kb->d_bmajor; |
346 | int c = kac - kbc; | | 366 | int c = kac - kbc; |
347 | if (c == 0) | | 367 | if (c == 0) |
348 | return kab - kbb; | | 368 | return kab - kbb; |
349 | else | | 369 | else |
350 | return c; | | 370 | return c; |
351 | } | | 371 | } |
352 | | | 372 | |
353 | static const char * | | 373 | static const char * |
354 | kdriver_search(int type, dev_t num) | | 374 | kdriver_search(int type, dev_t num) |
355 | { | | 375 | { |
356 | struct kinfo_drivers k, *kp; | | 376 | struct kinfo_drivers k, *kp; |
357 | static char buf[64]; | | 377 | static char buf[64]; |
358 | | | 378 | |
359 | if (nflg) | | 379 | if (nflg) |
360 | goto out; | | 380 | goto out; |
361 | | | 381 | |
362 | if (type == VBLK) { | | 382 | if (type == VBLK) { |
363 | k.d_bmajor = num; | | 383 | k.d_bmajor = num; |
364 | k.d_cmajor = -1; | | 384 | k.d_cmajor = -1; |
365 | } else { | | 385 | } else { |
366 | k.d_bmajor = -1; | | 386 | k.d_bmajor = -1; |
367 | k.d_cmajor = num; | | 387 | k.d_cmajor = num; |
368 | } | | 388 | } |
369 | kp = bsearch(&k, kdriver, kdriverlen, sizeof(*kdriver), kdriver_comp); | | 389 | kp = bsearch(&k, kdriver, kdriverlen, sizeof(*kdriver), kdriver_comp); |
370 | if (kp) | | 390 | if (kp) |
371 | return kp->d_name; | | 391 | return kp->d_name; |
372 | out: | | 392 | out: |
373 | snprintf(buf, sizeof(buf), "%llu", (unsigned long long)num); | | 393 | snprintf(buf, sizeof(buf), "%llu", (unsigned long long)num); |
374 | return buf; | | 394 | return buf; |
375 | } | | 395 | } |
376 | | | 396 | |
377 | | | 397 | |
378 | static void | | 398 | static void |
379 | kdriver_init(void) | | 399 | kdriver_init(void) |
380 | { | | 400 | { |
381 | size_t sz; | | 401 | size_t sz; |
382 | int error; | | 402 | int error; |
383 | static const int name[2] = { CTL_KERN, KERN_DRIVERS }; | | 403 | static const int name[2] = { CTL_KERN, KERN_DRIVERS }; |
384 | | | 404 | |
385 | error = sysctl(name, __arraycount(name), NULL, &sz, NULL, 0); | | 405 | error = sysctl(name, __arraycount(name), NULL, &sz, NULL, 0); |
386 | if (error == -1) { | | 406 | if (error == -1) { |
387 | warn("sysctl kern.drivers"); | | 407 | warn("sysctl kern.drivers"); |
388 | return; | | 408 | return; |
389 | } | | 409 | } |
390 | | | 410 | |
391 | if (sz % sizeof(*kdriver)) { | | 411 | if (sz % sizeof(*kdriver)) { |
392 | warnx("bad size %zu for kern.drivers", sz); | | 412 | warnx("bad size %zu for kern.drivers", sz); |
393 | return; | | 413 | return; |
394 | } | | 414 | } |
395 | | | 415 | |
396 | kdriver = malloc(sz); | | 416 | kdriver = malloc(sz); |
397 | if (kdriver == NULL) { | | 417 | if (kdriver == NULL) { |
398 | warn("malloc"); | | 418 | warn("malloc"); |
399 | return; | | 419 | return; |
400 | } | | 420 | } |
401 | | | 421 | |
402 | error = sysctl(name, __arraycount(name), kdriver, &sz, NULL, 0); | | 422 | error = sysctl(name, __arraycount(name), kdriver, &sz, NULL, 0); |
403 | if (error == -1) { | | 423 | if (error == -1) { |
404 | warn("sysctl kern.drivers"); | | 424 | warn("sysctl kern.drivers"); |
405 | return; | | 425 | return; |
406 | } | | 426 | } |
407 | | | 427 | |
408 | kdriverlen = sz / sizeof(*kdriver); | | 428 | kdriverlen = sz / sizeof(*kdriver); |
409 | qsort(kdriver, kdriverlen, sizeof(*kdriver), kdriver_comp); | | 429 | qsort(kdriver, kdriverlen, sizeof(*kdriver), kdriver_comp); |
410 | #ifdef DEBUG | | 430 | #ifdef DEBUG |
411 | for (size_t i = 0; i < kdriverlen; i++) | | 431 | for (size_t i = 0; i < kdriverlen; i++) |
412 | printf("%d %d %s\n", kdriver[i].d_cmajor, kdriver[i].d_bmajor, | | 432 | printf("%d %d %s\n", kdriver[i].d_cmajor, kdriver[i].d_bmajor, |
413 | kdriver[i].d_name); | | 433 | kdriver[i].d_name); |
414 | #endif | | 434 | #endif |
415 | } | | 435 | } |
416 | | | 436 | |
417 | /* | | 437 | /* |
418 | * print open files attributed to this process | | 438 | * print open files attributed to this process |
419 | */ | | 439 | */ |
420 | static void | | 440 | static void |
421 | dofiles(struct kinfo_proc2 *p) | | 441 | dofiles(struct kinfo_proc2 *p) |
422 | { | | 442 | { |
423 | int i; | | 443 | int i; |
424 | struct filedesc filed; | | 444 | struct filedesc filed; |
425 | struct cwdinfo cwdi; | | 445 | struct cwdinfo cwdi; |
426 | struct fdtab dt; | | 446 | struct fdtab dt; |
427 | | | 447 | |
428 | Uname = user_from_uid(p->p_uid, 0); | | 448 | Uname = user_from_uid(p->p_uid, 0); |
429 | Pid = p->p_pid; | | 449 | Pid = p->p_pid; |
430 | Comm = p->p_comm; | | 450 | Comm = p->p_comm; |
431 | | | 451 | |
432 | if (p->p_fd == 0 || p->p_cwdi == 0) | | 452 | if (p->p_fd == 0 || p->p_cwdi == 0) |
433 | return; | | 453 | return; |
434 | if (!KVM_READ(p->p_fd, &filed, sizeof (filed))) { | | 454 | if (!KVM_READ(p->p_fd, &filed, sizeof (filed))) { |
435 | warnx("can't read filedesc at %p for pid %d", | | 455 | warnx("can't read filedesc at %p for pid %d", |
436 | (void *)(uintptr_t)p->p_fd, Pid); | | 456 | (void *)(uintptr_t)p->p_fd, Pid); |
437 | return; | | 457 | return; |
438 | } | | 458 | } |
439 | if (filed.fd_lastfile == -1) | | 459 | if (filed.fd_lastfile == -1) |
440 | return; | | 460 | return; |
441 | if (!KVM_READ(p->p_cwdi, &cwdi, sizeof(cwdi))) { | | 461 | if (!KVM_READ(p->p_cwdi, &cwdi, sizeof(cwdi))) { |
442 | warnx("can't read cwdinfo at %p for pid %d", | | 462 | warnx("can't read cwdinfo at %p for pid %d", |
443 | (void *)(uintptr_t)p->p_cwdi, Pid); | | 463 | (void *)(uintptr_t)p->p_cwdi, Pid); |
444 | return; | | 464 | return; |
445 | } | | 465 | } |
446 | if (!KVM_READ(filed.fd_dt, &dt, sizeof(dt))) { | | 466 | if (!KVM_READ(filed.fd_dt, &dt, sizeof(dt))) { |
447 | warnx("can't read dtab at %p for pid %d", filed.fd_dt, Pid); | | 467 | warnx("can't read dtab at %p for pid %d", filed.fd_dt, Pid); |
448 | return; | | 468 | return; |
449 | } | | 469 | } |
450 | if ((unsigned)filed.fd_lastfile >= dt.dt_nfiles || | | 470 | if ((unsigned)filed.fd_lastfile >= dt.dt_nfiles || |
451 | filed.fd_freefile > filed.fd_lastfile + 1) { | | 471 | filed.fd_freefile > filed.fd_lastfile + 1) { |
452 | dprintf("filedesc corrupted at %p for pid %d", | | 472 | dprintf("filedesc corrupted at %p for pid %d", |
453 | (void *)(uintptr_t)p->p_fd, Pid); | | 473 | (void *)(uintptr_t)p->p_fd, Pid); |
454 | return; | | 474 | return; |
455 | } | | 475 | } |
456 | /* | | 476 | /* |
457 | * root directory vnode, if one | | 477 | * root directory vnode, if one |
458 | */ | | 478 | */ |
459 | if (cwdi.cwdi_rdir) | | 479 | if (cwdi.cwdi_rdir) |
460 | vtrans(NULL, cwdi.cwdi_rdir, RDIR, FREAD, (long)cwdi.cwdi_rdir); | | 480 | vtrans(NULL, cwdi.cwdi_rdir, RDIR, FREAD, (long)cwdi.cwdi_rdir); |
461 | /* | | 481 | /* |
462 | * current working directory vnode | | 482 | * current working directory vnode |
463 | */ | | 483 | */ |
464 | vtrans(NULL, cwdi.cwdi_cdir, CDIR, FREAD, (long)cwdi.cwdi_cdir); | | 484 | vtrans(NULL, cwdi.cwdi_cdir, CDIR, FREAD, (long)cwdi.cwdi_cdir); |
465 | #if 0 | | 485 | #if 0 |
466 | /* | | 486 | /* |
467 | * Disable for now, since p->p_tracep appears to point to a ktr_desc * | | 487 | * Disable for now, since p->p_tracep appears to point to a ktr_desc * |
468 | * ktrace vnode, if one | | 488 | * ktrace vnode, if one |
469 | */ | | 489 | */ |
470 | if (p->p_tracep) | | 490 | if (p->p_tracep) |
471 | ftrans(p->p_tracep, TRACE); | | 491 | ftrans(p->p_tracep, TRACE); |
472 | #endif | | 492 | #endif |
473 | /* | | 493 | /* |
474 | * open files | | 494 | * open files |
475 | */ | | 495 | */ |
476 | #define FPSIZE (sizeof (fdfile_t *)) | | 496 | #define FPSIZE (sizeof (fdfile_t *)) |
477 | ALLOC_OFILES(filed.fd_lastfile+1); | | 497 | ALLOC_OFILES(filed.fd_lastfile+1); |
478 | if (!KVM_READ(&filed.fd_dt->dt_ff, ofiles, | | 498 | if (!KVM_READ(&filed.fd_dt->dt_ff, ofiles, |
479 | (filed.fd_lastfile+1) * FPSIZE)) { | | 499 | (filed.fd_lastfile+1) * FPSIZE)) { |
480 | dprintf("can't read file structures at %p for pid %d", | | 500 | dprintf("can't read file structures at %p for pid %d", |
481 | &filed.fd_dt->dt_ff, Pid); | | 501 | &filed.fd_dt->dt_ff, Pid); |
482 | return; | | 502 | return; |
483 | } | | 503 | } |
484 | for (i = 0; i <= filed.fd_lastfile; i++) { | | 504 | for (i = 0; i <= filed.fd_lastfile; i++) { |
485 | if (ofiles[i] == NULL) | | 505 | if (ofiles[i] == NULL) |
486 | continue; | | 506 | continue; |
487 | ftrans(ofiles[i], i); | | 507 | ftrans(ofiles[i], i); |
488 | } | | 508 | } |
489 | } | | 509 | } |
490 | | | 510 | |
491 | static void | | 511 | static void |
492 | ftrans(fdfile_t *fp, int i) | | 512 | ftrans(fdfile_t *fp, int i) |
493 | { | | 513 | { |
494 | struct file file; | | 514 | struct file file; |
495 | fdfile_t fdfile; | | 515 | fdfile_t fdfile; |
496 | | | 516 | |
497 | if (!KVM_READ(fp, &fdfile, sizeof(fdfile))) { | | 517 | if (!KVM_READ(fp, &fdfile, sizeof(fdfile))) { |
498 | dprintf("can't read file %d at %p for pid %d", | | 518 | dprintf("can't read file %d at %p for pid %d", |
499 | i, fp, Pid); | | 519 | i, fp, Pid); |
500 | return; | | 520 | return; |
501 | } | | 521 | } |
502 | if (fdfile.ff_file == NULL) { | | 522 | if (fdfile.ff_file == NULL) { |
503 | dprintf("null ff_file for %d at %p for pid %d", | | 523 | dprintf("null ff_file for %d at %p for pid %d", |
504 | i, fp, Pid); | | 524 | i, fp, Pid); |
505 | return; | | 525 | return; |
506 | } | | 526 | } |
507 | if (!KVM_READ(fdfile.ff_file, &file, sizeof(file))) { | | 527 | if (!KVM_READ(fdfile.ff_file, &file, sizeof(file))) { |
508 | dprintf("can't read file %d at %p for pid %d", | | 528 | dprintf("can't read file %d at %p for pid %d", |
509 | i, fdfile.ff_file, Pid); | | 529 | i, fdfile.ff_file, Pid); |
510 | return; | | 530 | return; |
511 | } | | 531 | } |
512 | if (Aflg && file.f_type != DTYPE_VNODE && checkfile == 0) | | 532 | if (Aflg && file.f_type != DTYPE_VNODE && checkfile == 0) |
513 | (void)printf("%*lx ", | | 533 | (void)printf("%*lx ", |
514 | 2*(int)(sizeof(void*)), (long)fdfile.ff_file); | | 534 | 2*(int)(sizeof(void*)), (long)fdfile.ff_file); |
515 | switch (file.f_type) { | | 535 | switch (file.f_type) { |
516 | case DTYPE_VNODE: | | 536 | case DTYPE_VNODE: |
517 | vtrans(&file, file.f_data, i, file.f_flag, (long)fdfile.ff_file); | | 537 | vtrans(&file, file.f_data, i, file.f_flag, (long)fdfile.ff_file); |
518 | break; | | 538 | break; |
519 | case DTYPE_SOCKET: | | 539 | case DTYPE_SOCKET: |
520 | socktrans(&file, file.f_data, i); | | 540 | socktrans(&file, file.f_data, i); |
521 | break; | | 541 | break; |
522 | case DTYPE_PIPE: | | 542 | case DTYPE_PIPE: |
523 | if (checkfile == 0) | | 543 | if (checkfile == 0) |
524 | ptrans(&file, file.f_data, i); | | 544 | ptrans(&file, file.f_data, i); |
525 | break; | | 545 | break; |
526 | case DTYPE_MISC: | | 546 | case DTYPE_MISC: |
527 | case DTYPE_KQUEUE: | | 547 | case DTYPE_KQUEUE: |
528 | case DTYPE_CRYPTO: | | 548 | case DTYPE_CRYPTO: |
529 | case DTYPE_MQUEUE: | | 549 | case DTYPE_MQUEUE: |
530 | case DTYPE_SEM: | | 550 | case DTYPE_SEM: |
531 | if (checkfile == 0) | | 551 | if (checkfile == 0) |
532 | misctrans(&file, i); | | 552 | misctrans(&file, i); |
533 | break; | | 553 | break; |
534 | default: | | 554 | default: |
535 | dprintf("unknown file type %d for file %d of pid %d", | | 555 | dprintf("unknown file type %d for file %d of pid %d", |
536 | file.f_type, i, Pid); | | 556 | file.f_type, i, Pid); |
537 | break; | | 557 | break; |
538 | } | | 558 | } |
539 | } | | 559 | } |
540 | | | 560 | |
541 | static const char dead[] = "dead"; | | 561 | static const char dead[] = "dead"; |
542 | static const char *vnode_tag[] = { | | 562 | static const char *vnode_tag[] = { |
543 | VNODE_TAGS | | 563 | VNODE_TAGS |
544 | }; | | 564 | }; |
545 | | | 565 | |
546 | static const char * | | 566 | static const char * |
547 | vfilestat(struct vnode *vp, struct filestat *fsp) | | 567 | vfilestat(struct vnode *vp, struct filestat *fsp) |
548 | { | | 568 | { |
549 | const char *badtype = NULL; | | 569 | const char *badtype = NULL; |
550 | | | 570 | |
551 | if (vp->v_type == VNON) | | 571 | if (vp->v_type == VNON) |
552 | badtype = "none"; | | 572 | badtype = "none"; |
553 | else if (vp->v_type == VBAD) | | 573 | else if (vp->v_type == VBAD) |
554 | badtype = "bad"; | | 574 | badtype = "bad"; |
555 | else | | 575 | else |
556 | switch (vp->v_tag) { | | 576 | switch (vp->v_tag) { |
557 | case VT_NON: | | 577 | case VT_NON: |
558 | badtype = dead; | | 578 | badtype = dead; |
559 | break; | | 579 | break; |
560 | case VT_UFS: | | 580 | case VT_UFS: |
561 | case VT_LFS: | | 581 | case VT_LFS: |
562 | case VT_MFS: | | 582 | case VT_MFS: |
563 | if (!ufs_filestat(vp, fsp)) | | 583 | if (!ufs_filestat(vp, fsp)) |
564 | badtype = "error"; | | 584 | badtype = "error"; |
565 | break; | | 585 | break; |
566 | case VT_MSDOSFS: | | 586 | case VT_MSDOSFS: |
567 | if (!msdosfs_filestat(vp, fsp)) | | 587 | if (!msdosfs_filestat(vp, fsp)) |
568 | badtype = "error"; | | 588 | badtype = "error"; |
569 | break; | | 589 | break; |
570 | case VT_NFS: | | 590 | case VT_NFS: |
571 | if (!nfs_filestat(vp, fsp)) | | 591 | if (!nfs_filestat(vp, fsp)) |
572 | badtype = "error"; | | 592 | badtype = "error"; |
573 | break; | | 593 | break; |
574 | case VT_EXT2FS: | | 594 | case VT_EXT2FS: |
575 | if (!ext2fs_filestat(vp, fsp)) | | 595 | if (!ext2fs_filestat(vp, fsp)) |
576 | badtype = "error"; | | 596 | badtype = "error"; |
577 | break; | | 597 | break; |
578 | case VT_ISOFS: | | 598 | case VT_ISOFS: |
579 | if (!isofs_filestat(vp, fsp)) | | 599 | if (!isofs_filestat(vp, fsp)) |
580 | badtype = "error"; | | 600 | badtype = "error"; |
581 | break; | | 601 | break; |
582 | case VT_NTFS: | | 602 | case VT_NTFS: |
583 | if (!ntfs_filestat(vp, fsp)) | | 603 | if (!ntfs_filestat(vp, fsp)) |
584 | badtype = "error"; | | 604 | badtype = "error"; |
585 | break; | | 605 | break; |
586 | case VT_PTYFS: | | 606 | case VT_PTYFS: |
587 | if (!ptyfs_filestat(vp, fsp)) | | 607 | if (!ptyfs_filestat(vp, fsp)) |
588 | badtype = "error"; | | 608 | badtype = "error"; |
589 | break; | | 609 | break; |
590 | case VT_TMPFS: | | 610 | case VT_TMPFS: |
591 | if (!tmpfs_filestat(vp, fsp)) | | 611 | if (!tmpfs_filestat(vp, fsp)) |
592 | badtype = "error"; | | 612 | badtype = "error"; |
593 | break; | | 613 | break; |
594 | case VT_NULL: | | 614 | case VT_NULL: |
595 | case VT_OVERLAY: | | 615 | case VT_OVERLAY: |
596 | case VT_UMAP: | | 616 | case VT_UMAP: |
597 | badtype = layer_filestat(vp, fsp); | | 617 | badtype = layer_filestat(vp, fsp); |
598 | break; | | 618 | break; |
599 | default: { | | 619 | default: { |
600 | static char unknown[10]; | | 620 | static char unknown[10]; |
601 | (void)snprintf(unknown, sizeof unknown, "%s(%#x)", | | 621 | (void)snprintf(unknown, sizeof unknown, "%s(%#x)", |
602 | (size_t)vp->v_tag < __arraycount(vnode_tag) ? | | 622 | (size_t)vp->v_tag < __arraycount(vnode_tag) ? |
603 | vnode_tag[vp->v_tag] : "?", vp->v_tag); | | 623 | vnode_tag[vp->v_tag] : "?", vp->v_tag); |
604 | badtype = unknown; | | 624 | badtype = unknown; |
605 | break; | | 625 | break; |
606 | } | | 626 | } |
607 | } | | 627 | } |
608 | return badtype; | | 628 | return badtype; |
609 | } | | 629 | } |
610 | | | 630 | |
611 | static int | | 631 | static int |
612 | checkfs(struct vnode *vp, struct vnode *vn, struct filestat *fst, | | 632 | checkfs(struct vnode *vp, struct vnode *vn, struct filestat *fst, |
613 | const char **type, const char **fname) | | 633 | const char **type, const char **fname) |
614 | { | | 634 | { |
615 | *fname = NULL; | | 635 | *fname = NULL; |
616 | if (!KVM_READ(vp, vn, sizeof(*vn))) { | | 636 | if (!KVM_READ(vp, vn, sizeof(*vn))) { |
617 | dprintf("can't read vnode at %p for pid %d", vp, Pid); | | 637 | dprintf("can't read vnode at %p for pid %d", vp, Pid); |
618 | return 0; | | 638 | return 0; |
619 | } | | 639 | } |
620 | *type = vfilestat(vn, fst); | | 640 | *type = vfilestat(vn, fst); |
621 | if (checkfile) { | | 641 | if (checkfile) { |
622 | int fsmatch = 0; | | 642 | int fsmatch = 0; |
623 | DEVS *d; | | 643 | DEVS *d; |
624 | #if 0 | | 644 | #if 0 |
625 | if (*type && *type != dead) | | 645 | if (*type && *type != dead) |
626 | return 0; | | 646 | return 0; |
627 | #endif | | 647 | #endif |
628 | for (d = devs; d != NULL; d = d->next) { | | 648 | for (d = devs; d != NULL; d = d->next) { |
629 | if (d->fsid == fst->fsid) { | | 649 | if (d->fsid == fst->fsid) { |
630 | fsmatch = 1; | | 650 | fsmatch = 1; |
631 | if (d->ino == fst->fileid) { | | 651 | if (d->ino == fst->fileid) { |
632 | *fname = d->name; | | 652 | *fname = d->name; |
633 | break; | | 653 | break; |
634 | } | | 654 | } |
635 | } | | 655 | } |
636 | } | | 656 | } |
637 | if (fsmatch == 0 || (*fname == NULL && fsflg == 0)) | | 657 | if (fsmatch == 0 || (*fname == NULL && fsflg == 0)) |
638 | return 0; | | 658 | return 0; |
639 | } | | 659 | } |
640 | return 1; | | 660 | return 1; |
641 | } | | 661 | } |
642 | | | 662 | |
643 | static void | | 663 | static void |
644 | vprint(struct vnode *vn, struct filestat *fst) | | 664 | vprint(struct vnode *vn, struct filestat *fst) |
645 | { | | 665 | { |
646 | switch (vn->v_type) { | | 666 | switch (vn->v_type) { |
647 | case VBLK: | | 667 | case VBLK: |
648 | case VCHR: { | | 668 | case VCHR: { |
649 | const char *name; | | 669 | const char *name; |
650 | | | 670 | |
651 | if (nflg || ((name = devname(fst->rdev, vn->v_type == VCHR ? | | 671 | if (nflg || ((name = devname(fst->rdev, vn->v_type == VCHR ? |
652 | S_IFCHR : S_IFBLK)) == NULL)) | | 672 | S_IFCHR : S_IFBLK)) == NULL)) |
653 | (void)printf(" %s,%-2llu", | | 673 | (void)printf(" %s,%-2llu", |
654 | kdriver_search(vn->v_type, major(fst->rdev)), | | 674 | kdriver_search(vn->v_type, major(fst->rdev)), |
655 | (unsigned long long)minor(fst->rdev)); | | 675 | (unsigned long long)minor(fst->rdev)); |
656 | else | | 676 | else |
657 | (void)printf(" %6s", name); | | 677 | (void)printf(" %6s", name); |
658 | break; | | 678 | break; |
659 | } | | 679 | } |
660 | default: | | 680 | default: |
661 | (void)printf(" %6lld", (long long)fst->size); | | 681 | (void)printf(" %6lld", (long long)fst->size); |
662 | } | | 682 | } |
663 | } | | 683 | } |
664 | | | 684 | |
665 | void | | 685 | void |
666 | oprint(struct file *fp, const char *str) | | 686 | oprint(struct file *fp, const char *str) |
667 | { | | 687 | { |
668 | if (Oflg) | | 688 | if (Oflg) |
669 | (void)printf(" %6lld", (long long)(fp ? fp->f_offset : 0)); | | 689 | (void)printf(" %6lld", (long long)(fp ? fp->f_offset : 0)); |
670 | fputs(str, stdout); | | 690 | fputs(str, stdout); |
671 | } | | 691 | } |
672 | | | 692 | |
673 | static void | | 693 | static void |
674 | vtrans(struct file *fp, struct vnode *vp, int i, int flag, long addr) | | 694 | vtrans(struct file *fp, struct vnode *vp, int i, int flag, long addr) |
675 | { | | 695 | { |
676 | struct vnode vn; | | 696 | struct vnode vn; |
677 | char mode[15], rw[3]; | | 697 | char mode[15], rw[3]; |
678 | const char *badtype, *filename; | | 698 | const char *badtype, *filename; |
679 | struct filestat fst; | | 699 | struct filestat fst; |
680 | | | 700 | |
681 | if (!checkfs(vp, &vn, &fst, &badtype, &filename)) | | 701 | if (!checkfs(vp, &vn, &fst, &badtype, &filename)) |
682 | return; | | 702 | return; |
683 | | | 703 | |
684 | if (Aflg) | | 704 | if (Aflg) |
685 | (void)printf("%*lx ", 2*(int)(sizeof(void*)), addr); | | 705 | (void)printf("%*lx ", 2*(int)(sizeof(void*)), addr); |
686 | PREFIX(i); | | 706 | PREFIX(i); |
687 | if (badtype == dead) { | | 707 | if (badtype == dead) { |
688 | char buf[1024]; | | 708 | char buf[1024]; |
689 | (void)snprintb(buf, sizeof(buf), VNODE_FLAGBITS, | | 709 | (void)snprintb(buf, sizeof(buf), VNODE_FLAGBITS, |
690 | vn.v_iflag | vn.v_vflag | vn.v_uflag); | | 710 | vn.v_iflag | vn.v_vflag | vn.v_uflag); |
691 | (void)printf(" flags %s\n", buf); | | 711 | (void)printf(" flags %s\n", buf); |
692 | return; | | 712 | return; |
693 | } else if (badtype) { | | 713 | } else if (badtype) { |
694 | (void)printf(" - - %10s -\n", badtype); | | 714 | (void)printf(" - - %10s -\n", badtype); |
695 | return; | | 715 | return; |
696 | } | | 716 | } |
697 | if (nflg) | | 717 | if (nflg) |
698 | (void)printf(" %3llu,%-2llu", | | 718 | (void)printf(" %3llu,%-2llu", |
699 | (unsigned long long)major(fst.fsid), | | 719 | (unsigned long long)major(fst.fsid), |
700 | (unsigned long long)minor(fst.fsid)); | | 720 | (unsigned long long)minor(fst.fsid)); |
701 | else | | 721 | else |
702 | (void)printf(" %-8s", getmnton(vn.v_mount)); | | 722 | (void)printf(" %-8s", getmnton(vn.v_mount)); |
703 | if (nflg) | | 723 | if (nflg) |
704 | (void)snprintf(mode, sizeof mode, "%6o", fst.mode); | | 724 | (void)snprintf(mode, sizeof mode, "%6o", fst.mode); |
705 | else | | 725 | else |
706 | strmode(fst.mode, mode); | | 726 | strmode(fst.mode, mode); |
707 | (void)printf(" %8"PRIu64" %*s", fst.fileid, nflg ? 5 : 10, mode); | | 727 | (void)printf(" %8"PRIu64" %*s", fst.fileid, nflg ? 5 : 10, mode); |
708 | if (Oflg) { | | 728 | if (Oflg) { |
709 | oprint(fp, ""); | | 729 | oprint(fp, ""); |
710 | } else { | | 730 | } else { |
711 | vprint(&vn, &fst); | | 731 | vprint(&vn, &fst); |
712 | } | | 732 | } |
713 | rw[0] = '\0'; | | 733 | rw[0] = '\0'; |
714 | if (flag & FREAD) | | 734 | if (flag & FREAD) |
715 | (void)strlcat(rw, "r", sizeof(rw)); | | 735 | (void)strlcat(rw, "r", sizeof(rw)); |
716 | if (flag & FWRITE) | | 736 | if (flag & FWRITE) |
717 | (void)strlcat(rw, "w", sizeof(rw)); | | 737 | (void)strlcat(rw, "w", sizeof(rw)); |
718 | (void)printf(" %-2s", rw); | | 738 | (void)printf(" %-2s", rw); |
719 | if (filename && !fsflg) | | 739 | if (filename && !fsflg) |
720 | (void)printf(" %s", filename); | | 740 | (void)printf(" %s", filename); |
721 | (void)putchar('\n'); | | 741 | (void)putchar('\n'); |
722 | } | | 742 | } |
723 | | | 743 | |
724 | static int | | 744 | static int |
725 | ufs_filestat(struct vnode *vp, struct filestat *fsp) | | 745 | ufs_filestat(struct vnode *vp, struct filestat *fsp) |
726 | { | | 746 | { |
727 | struct inode inode; | | 747 | struct inode inode; |
728 | struct ufsmount ufsmount; | | 748 | struct ufsmount ufsmount; |
729 | union dinode { | | 749 | union dinode { |
730 | struct ufs1_dinode dp1; | | 750 | struct ufs1_dinode dp1; |
731 | struct ufs2_dinode dp2; | | 751 | struct ufs2_dinode dp2; |
732 | } dip; | | 752 | } dip; |
733 | | | 753 | |
734 | if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { | | 754 | if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { |
735 | dprintf("can't read inode at %p for pid %d", VTOI(vp), Pid); | | 755 | dprintf("can't read inode at %p for pid %d", VTOI(vp), Pid); |
736 | return 0; | | 756 | return 0; |
737 | } | | 757 | } |
738 | | | 758 | |
739 | if (!KVM_READ(inode.i_ump, &ufsmount, sizeof (struct ufsmount))) { | | 759 | if (!KVM_READ(inode.i_ump, &ufsmount, sizeof (struct ufsmount))) { |
740 | dprintf("can't read ufsmount at %p for pid %d", inode.i_ump, Pid); | | 760 | dprintf("can't read ufsmount at %p for pid %d", inode.i_ump, Pid); |
741 | return 0; | | 761 | return 0; |
742 | } | | 762 | } |
743 | | | 763 | |
744 | switch (ufsmount.um_fstype) { | | 764 | switch (ufsmount.um_fstype) { |
745 | case UFS1: | | 765 | case UFS1: |
746 | if (!KVM_READ(inode.i_din.ffs1_din, &dip, | | 766 | if (!KVM_READ(inode.i_din.ffs1_din, &dip, |
747 | sizeof(struct ufs1_dinode))) { | | 767 | sizeof(struct ufs1_dinode))) { |
748 | dprintf("can't read dinode at %p for pid %d", | | 768 | dprintf("can't read dinode at %p for pid %d", |
749 | inode.i_din.ffs1_din, Pid); | | 769 | inode.i_din.ffs1_din, Pid); |
750 | return 0; | | 770 | return 0; |
751 | } | | 771 | } |
752 | fsp->rdev = dip.dp1.di_rdev; | | 772 | fsp->rdev = dip.dp1.di_rdev; |
753 | break; | | 773 | break; |
754 | case UFS2: | | 774 | case UFS2: |
755 | if (!KVM_READ(inode.i_din.ffs2_din, &dip, | | 775 | if (!KVM_READ(inode.i_din.ffs2_din, &dip, |
756 | sizeof(struct ufs2_dinode))) { | | 776 | sizeof(struct ufs2_dinode))) { |
757 | dprintf("can't read dinode at %p for pid %d", | | 777 | dprintf("can't read dinode at %p for pid %d", |
758 | inode.i_din.ffs2_din, Pid); | | 778 | inode.i_din.ffs2_din, Pid); |
759 | return 0; | | 779 | return 0; |
760 | } | | 780 | } |
761 | fsp->rdev = dip.dp2.di_rdev; | | 781 | fsp->rdev = dip.dp2.di_rdev; |
762 | break; | | 782 | break; |
763 | default: | | 783 | default: |
764 | dprintf("unknown ufs type %ld for pid %d", | | 784 | dprintf("unknown ufs type %ld for pid %d", |
765 | ufsmount.um_fstype, Pid); | | 785 | ufsmount.um_fstype, Pid); |
766 | break; | | 786 | break; |
767 | } | | 787 | } |
768 | fsp->fsid = inode.i_dev & 0xffff; | | 788 | fsp->fsid = inode.i_dev & 0xffff; |
769 | fsp->fileid = inode.i_number; | | 789 | fsp->fileid = inode.i_number; |
770 | fsp->mode = (mode_t)inode.i_mode; | | 790 | fsp->mode = (mode_t)inode.i_mode; |
771 | fsp->size = inode.i_size; | | 791 | fsp->size = inode.i_size; |
772 | | | 792 | |
773 | return 1; | | 793 | return 1; |
774 | } | | 794 | } |
775 | | | 795 | |
776 | static int | | 796 | static int |
777 | ext2fs_filestat(struct vnode *vp, struct filestat *fsp) | | 797 | ext2fs_filestat(struct vnode *vp, struct filestat *fsp) |
778 | { | | 798 | { |
779 | struct inode inode; | | 799 | struct inode inode; |
780 | struct ext2fs_dinode dinode; | | 800 | struct ext2fs_dinode dinode; |
781 | | | 801 | |
782 | if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { | | 802 | if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { |
783 | dprintf("can't read inode at %p for pid %d", VTOI(vp), Pid); | | 803 | dprintf("can't read inode at %p for pid %d", VTOI(vp), Pid); |
784 | return 0; | | 804 | return 0; |
785 | } | | 805 | } |
786 | fsp->fsid = inode.i_dev & 0xffff; | | 806 | fsp->fsid = inode.i_dev & 0xffff; |
787 | fsp->fileid = inode.i_number; | | 807 | fsp->fileid = inode.i_number; |
788 | | | 808 | |
789 | if (!KVM_READ(inode.i_din.e2fs_din, &dinode, sizeof dinode)) { | | 809 | if (!KVM_READ(inode.i_din.e2fs_din, &dinode, sizeof dinode)) { |
790 | dprintf("can't read ext2fs_dinode at %p for pid %d", | | 810 | dprintf("can't read ext2fs_dinode at %p for pid %d", |
791 | inode.i_din.e2fs_din, Pid); | | 811 | inode.i_din.e2fs_din, Pid); |
792 | return 0; | | 812 | return 0; |
793 | } | | 813 | } |
794 | fsp->mode = dinode.e2di_mode; | | 814 | fsp->mode = dinode.e2di_mode; |
795 | fsp->size = dinode.e2di_size; | | 815 | fsp->size = dinode.e2di_size; |
796 | fsp->rdev = dinode.e2di_rdev; | | 816 | fsp->rdev = dinode.e2di_rdev; |
797 | | | 817 | |
798 | return 1; | | 818 | return 1; |
799 | } | | 819 | } |
800 | | | 820 | |
801 | static int | | 821 | static int |
802 | nfs_filestat(struct vnode *vp, struct filestat *fsp) | | 822 | nfs_filestat(struct vnode *vp, struct filestat *fsp) |
803 | { | | 823 | { |
804 | struct nfsnode nfsnode; | | 824 | struct nfsnode nfsnode; |
805 | struct vattr va; | | 825 | struct vattr va; |
806 | | | 826 | |
807 | if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) { | | 827 | if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) { |
808 | dprintf("can't read nfsnode at %p for pid %d", VTONFS(vp), | | 828 | dprintf("can't read nfsnode at %p for pid %d", VTONFS(vp), |
809 | Pid); | | 829 | Pid); |
810 | return 0; | | 830 | return 0; |
811 | } | | 831 | } |
812 | if (!KVM_READ(nfsnode.n_vattr, &va, sizeof(va))) { | | 832 | if (!KVM_READ(nfsnode.n_vattr, &va, sizeof(va))) { |
813 | dprintf("can't read vnode attributes at %p for pid %d", | | 833 | dprintf("can't read vnode attributes at %p for pid %d", |
814 | nfsnode.n_vattr, Pid); | | 834 | nfsnode.n_vattr, Pid); |
815 | return 0; | | 835 | return 0; |
816 | } | | 836 | } |
817 | fsp->fsid = va.va_fsid; | | 837 | fsp->fsid = va.va_fsid; |
818 | fsp->fileid = va.va_fileid; | | 838 | fsp->fileid = va.va_fileid; |
819 | fsp->size = nfsnode.n_size; | | 839 | fsp->size = nfsnode.n_size; |
820 | fsp->rdev = va.va_rdev; | | 840 | fsp->rdev = va.va_rdev; |
821 | fsp->mode = (mode_t)va.va_mode | getftype(vp->v_type); | | 841 | fsp->mode = (mode_t)va.va_mode | getftype(vp->v_type); |
822 | | | 842 | |
823 | return 1; | | 843 | return 1; |
824 | } | | 844 | } |
825 | | | 845 | |
826 | static int | | 846 | static int |
827 | msdosfs_filestat(struct vnode *vp, struct filestat *fsp) | | 847 | msdosfs_filestat(struct vnode *vp, struct filestat *fsp) |
828 | { | | 848 | { |
829 | struct denode de; | | 849 | struct denode de; |
830 | struct msdosfsmount mp; | | 850 | struct msdosfsmount mp; |
831 | | | 851 | |
832 | if (!KVM_READ(VTONFS(vp), &de, sizeof(de))) { | | 852 | if (!KVM_READ(VTONFS(vp), &de, sizeof(de))) { |
833 | dprintf("can't read denode at %p for pid %d", VTONFS(vp), | | 853 | dprintf("can't read denode at %p for pid %d", VTONFS(vp), |
834 | Pid); | | 854 | Pid); |
835 | return 0; | | 855 | return 0; |
836 | } | | 856 | } |
837 | if (!KVM_READ(de.de_pmp, &mp, sizeof(mp))) { | | 857 | if (!KVM_READ(de.de_pmp, &mp, sizeof(mp))) { |
838 | dprintf("can't read mount struct at %p for pid %d", de.de_pmp, | | 858 | dprintf("can't read mount struct at %p for pid %d", de.de_pmp, |
839 | Pid); | | 859 | Pid); |
840 | return 0; | | 860 | return 0; |
841 | } | | 861 | } |
842 | | | 862 | |
843 | fsp->fsid = de.de_dev & 0xffff; | | 863 | fsp->fsid = de.de_dev & 0xffff; |
844 | fsp->fileid = 0; /* XXX see msdosfs_vptofh() for more info */ | | 864 | fsp->fileid = 0; /* XXX see msdosfs_vptofh() for more info */ |
845 | fsp->size = de.de_FileSize; | | 865 | fsp->size = de.de_FileSize; |
846 | fsp->rdev = 0; /* msdosfs doesn't support device files */ | | 866 | fsp->rdev = 0; /* msdosfs doesn't support device files */ |
847 | fsp->mode = (0777 & mp.pm_mask) | getftype(vp->v_type); | | 867 | fsp->mode = (0777 & mp.pm_mask) | getftype(vp->v_type); |
848 | return 1; | | 868 | return 1; |
849 | } | | 869 | } |
850 | | | 870 | |
851 | static const char * | | 871 | static const char * |
852 | layer_filestat(struct vnode *vp, struct filestat *fsp) | | 872 | layer_filestat(struct vnode *vp, struct filestat *fsp) |
853 | { | | 873 | { |
854 | struct layer_node layer_node; | | 874 | struct layer_node layer_node; |
855 | struct mount mount; | | 875 | struct mount mount; |
856 | struct vnode vn; | | 876 | struct vnode vn; |
857 | const char *badtype; | | 877 | const char *badtype; |
858 | | | 878 | |
859 | if (!KVM_READ(VTOLAYER(vp), &layer_node, sizeof(layer_node))) { | | 879 | if (!KVM_READ(VTOLAYER(vp), &layer_node, sizeof(layer_node))) { |
860 | dprintf("can't read layer_node at %p for pid %d", | | 880 | dprintf("can't read layer_node at %p for pid %d", |
861 | VTOLAYER(vp), Pid); | | 881 | VTOLAYER(vp), Pid); |
862 | return "error"; | | 882 | return "error"; |
863 | } | | 883 | } |
864 | if (!KVM_READ(vp->v_mount, &mount, sizeof(struct mount))) { | | 884 | if (!KVM_READ(vp->v_mount, &mount, sizeof(struct mount))) { |
865 | dprintf("can't read mount struct at %p for pid %d", | | 885 | dprintf("can't read mount struct at %p for pid %d", |
866 | vp->v_mount, Pid); | | 886 | vp->v_mount, Pid); |
867 | return "error"; | | 887 | return "error"; |
868 | } | | 888 | } |
869 | vp = layer_node.layer_lowervp; | | 889 | vp = layer_node.layer_lowervp; |
870 | if (!KVM_READ(vp, &vn, sizeof(struct vnode))) { | | 890 | if (!KVM_READ(vp, &vn, sizeof(struct vnode))) { |
871 | dprintf("can't read vnode at %p for pid %d", vp, Pid); | | 891 | dprintf("can't read vnode at %p for pid %d", vp, Pid); |
872 | return "error"; | | 892 | return "error"; |
873 | } | | 893 | } |
874 | if ((badtype = vfilestat(&vn, fsp)) == NULL) | | 894 | if ((badtype = vfilestat(&vn, fsp)) == NULL) |
875 | fsp->fsid = mount.mnt_stat.f_fsidx.__fsid_val[0]; | | 895 | fsp->fsid = mount.mnt_stat.f_fsidx.__fsid_val[0]; |
876 | return badtype; | | 896 | return badtype; |
877 | } | | 897 | } |
878 | | | 898 | |
879 | static char * | | 899 | static char * |
880 | getmnton(struct mount *m) | | 900 | getmnton(struct mount *m) |
881 | { | | 901 | { |
882 | static struct mount mount; | | 902 | static struct mount mount; |
883 | static struct mtab { | | 903 | static struct mtab { |
884 | struct mtab *next; | | 904 | struct mtab *next; |
885 | struct mount *m; | | 905 | struct mount *m; |
886 | char mntonname[MNAMELEN]; | | 906 | char mntonname[MNAMELEN]; |
887 | } *mhead = NULL; | | 907 | } *mhead = NULL; |
888 | struct mtab *mt; | | 908 | struct mtab *mt; |
889 | | | 909 | |
890 | for (mt = mhead; mt != NULL; mt = mt->next) | | 910 | for (mt = mhead; mt != NULL; mt = mt->next) |
891 | if (m == mt->m) | | 911 | if (m == mt->m) |
892 | return mt->mntonname; | | 912 | return mt->mntonname; |
893 | if (!KVM_READ(m, &mount, sizeof(struct mount))) { | | 913 | if (!KVM_READ(m, &mount, sizeof(struct mount))) { |
894 | warnx("can't read mount table at %p", m); | | 914 | warnx("can't read mount table at %p", m); |
895 | return NULL; | | 915 | return NULL; |
896 | } | | 916 | } |
897 | if ((mt = malloc(sizeof (struct mtab))) == NULL) { | | 917 | if ((mt = malloc(sizeof (struct mtab))) == NULL) { |
898 | err(1, "malloc(%u)", (unsigned int)sizeof(struct mtab)); | | 918 | err(1, "malloc(%u)", (unsigned int)sizeof(struct mtab)); |
899 | } | | 919 | } |
900 | mt->m = m; | | 920 | mt->m = m; |
901 | (void)memmove(&mt->mntonname[0], &mount.mnt_stat.f_mntonname[0], | | 921 | (void)memmove(&mt->mntonname[0], &mount.mnt_stat.f_mntonname[0], |
902 | MNAMELEN); | | 922 | MNAMELEN); |
903 | mt->next = mhead; | | 923 | mt->next = mhead; |
904 | mhead = mt; | | 924 | mhead = mt; |
905 | return mt->mntonname; | | 925 | return mt->mntonname; |
906 | } | | 926 | } |
907 | | | 927 | |
908 | static const char * | | 928 | static const char * |
909 | inet_addrstr(char *buf, size_t len, const struct in_addr *a, uint16_t p, bool isdg) | | 929 | inet_addrstr(char *buf, size_t len, const struct in_addr *a, uint16_t p, bool isdg) |
910 | { | | 930 | { |
911 | char addr[256], serv[256]; | | 931 | char addr[256], serv[256]; |
912 | struct sockaddr_in sin; | | 932 | struct sockaddr_in sin; |
913 | const int niflags = | | 933 | const int niflags = |
914 | (nflg ? (NI_NUMERICHOST|NI_NUMERICSERV) : 0) | | | 934 | (nflg ? (NI_NUMERICHOST|NI_NUMERICSERV) : 0) | |
915 | (isdg ? NI_DGRAM : 0); | | 935 | (isdg ? NI_DGRAM : 0); |
916 | | | 936 | |
917 | | | 937 | |
918 | (void)memset(&sin, 0, sizeof(sin)); | | 938 | (void)memset(&sin, 0, sizeof(sin)); |
919 | sin.sin_family = AF_INET; | | 939 | sin.sin_family = AF_INET; |
920 | sin.sin_len = sizeof(sin); | | 940 | sin.sin_len = sizeof(sin); |
921 | sin.sin_addr = *a; | | 941 | sin.sin_addr = *a; |
922 | sin.sin_port = htons(p); | | 942 | sin.sin_port = htons(p); |
923 | | | 943 | |
924 | serv[0] = '\0'; | | 944 | serv[0] = '\0'; |
925 | | | 945 | |
926 | if (getnameinfo((struct sockaddr *)&sin, sin.sin_len, | | 946 | if (getnameinfo((struct sockaddr *)&sin, sin.sin_len, |
927 | addr, sizeof(addr), serv, sizeof(serv), niflags)) { | | 947 | addr, sizeof(addr), serv, sizeof(serv), niflags)) { |
928 | if (inet_ntop(AF_INET, a, addr, sizeof(addr)) == NULL) | | 948 | if (inet_ntop(AF_INET, a, addr, sizeof(addr)) == NULL) |
929 | strlcpy(addr, "invalid", sizeof(addr)); | | 949 | strlcpy(addr, "invalid", sizeof(addr)); |
930 | } | | 950 | } |
931 | | | 951 | |
932 | if (serv[0] == '\0') | | 952 | if (serv[0] == '\0') |
933 | snprintf(serv, sizeof(serv), "%u", p); | | 953 | snprintf(serv, sizeof(serv), "%u", p); |
934 | | | 954 | |
935 | if (a->s_addr == INADDR_ANY) { | | 955 | if (a->s_addr == INADDR_ANY) { |
936 | if (p == 0) | | 956 | if (p == 0) |
937 | buf[0] = '\0'; | | 957 | buf[0] = '\0'; |
938 | else | | 958 | else |
939 | snprintf(buf, len, "*:%s", serv); | | 959 | snprintf(buf, len, "*:%s", serv); |
940 | return buf; | | 960 | return buf; |
941 | } | | 961 | } |
942 | | | 962 | |
943 | snprintf(buf, len, "%s:%s", addr, serv); | | 963 | snprintf(buf, len, "%s:%s", addr, serv); |
944 | return buf; | | 964 | return buf; |
945 | } | | 965 | } |
946 | | | 966 | |
947 | #ifdef INET6 | | 967 | #ifdef INET6 |
948 | static const char * | | 968 | static const char * |
949 | inet6_addrstr(char *buf, size_t len, const struct in6_addr *a, uint16_t p, bool isdg) | | 969 | inet6_addrstr(char *buf, size_t len, const struct in6_addr *a, uint16_t p, bool isdg) |
950 | { | | 970 | { |
951 | char addr[256], serv[256]; | | 971 | char addr[256], serv[256]; |
952 | struct sockaddr_in6 sin6; | | 972 | struct sockaddr_in6 sin6; |
953 | const int niflags = | | 973 | const int niflags = |
954 | (nflg ? (NI_NUMERICHOST|NI_NUMERICSERV) : 0) | | | 974 | (nflg ? (NI_NUMERICHOST|NI_NUMERICSERV) : 0) | |
955 | (isdg ? NI_DGRAM : 0); | | 975 | (isdg ? NI_DGRAM : 0); |
956 | | | 976 | |
957 | (void)memset(&sin6, 0, sizeof(sin6)); | | 977 | (void)memset(&sin6, 0, sizeof(sin6)); |
958 | sin6.sin6_family = AF_INET6; | | 978 | sin6.sin6_family = AF_INET6; |
959 | sin6.sin6_len = sizeof(sin6); | | 979 | sin6.sin6_len = sizeof(sin6); |
960 | sin6.sin6_addr = *a; | | 980 | sin6.sin6_addr = *a; |
961 | sin6.sin6_port = htons(p); | | 981 | sin6.sin6_port = htons(p); |
962 | | | 982 | |
963 | inet6_getscopeid(&sin6, INET6_IS_ADDR_LINKLOCAL); | | 983 | inet6_getscopeid(&sin6, INET6_IS_ADDR_LINKLOCAL); |
964 | serv[0] = '\0'; | | 984 | serv[0] = '\0'; |
965 | | | 985 | |
966 | if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, | | 986 | if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, |
967 | addr, sizeof(addr), serv, sizeof(serv), niflags)) { | | 987 | addr, sizeof(addr), serv, sizeof(serv), niflags)) { |
968 | if (inet_ntop(AF_INET6, a, addr, sizeof(addr)) == NULL) | | 988 | if (inet_ntop(AF_INET6, a, addr, sizeof(addr)) == NULL) |
969 | strlcpy(addr, "invalid", sizeof(addr)); | | 989 | strlcpy(addr, "invalid", sizeof(addr)); |
970 | } | | 990 | } |
971 | | | 991 | |
972 | if (serv[0] == '\0') | | 992 | if (serv[0] == '\0') |
973 | snprintf(serv, sizeof(serv), "%u", p); | | 993 | snprintf(serv, sizeof(serv), "%u", p); |
974 | | | 994 | |
975 | if (IN6_IS_ADDR_UNSPECIFIED(a)) { | | 995 | if (IN6_IS_ADDR_UNSPECIFIED(a)) { |
976 | if (p == 0) | | 996 | if (p == 0) |
977 | buf[0] = '\0'; | | 997 | buf[0] = '\0'; |
978 | else | | 998 | else |
979 | snprintf(buf, len, "*:%s", serv); | | 999 | snprintf(buf, len, "*:%s", serv); |
980 | return buf; | | 1000 | return buf; |
981 | } | | 1001 | } |
982 | | | 1002 | |
983 | if (strchr(addr, ':') == NULL) | | 1003 | if (strchr(addr, ':') == NULL) |
984 | snprintf(buf, len, "%s:%s", addr, serv); | | 1004 | snprintf(buf, len, "%s:%s", addr, serv); |
985 | else | | 1005 | else |
986 | snprintf(buf, len, "[%s]:%s", addr, serv); | | 1006 | snprintf(buf, len, "[%s]:%s", addr, serv); |
987 | | | 1007 | |
988 | return buf; | | 1008 | return buf; |
989 | } | | 1009 | } |
990 | #endif | | 1010 | #endif |
991 | | | 1011 | |
992 | static const char * | | 1012 | static const char * |
993 | at_addrstr(char *buf, size_t len, const struct sockaddr_at *sat) | | 1013 | at_addrstr(char *buf, size_t len, const struct sockaddr_at *sat) |
994 | { | | 1014 | { |
995 | const struct netrange *nr = &sat->sat_range.r_netrange; | | 1015 | const struct netrange *nr = &sat->sat_range.r_netrange; |
996 | const struct at_addr *at = &sat->sat_addr; | | 1016 | const struct at_addr *at = &sat->sat_addr; |
997 | char addr[64], phase[64], range[64]; | | 1017 | char addr[64], phase[64], range[64]; |
998 | | | 1018 | |
999 | if (sat->sat_port || at->s_net || at->s_node) { | | 1019 | if (sat->sat_port || at->s_net || at->s_node) { |
1000 | if (at->s_net || at->s_node) | | 1020 | if (at->s_net || at->s_node) |
1001 | snprintf(addr, sizeof(addr), "%u.%u:%u", | | 1021 | snprintf(addr, sizeof(addr), "%u.%u:%u", |
1002 | ntohs(at->s_net), at->s_node, sat->sat_port); | | 1022 | ntohs(at->s_net), at->s_node, sat->sat_port); |
1003 | else | | 1023 | else |
1004 | snprintf(addr, sizeof(addr), "*:%u", sat->sat_port); | | 1024 | snprintf(addr, sizeof(addr), "*:%u", sat->sat_port); |
1005 | } else | | 1025 | } else |
1006 | addr[0] = '\0'; | | 1026 | addr[0] = '\0'; |
1007 | | | 1027 | |
1008 | if (nr->nr_phase) | | 1028 | if (nr->nr_phase) |
1009 | snprintf(phase, sizeof(phase), " phase %u", nr->nr_phase); | | 1029 | snprintf(phase, sizeof(phase), " phase %u", nr->nr_phase); |
1010 | else | | 1030 | else |
1011 | phase[0] = '\0'; | | 1031 | phase[0] = '\0'; |
1012 | | | 1032 | |
1013 | if (nr->nr_firstnet || nr->nr_lastnet) | | 1033 | if (nr->nr_firstnet || nr->nr_lastnet) |
1014 | snprintf(range, sizeof(range), " range [%u-%u]", | | 1034 | snprintf(range, sizeof(range), " range [%u-%u]", |
1015 | ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet)); | | 1035 | ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet)); |
1016 | else | | 1036 | else |
1017 | range[0] = '\0'; | | 1037 | range[0] = '\0'; |
1018 | | | 1038 | |
1019 | snprintf(buf, len, "%s%s%s", addr, phase, range); | | 1039 | snprintf(buf, len, "%s%s%s", addr, phase, range); |
1020 | return buf; | | 1040 | return buf; |
1021 | } | | 1041 | } |
1022 | | | 1042 | |
1023 | static void | | 1043 | static void |
1024 | socktrans(struct file *f, struct socket *sock, int i) | | 1044 | socktrans(struct file *f, struct socket *sock, int i) |
1025 | { | | 1045 | { |
1026 | static const char *stypename[] = { | | 1046 | static const char *stypename[] = { |
1027 | "unused", /* 0 */ | | 1047 | "unused", /* 0 */ |
1028 | "stream", /* 1 */ | | 1048 | "stream", /* 1 */ |
1029 | "dgram", /* 2 */ | | 1049 | "dgram", /* 2 */ |
1030 | "raw", /* 3 */ | | 1050 | "raw", /* 3 */ |
1031 | "rdm", /* 4 */ | | 1051 | "rdm", /* 4 */ |
1032 | "seqpak" /* 5 */ | | 1052 | "seqpak" /* 5 */ |
1033 | }; | | 1053 | }; |
1034 | #define STYPEMAX 5 | | 1054 | #define STYPEMAX 5 |
1035 | struct socket so; | | 1055 | struct socket so; |
1036 | struct protosw proto; | | 1056 | struct protosw proto; |
1037 | struct domain dom; | | 1057 | struct domain dom; |
1038 | struct inpcb inpcb; | | 1058 | struct inpcb inpcb; |
1039 | #ifdef INET6 | | 1059 | #ifdef INET6 |
1040 | struct in6pcb in6pcb; | | 1060 | struct in6pcb in6pcb; |
1041 | #endif | | 1061 | #endif |
1042 | struct unpcb unpcb; | | 1062 | struct unpcb unpcb; |
1043 | struct ddpcb ddpcb; | | 1063 | struct ddpcb ddpcb; |
1044 | int len; | | 1064 | int len; |
1045 | char dname[32]; | | 1065 | char dname[32]; |
1046 | char lbuf[512], fbuf[512], pbuf[24]; | | 1066 | char lbuf[512], fbuf[512], pbuf[24]; |
1047 | bool isdgram; | | 1067 | bool isdgram; |
1048 | | | 1068 | |
1049 | pbuf[0] = '\0'; | | 1069 | pbuf[0] = '\0'; |
1050 | /* fill in socket */ | | 1070 | /* fill in socket */ |
1051 | if (!KVM_READ(sock, &so, sizeof(struct socket))) { | | 1071 | if (!KVM_READ(sock, &so, sizeof(struct socket))) { |
1052 | dprintf("can't read sock at %p", sock); | | 1072 | dprintf("can't read sock at %p", sock); |
1053 | goto bad; | | 1073 | goto bad; |
1054 | } | | 1074 | } |
1055 | | | 1075 | |
1056 | /* fill in protosw entry */ | | 1076 | /* fill in protosw entry */ |
1057 | if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) { | | 1077 | if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) { |
1058 | dprintf("can't read protosw at %p", so.so_proto); | | 1078 | dprintf("can't read protosw at %p", so.so_proto); |
1059 | goto bad; | | 1079 | goto bad; |
1060 | } | | 1080 | } |
1061 | | | 1081 | |
1062 | /* fill in domain */ | | 1082 | /* fill in domain */ |
1063 | if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) { | | 1083 | if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) { |
1064 | dprintf("can't read domain at %p", proto.pr_domain); | | 1084 | dprintf("can't read domain at %p", proto.pr_domain); |
1065 | goto bad; | | 1085 | goto bad; |
1066 | } | | 1086 | } |
1067 | | | 1087 | |
1068 | if (checkfile && dom.dom_family != AF_LOCAL) | | 1088 | if (checkfile && dom.dom_family != AF_LOCAL) |
1069 | return; | | 1089 | return; |
1070 | | | 1090 | |
1071 | if ((len = kvm_read(kd, (u_long)dom.dom_name, dname, | | 1091 | if ((len = kvm_read(kd, (u_long)dom.dom_name, dname, |
1072 | sizeof(dname) - 1)) != sizeof(dname) -1) { | | 1092 | sizeof(dname) - 1)) != sizeof(dname) -1) { |
1073 | dprintf("can't read domain name at %p", dom.dom_name); | | 1093 | dprintf("can't read domain name at %p", dom.dom_name); |
1074 | dname[0] = '\0'; | | 1094 | dname[0] = '\0'; |
1075 | } | | 1095 | } |
1076 | else | | 1096 | else |
1077 | dname[len] = '\0'; | | 1097 | dname[len] = '\0'; |
1078 | | | 1098 | |
1079 | /* | | 1099 | /* |
1080 | * protocol specific formatting | | 1100 | * protocol specific formatting |
1081 | * | | 1101 | * |
1082 | * Try to find interesting things to print. For TCP, the interesting | | 1102 | * Try to find interesting things to print. For TCP, the interesting |
1083 | * thing is the address of the tcpcb, for UDP and others, just the | | 1103 | * thing is the address of the tcpcb, for UDP and others, just the |
1084 | * inpcb (socket pcb). For UNIX domain, its the address of the socket | | 1104 | * inpcb (socket pcb). For UNIX domain, its the address of the socket |
1085 | * pcb and the address of the connected pcb (if connected). Otherwise | | 1105 | * pcb and the address of the connected pcb (if connected). Otherwise |
1086 | * just print the protocol number and address of the socket itself. | | 1106 | * just print the protocol number and address of the socket itself. |
1087 | * The idea is not to duplicate netstat, but to make available enough | | 1107 | * The idea is not to duplicate netstat, but to make available enough |
1088 | * information for further analysis. | | 1108 | * information for further analysis. |
1089 | */ | | 1109 | */ |
1090 | fbuf[0] = '\0'; | | 1110 | fbuf[0] = '\0'; |
1091 | lbuf[0] = '\0'; | | 1111 | lbuf[0] = '\0'; |
1092 | isdgram = false; | | 1112 | isdgram = false; |
1093 | switch(dom.dom_family) { | | 1113 | switch(dom.dom_family) { |
1094 | case AF_INET: | | 1114 | case AF_INET: |
1095 | getinetproto(pbuf, sizeof(pbuf), proto.pr_protocol); | | 1115 | getinetproto(pbuf, sizeof(pbuf), proto.pr_protocol); |
1096 | switch (proto.pr_protocol) { | | 1116 | switch (proto.pr_protocol) { |
1097 | case IPPROTO_UDP: | | 1117 | case IPPROTO_UDP: |
1098 | isdgram = true; | | 1118 | isdgram = true; |
1099 | /* FALLTHROUGH */ | | 1119 | /* FALLTHROUGH */ |
1100 | case IPPROTO_TCP: | | 1120 | case IPPROTO_TCP: |
1101 | if (so.so_pcb == NULL) | | 1121 | if (so.so_pcb == NULL) |
1102 | break; | | 1122 | break; |
1103 | if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, | | 1123 | if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, |
1104 | sizeof(inpcb)) != sizeof(inpcb)) { | | 1124 | sizeof(inpcb)) != sizeof(inpcb)) { |
1105 | dprintf("can't read inpcb at %p", so.so_pcb); | | 1125 | dprintf("can't read inpcb at %p", so.so_pcb); |
1106 | goto bad; | | 1126 | goto bad; |
1107 | } | | 1127 | } |
1108 | inet_addrstr(lbuf, sizeof(lbuf), &inpcb.inp_laddr, | | 1128 | inet_addrstr(lbuf, sizeof(lbuf), &inpcb.inp_laddr, |
1109 | ntohs(inpcb.inp_lport), isdgram); | | 1129 | ntohs(inpcb.inp_lport), isdgram); |
1110 | inet_addrstr(fbuf, sizeof(fbuf), &inpcb.inp_faddr, | | 1130 | inet_addrstr(fbuf, sizeof(fbuf), &inpcb.inp_faddr, |
1111 | ntohs(inpcb.inp_fport), isdgram); | | 1131 | ntohs(inpcb.inp_fport), isdgram); |
1112 | break; | | 1132 | break; |
1113 | default: | | 1133 | default: |
1114 | break; | | 1134 | break; |
1115 | } | | 1135 | } |
1116 | break; | | 1136 | break; |
1117 | #ifdef INET6 | | 1137 | #ifdef INET6 |
1118 | case AF_INET6: | | 1138 | case AF_INET6: |
1119 | getinetproto(pbuf, sizeof(pbuf), proto.pr_protocol); | | 1139 | getinetproto(pbuf, sizeof(pbuf), proto.pr_protocol); |
1120 | switch (proto.pr_protocol) { | | 1140 | switch (proto.pr_protocol) { |
1121 | case IPPROTO_UDP: | | 1141 | case IPPROTO_UDP: |
1122 | isdgram = true; | | 1142 | isdgram = true; |
1123 | /* FALLTHROUGH */ | | 1143 | /* FALLTHROUGH */ |
1124 | case IPPROTO_TCP: | | 1144 | case IPPROTO_TCP: |
1125 | if (so.so_pcb == NULL) | | 1145 | if (so.so_pcb == NULL) |
1126 | break; | | 1146 | break; |
1127 | if (kvm_read(kd, (u_long)so.so_pcb, (char *)&in6pcb, | | 1147 | if (kvm_read(kd, (u_long)so.so_pcb, (char *)&in6pcb, |
1128 | sizeof(in6pcb)) != sizeof(in6pcb)) { | | 1148 | sizeof(in6pcb)) != sizeof(in6pcb)) { |
1129 | dprintf("can't read in6pcb at %p", so.so_pcb); | | 1149 | dprintf("can't read in6pcb at %p", so.so_pcb); |
1130 | goto bad; | | 1150 | goto bad; |
1131 | } | | 1151 | } |
1132 | inet6_addrstr(lbuf, sizeof(lbuf), &in6pcb.in6p_laddr, | | 1152 | inet6_addrstr(lbuf, sizeof(lbuf), &in6pcb.in6p_laddr, |
1133 | ntohs(in6pcb.in6p_lport), isdgram); | | 1153 | ntohs(in6pcb.in6p_lport), isdgram); |
1134 | inet6_addrstr(fbuf, sizeof(fbuf), &in6pcb.in6p_faddr, | | 1154 | inet6_addrstr(fbuf, sizeof(fbuf), &in6pcb.in6p_faddr, |
1135 | ntohs(in6pcb.in6p_fport), isdgram); | | 1155 | ntohs(in6pcb.in6p_fport), isdgram); |
1136 | break; | | 1156 | break; |
1137 | default: | | 1157 | default: |
1138 | break; | | 1158 | break; |
1139 | } | | 1159 | } |
1140 | break; | | 1160 | break; |
1141 | #endif | | 1161 | #endif |
1142 | case AF_LOCAL: | | 1162 | case AF_LOCAL: |
1143 | /* print address of pcb and connected pcb */ | | 1163 | /* print address of pcb and connected pcb */ |
1144 | if (so.so_pcb) { | | 1164 | if (so.so_pcb) { |
1145 | char shoconn[4], *cp; | | 1165 | char shoconn[4], *cp; |
1146 | void *pcb[2]; | | 1166 | void *pcb[2]; |
1147 | size_t p = 0; | | 1167 | size_t p = 0; |
1148 | | | 1168 | |
1149 | pcb[0] = so.so_pcb; | | 1169 | pcb[0] = so.so_pcb; |
1150 | | | 1170 | |
1151 | cp = shoconn; | | 1171 | cp = shoconn; |
1152 | if (!(so.so_state & SS_CANTRCVMORE)) | | 1172 | if (!(so.so_state & SS_CANTRCVMORE)) |
1153 | *cp++ = '<'; | | 1173 | *cp++ = '<'; |
1154 | *cp++ = '-'; | | 1174 | *cp++ = '-'; |
1155 | if (!(so.so_state & SS_CANTSENDMORE)) | | 1175 | if (!(so.so_state & SS_CANTSENDMORE)) |
1156 | *cp++ = '>'; | | 1176 | *cp++ = '>'; |
1157 | *cp = '\0'; | | 1177 | *cp = '\0'; |
1158 | again: | | 1178 | again: |
1159 | if (kvm_read(kd, (u_long)pcb[p], (char *)&unpcb, | | 1179 | if (kvm_read(kd, (u_long)pcb[p], (char *)&unpcb, |
1160 | sizeof(struct unpcb)) != sizeof(struct unpcb)){ | | 1180 | sizeof(struct unpcb)) != sizeof(struct unpcb)){ |
1161 | dprintf("can't read unpcb at %p", so.so_pcb); | | 1181 | dprintf("can't read unpcb at %p", so.so_pcb); |
1162 | goto bad; | | 1182 | goto bad; |
1163 | } | | 1183 | } |
1164 | if (checkfile) { | | 1184 | if (checkfile) { |
1165 | struct vnode vn; | | 1185 | struct vnode vn; |
1166 | struct filestat fst; | | 1186 | struct filestat fst; |
1167 | const char *badtype, *filename; | | 1187 | const char *badtype, *filename; |
1168 | if (unpcb.unp_vnode == NULL) | | 1188 | if (unpcb.unp_vnode == NULL) |
1169 | return; | | 1189 | return; |
1170 | if (!checkfs(unpcb.unp_vnode, &vn, &fst, | | 1190 | if (!checkfs(unpcb.unp_vnode, &vn, &fst, |
1171 | &badtype, &filename)) | | 1191 | &badtype, &filename)) |
1172 | return; | | 1192 | return; |
1173 | } | | 1193 | } |
1174 | | | 1194 | |
1175 | if (unpcb.unp_addr) { | | 1195 | if (unpcb.unp_addr) { |
1176 | struct sockaddr_un *sun = | | 1196 | struct sockaddr_un *sun = |
1177 | malloc(unpcb.unp_addrlen); | | 1197 | malloc(unpcb.unp_addrlen); |
1178 | if (sun == NULL) | | 1198 | if (sun == NULL) |
1179 | err(1, "malloc(%zu)", | | 1199 | err(1, "malloc(%zu)", |
1180 | unpcb.unp_addrlen); | | 1200 | unpcb.unp_addrlen); |
1181 | if (kvm_read(kd, (u_long)unpcb.unp_addr, | | 1201 | if (kvm_read(kd, (u_long)unpcb.unp_addr, |
1182 | sun, unpcb.unp_addrlen) != | | 1202 | sun, unpcb.unp_addrlen) != |
1183 | (ssize_t)unpcb.unp_addrlen) { | | 1203 | (ssize_t)unpcb.unp_addrlen) { |
1184 | dprintf("can't read sun at %p", | | 1204 | dprintf("can't read sun at %p", |
1185 | unpcb.unp_addr); | | 1205 | unpcb.unp_addr); |
1186 | free(sun); | | 1206 | free(sun); |
1187 | } else { | | 1207 | } else { |
1188 | snprintf(fbuf, sizeof(fbuf), " %s %s %s", | | 1208 | snprintf(fbuf, sizeof(fbuf), " %s %s %s", |
1189 | shoconn, sun->sun_path, | | 1209 | shoconn, sun->sun_path, |
1190 | p == 0 ? "[creat]" : "[using]"); | | 1210 | p == 0 ? "[creat]" : "[using]"); |
1191 | free(sun); | | 1211 | free(sun); |
1192 | break; | | 1212 | break; |
1193 | } | | 1213 | } |
1194 | } | | 1214 | } |
1195 | if (unpcb.unp_conn) { | | 1215 | if (unpcb.unp_conn) { |
1196 | if (p == 0) { | | 1216 | if (p == 0) { |
1197 | pcb[++p] = unpcb.unp_conn; | | 1217 | pcb[++p] = unpcb.unp_conn; |
1198 | goto again; | | 1218 | goto again; |
1199 | } else | | 1219 | } else |
1200 | snprintf(fbuf, sizeof(fbuf), | | 1220 | snprintf(fbuf, sizeof(fbuf), |
1201 | " %p %s %p", pcb[0], shoconn, | | 1221 | " %p %s %p", pcb[0], shoconn, |
1202 | pcb[1]); | | 1222 | pcb[1]); |
1203 | } | | 1223 | } |
1204 | } | | 1224 | } |
1205 | break; | | 1225 | break; |
1206 | case AF_APPLETALK: | | 1226 | case AF_APPLETALK: |
1207 | getatproto(pbuf, sizeof(pbuf), proto.pr_protocol); | | 1227 | getatproto(pbuf, sizeof(pbuf), proto.pr_protocol); |
1208 | if (so.so_pcb) { | | 1228 | if (so.so_pcb) { |
1209 | if (kvm_read(kd, (u_long)so.so_pcb, (char *)&ddpcb, | | 1229 | if (kvm_read(kd, (u_long)so.so_pcb, (char *)&ddpcb, |
1210 | sizeof(ddpcb)) != sizeof(ddpcb)){ | | 1230 | sizeof(ddpcb)) != sizeof(ddpcb)){ |
1211 | dprintf("can't read ddpcb at %p", so.so_pcb); | | 1231 | dprintf("can't read ddpcb at %p", so.so_pcb); |
1212 | goto bad; | | 1232 | goto bad; |
1213 | } | | 1233 | } |
1214 | at_addrstr(fbuf, sizeof(fbuf), &ddpcb.ddp_fsat); | | 1234 | at_addrstr(fbuf, sizeof(fbuf), &ddpcb.ddp_fsat); |
1215 | at_addrstr(lbuf, sizeof(lbuf), &ddpcb.ddp_lsat); | | 1235 | at_addrstr(lbuf, sizeof(lbuf), &ddpcb.ddp_lsat); |
1216 | } | | 1236 | } |
1217 | break; | | 1237 | break; |
1218 | default: | | 1238 | default: |
1219 | /* print protocol number and socket address */ | | 1239 | /* print protocol number and socket address */ |
1220 | snprintf(fbuf, sizeof(fbuf), " %d %jx", proto.pr_protocol, | | 1240 | snprintf(fbuf, sizeof(fbuf), " %d %jx", proto.pr_protocol, |
1221 | (uintmax_t)(uintptr_t)sock); | | 1241 | (uintmax_t)(uintptr_t)sock); |
1222 | break; | | 1242 | break; |
1223 | } | | 1243 | } |
1224 | PREFIX(i); | | 1244 | PREFIX(i); |
1225 | if ((u_short)so.so_type > STYPEMAX) | | 1245 | if ((u_short)so.so_type > STYPEMAX) |
1226 | (void)printf("* %s ?%d", dname, so.so_type); | | 1246 | (void)printf("* %s ?%d", dname, so.so_type); |
1227 | else | | 1247 | else |
1228 | (void)printf("* %s %s", dname, stypename[so.so_type]); | | 1248 | (void)printf("* %s %s", dname, stypename[so.so_type]); |
1229 | | | 1249 | |
1230 | if (pbuf[0]) | | 1250 | if (pbuf[0]) |
1231 | printf("%s", pbuf); | | 1251 | printf("%s", pbuf); |
1232 | if (fbuf[0] || lbuf[0]) | | 1252 | if (fbuf[0] || lbuf[0]) |
1233 | printf(" %s%s%s", fbuf, (fbuf[0] && lbuf[0]) ? " <-> " : "", | | 1253 | printf(" %s%s%s", fbuf, (fbuf[0] && lbuf[0]) ? " <-> " : "", |
1234 | lbuf); | | 1254 | lbuf); |
1235 | else if (so.so_pcb) | | 1255 | else if (so.so_pcb) |
1236 | printf(" %jx", (uintmax_t)(uintptr_t)so.so_pcb); | | 1256 | printf(" %jx", (uintmax_t)(uintptr_t)so.so_pcb); |
1237 | oprint(f, "\n"); | | 1257 | oprint(f, "\n"); |
1238 | return; | | 1258 | return; |
1239 | bad: | | 1259 | bad: |
1240 | (void)printf("* error\n"); | | 1260 | (void)printf("* error\n"); |
1241 | } | | 1261 | } |
1242 | | | 1262 | |
1243 | static void | | 1263 | static void |
1244 | ptrans(struct file *fp, struct pipe *cpipe, int i) | | 1264 | ptrans(struct file *fp, struct pipe *cpipe, int i) |
1245 | { | | 1265 | { |
1246 | struct pipe cp; | | 1266 | struct pipe cp; |
1247 | | | 1267 | |
1248 | PREFIX(i); | | 1268 | PREFIX(i); |
1249 | | | 1269 | |
1250 | /* fill in pipe */ | | 1270 | /* fill in pipe */ |
1251 | if (!KVM_READ(cpipe, &cp, sizeof(struct pipe))) { | | 1271 | if (!KVM_READ(cpipe, &cp, sizeof(struct pipe))) { |
1252 | dprintf("can't read pipe at %p", cpipe); | | 1272 | dprintf("can't read pipe at %p", cpipe); |
1253 | goto bad; | | 1273 | goto bad; |
1254 | } | | 1274 | } |
1255 | | | 1275 | |
1256 | /* pipe descriptor is either read or write, never both */ | | 1276 | /* pipe descriptor is either read or write, never both */ |
1257 | (void)printf("* pipe %p %s %p %s%s%s", cpipe, | | 1277 | (void)printf("* pipe %p %s %p %s%s%s", cpipe, |
1258 | (fp->f_flag & FWRITE) ? "->" : "<-", | | 1278 | (fp->f_flag & FWRITE) ? "->" : "<-", |
1259 | cp.pipe_peer, | | 1279 | cp.pipe_peer, |
1260 | (fp->f_flag & FWRITE) ? "w" : "r", | | 1280 | (fp->f_flag & FWRITE) ? "w" : "r", |
1261 | (fp->f_flag & FNONBLOCK) ? "n" : "", | | 1281 | (fp->f_flag & FNONBLOCK) ? "n" : "", |
1262 | (cp.pipe_state & PIPE_ASYNC) ? "a" : ""); | | 1282 | (cp.pipe_state & PIPE_ASYNC) ? "a" : ""); |
1263 | oprint(fp, "\n"); | | 1283 | oprint(fp, "\n"); |
1264 | return; | | 1284 | return; |
1265 | bad: | | 1285 | bad: |
1266 | (void)printf("* error\n"); | | 1286 | (void)printf("* error\n"); |
1267 | } | | 1287 | } |
1268 | | | 1288 | |
1269 | static void | | 1289 | static void |
1270 | misctrans(struct file *file, int i) | | 1290 | misctrans(struct file *file, int i) |
1271 | { | | 1291 | { |
1272 | | | 1292 | |
1273 | PREFIX(i); | | 1293 | PREFIX(i); |
1274 | pmisc(file, dtypes[file->f_type]); | | 1294 | pmisc(file, dtypes[file->f_type]); |
1275 | } | | 1295 | } |
1276 | | | 1296 | |
1277 | /* | | 1297 | /* |
1278 | * getinetproto -- | | 1298 | * getinetproto -- |
1279 | * print name of protocol number | | 1299 | * print name of protocol number |
1280 | */ | | 1300 | */ |
1281 | static void | | 1301 | static void |
1282 | getinetproto(char *buf, size_t len, int number) | | 1302 | getinetproto(char *buf, size_t len, int number) |
1283 | { | | 1303 | { |
1284 | const char *cp; | | 1304 | const char *cp; |
1285 | | | 1305 | |
1286 | switch (number) { | | 1306 | switch (number) { |
1287 | case IPPROTO_IP: | | 1307 | case IPPROTO_IP: |
1288 | cp = "ip"; break; | | 1308 | cp = "ip"; break; |
1289 | case IPPROTO_ICMP: | | 1309 | case IPPROTO_ICMP: |
1290 | cp ="icmp"; break; | | 1310 | cp ="icmp"; break; |
1291 | case IPPROTO_GGP: | | 1311 | case IPPROTO_GGP: |
1292 | cp ="ggp"; break; | | 1312 | cp ="ggp"; break; |
1293 | case IPPROTO_TCP: | | 1313 | case IPPROTO_TCP: |
1294 | cp ="tcp"; break; | | 1314 | cp ="tcp"; break; |
1295 | case IPPROTO_EGP: | | 1315 | case IPPROTO_EGP: |
1296 | cp ="egp"; break; | | 1316 | cp ="egp"; break; |
1297 | case IPPROTO_PUP: | | 1317 | case IPPROTO_PUP: |
1298 | cp ="pup"; break; | | 1318 | cp ="pup"; break; |
1299 | case IPPROTO_UDP: | | 1319 | case IPPROTO_UDP: |
1300 | cp ="udp"; break; | | 1320 | cp ="udp"; break; |
1301 | case IPPROTO_IDP: | | 1321 | case IPPROTO_IDP: |
1302 | cp ="idp"; break; | | 1322 | cp ="idp"; break; |
1303 | case IPPROTO_RAW: | | 1323 | case IPPROTO_RAW: |
1304 | cp ="raw"; break; | | 1324 | cp ="raw"; break; |
1305 | case IPPROTO_ICMPV6: | | 1325 | case IPPROTO_ICMPV6: |
1306 | cp ="icmp6"; break; | | 1326 | cp ="icmp6"; break; |
1307 | default: | | 1327 | default: |
1308 | (void)snprintf(buf, len, " %d", number); | | 1328 | (void)snprintf(buf, len, " %d", number); |
1309 | return; | | 1329 | return; |
1310 | } | | 1330 | } |