xref: /openbsd/lib/libkvm/kvm_file2.c (revision cecf84d4)
1 /*	$OpenBSD: kvm_file2.c,v 1.45 2015/03/28 23:50:55 bluhm Exp $	*/
2 
3 /*
4  * Copyright (c) 2009 Todd C. Miller <Todd.Miller@courtesan.com>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*-
20  * Copyright (c) 1989, 1992, 1993
21  *	The Regents of the University of California.  All rights reserved.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the above copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. Neither the name of the University nor the names of its contributors
32  *    may be used to endorse or promote products derived from this software
33  *    without specific prior written permission.
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
36  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
39  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45  * SUCH DAMAGE.
46  */
47 
48 /*
49  * Extended file list interface for kvm.  pstat, fstat and netstat are
50  * users of this code, so we've factored it out into a separate module.
51  * Thus, we keep this grunge out of the other kvm applications (i.e.,
52  * most other applications are interested only in open/close/read/nlist).
53  */
54 
55 #define __need_process
56 
57 #include <sys/param.h>
58 #include <sys/uio.h>
59 #include <sys/ucred.h>
60 #include <sys/proc.h>
61 #define _KERNEL
62 #include <sys/file.h>
63 #include <sys/mount.h>
64 #include <dev/systrace.h>
65 #undef _KERNEL
66 #include <sys/vnode.h>
67 #include <sys/socket.h>
68 #include <sys/socketvar.h>
69 #include <sys/domain.h>
70 #include <sys/protosw.h>
71 #include <sys/event.h>
72 #include <sys/eventvar.h>
73 #include <sys/un.h>
74 #include <sys/unpcb.h>
75 #include <sys/filedesc.h>
76 #include <sys/mbuf.h>
77 #include <sys/pipe.h>
78 #include <sys/stat.h>
79 #include <sys/sysctl.h>
80 #include <sys/specdev.h>
81 
82 #define _KERNEL
83 #include <ufs/ufs/quota.h>
84 #include <ufs/ufs/inode.h>
85 #undef _KERNEL
86 
87 #include <nfs/nfsproto.h>
88 #include <nfs/rpcv2.h>
89 #include <nfs/nfs.h>
90 #include <nfs/nfsnode.h>
91 
92 #include <msdosfs/bpb.h>
93 #include <msdosfs/denode.h>
94 #include <msdosfs/msdosfsmount.h>
95 
96 #include <net/route.h>
97 #include <netinet/in.h>
98 #include <netinet/ip.h>
99 #include <netinet/in_pcb.h>
100 #include <netinet/tcp.h>
101 #include <netinet/tcp_timer.h>
102 #include <netinet/tcp_var.h>
103 
104 #ifdef INET6
105 #include <netinet/ip6.h>
106 #include <netinet6/ip6_var.h>
107 #endif
108 
109 #include <nlist.h>
110 #include <kvm.h>
111 #include <db.h>
112 #include <stddef.h>
113 #include <stdlib.h>
114 #include <string.h>
115 #include <unistd.h>
116 #include <limits.h>
117 
118 #include "kvm_private.h"
119 #include "kvm_file.h"
120 
121 static struct kinfo_file *kvm_deadfile_byfile(kvm_t *, int, int,
122     size_t, int *);
123 static struct kinfo_file *kvm_deadfile_byid(kvm_t *, int, int,
124     size_t, int *);
125 static int fill_file(kvm_t *, struct kinfo_file *, struct file *, u_long,
126     struct vnode *, struct process *, int, pid_t);
127 static int filestat(kvm_t *, struct kinfo_file *, struct vnode *);
128 
129 LIST_HEAD(processlist, process);
130 
131 struct kinfo_file *
132 kvm_getfiles(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
133 {
134 	int mib[6], rv;
135 	size_t size;
136 
137 	if (kd->filebase != NULL) {
138 		free(kd->filebase);
139 		/*
140 		 * Clear this pointer in case this call fails.  Otherwise,
141 		 * kvm_close() will free it again.
142 		 */
143 		kd->filebase = 0;
144 	}
145 
146 	if (ISALIVE(kd)) {
147 		mib[0] = CTL_KERN;
148 		mib[1] = KERN_FILE;
149 		mib[2] = op;
150 		mib[3] = arg;
151 		mib[4] = esize;
152 		mib[5] = 0;
153 
154 		/* find size and alloc buffer */
155 		rv = sysctl(mib, 6, NULL, &size, NULL, 0);
156 		if (rv == -1) {
157 			if (kd->vmfd != -1)
158 				goto deadway;
159 			_kvm_syserr(kd, kd->program, "kvm_getfiles");
160 			return (NULL);
161 		}
162 		kd->filebase = _kvm_malloc(kd, size);
163 		if (kd->filebase == NULL)
164 			return (NULL);
165 
166 		/* get actual data */
167 		mib[5] = size / esize;
168 		rv = sysctl(mib, 6, kd->filebase, &size, NULL, 0);
169 		if (rv == -1) {
170 			_kvm_syserr(kd, kd->program, "kvm_getfiles");
171 			return (NULL);
172 		}
173 		*cnt = size / esize;
174 		return (kd->filebase);
175 	} else {
176 		if (esize > sizeof(struct kinfo_file)) {
177 			_kvm_syserr(kd, kd->program,
178 			    "kvm_getfiles: unknown fields requested: libkvm out of date?");
179 			return (NULL);
180 		}
181 	    deadway:
182 		switch (op) {
183 		case KERN_FILE_BYFILE:
184 			return (kvm_deadfile_byfile(kd, op, arg, esize, cnt));
185 			break;
186 		case KERN_FILE_BYPID:
187 		case KERN_FILE_BYUID:
188 			return (kvm_deadfile_byid(kd, op, arg, esize, cnt));
189 			break;
190 		default:
191 			return (NULL);
192 		}
193 	}
194 }
195 
196 static struct kinfo_file *
197 kvm_deadfile_byfile(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
198 {
199 	struct nlist nl[3], *p;
200 	size_t buflen;
201 	int n = 0;
202 	char *where;
203 	struct kinfo_file kf;
204 	struct file *fp, file;
205 	struct filelist filehead;
206 	int nfiles;
207 
208 	nl[0].n_name = "_filehead";
209 	nl[1].n_name = "_nfiles";
210 	nl[2].n_name = 0;
211 
212 	if (kvm_nlist(kd, nl) != 0) {
213 		for (p = nl; p->n_type != 0; ++p)
214 			;
215 		_kvm_err(kd, kd->program,
216 			 "%s: no such symbol", p->n_name);
217 		return (NULL);
218 	}
219 	if (KREAD(kd, nl[0].n_value, &filehead)) {
220 		_kvm_err(kd, kd->program, "can't read filehead");
221 		return (NULL);
222 	}
223 	if (KREAD(kd, nl[1].n_value, &nfiles)) {
224 		_kvm_err(kd, kd->program, "can't read nfiles");
225 		return (NULL);
226 	}
227 	where = _kvm_reallocarray(kd, NULL, nfiles, esize);
228 	kd->filebase = (void *)where;
229 	if (kd->filebase == NULL)
230 		return (NULL);
231 	buflen = nfiles * esize;
232 
233 	for (fp = LIST_FIRST(&filehead);
234 	    fp != NULL && esize <= buflen;
235 	    fp = LIST_NEXT(&file, f_list)) {
236 		if (KREAD(kd, (u_long)fp, &file)) {
237 			_kvm_err(kd, kd->program, "can't read kfp");
238 			return (NULL);
239 		}
240 		if (file.f_count == 0)
241 			continue;
242 		if (arg != 0 && file.f_type != arg)
243 			continue;
244 		if (fill_file(kd, &kf, &file, (u_long)fp, NULL, NULL, 0, 0)
245 		    == -1)
246 			return (NULL);
247 		memcpy(where, &kf, esize);
248 		where += esize;
249 		buflen -= esize;
250 		n++;
251 	}
252 	if (n != nfiles) {
253 		_kvm_err(kd, kd->program, "inconsistent nfiles");
254 		return (NULL);
255 	}
256 	*cnt = n;
257 	return (kd->filebase);
258 }
259 
260 static struct kinfo_file *
261 kvm_deadfile_byid(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
262 {
263 	size_t buflen;
264 	struct nlist nl[4], *np;
265 	int n = 0;
266 	char *where;
267 	struct kinfo_file kf;
268 	struct file *fp, file;
269 	struct filelist filehead;
270 	struct filedesc0 filed0;
271 #define filed	filed0.fd_fd
272 	struct processlist allprocess;
273 	struct proc proc;
274 	struct process *pr, process;
275 	struct ucred ucred;
276 	char *filebuf = NULL;
277 	int i, nfiles;
278 
279 	nl[0].n_name = "_filehead";
280 	nl[1].n_name = "_nfiles";
281 	nl[2].n_name = "_allprocess";
282 	nl[3].n_name = 0;
283 
284 	if (kvm_nlist(kd, nl) != 0) {
285 		for (np = nl; np->n_type != 0; ++np)
286 			;
287 		_kvm_err(kd, kd->program,
288 			 "%s: no such symbol", np->n_name);
289 		return (NULL);
290 	}
291 	if (KREAD(kd, nl[0].n_value, &filehead)) {
292 		_kvm_err(kd, kd->program, "can't read filehead");
293 		return (NULL);
294 	}
295 	if (KREAD(kd, nl[1].n_value, &nfiles)) {
296 		_kvm_err(kd, kd->program, "can't read nfiles");
297 		return (NULL);
298 	}
299 	if (KREAD(kd, nl[2].n_value, &allprocess)) {
300 		_kvm_err(kd, kd->program, "can't read allprocess");
301 		return (NULL);
302 	}
303 	/* this may be more room than we need but counting is expensive */
304 	where = _kvm_reallocarray(kd, NULL, nfiles + 10, esize);
305 	kd->filebase = (void *)where;
306 	if (kd->filebase == NULL)
307 		return (NULL);
308 	buflen = (nfiles + 10) * esize;
309 
310 	for (pr = LIST_FIRST(&allprocess);
311 	    pr != NULL;
312 	    pr = LIST_NEXT(&process, ps_list)) {
313 		if (KREAD(kd, (u_long)pr, &process)) {
314 			_kvm_err(kd, kd->program, "can't read process at %lx",
315 			    (u_long)pr);
316 			goto cleanup;
317 		}
318 
319 		/* skip system, exiting, embryonic and undead processes */
320 		if (process.ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING))
321 			continue;
322 
323 		if (process.ps_mainproc == NULL)
324 			continue;
325 		if (KREAD(kd, (u_long)process.ps_mainproc, &proc)) {
326 			_kvm_err(kd, kd->program, "can't read proc at %lx",
327 			    (u_long)process.ps_mainproc);
328 			goto cleanup;
329 		}
330 
331 		if (op == KERN_FILE_BYPID && arg > 0 &&
332 		    proc.p_pid != (pid_t)arg) {
333 				/* not the pid we are looking for */
334 				continue;
335 		}
336 
337 		if (KREAD(kd, (u_long)process.ps_ucred, &ucred)) {
338 			_kvm_err(kd, kd->program, "can't read ucred at %lx",
339 			    (u_long)process.ps_ucred);
340 			goto cleanup;
341 		}
342 		process.ps_mainproc = &proc;
343 		proc.p_p = &process;
344 		process.ps_ucred = &ucred;
345 
346 		if (op == KERN_FILE_BYUID && arg >= 0 &&
347 		    process.ps_ucred->cr_uid != (uid_t)arg) {
348 			/* not the uid we are looking for */
349 			continue;
350 		}
351 
352 		if (KREAD(kd, (u_long)process.ps_fd, &filed0)) {
353 			_kvm_err(kd, kd->program, "can't read filedesc at %lx",
354 			    (u_long)process.ps_fd);
355 			goto cleanup;
356 		}
357 		if ((char *)process.ps_fd + offsetof(struct filedesc0,fd_dfiles)
358 		    == (char *)filed.fd_ofiles) {
359 			filed.fd_ofiles = filed0.fd_dfiles;
360 			filed.fd_ofileflags = filed0.fd_dfileflags;
361 		} else {
362 			size_t fsize;
363 			char *tmp = reallocarray(filebuf,
364 			    filed.fd_nfiles, OFILESIZE);
365 
366 			fsize = filed.fd_nfiles * OFILESIZE;
367 			if (tmp == NULL) {
368 				_kvm_syserr(kd, kd->program, "realloc ofiles");
369 				goto cleanup;
370 			}
371 			filebuf = tmp;
372 			if (kvm_read(kd, (u_long)filed.fd_ofiles, filebuf,
373 			    fsize) != fsize) {
374 				_kvm_err(kd, kd->program,
375 				    "can't read fd_ofiles");
376 				goto cleanup;
377 			}
378 			filed.fd_ofiles = (void *)filebuf;
379 			filed.fd_ofileflags = filebuf +
380 			    (filed.fd_nfiles * sizeof(struct file *));
381 		}
382 		process.ps_fd = &filed;
383 
384 		if (process.ps_textvp) {
385 			if (buflen < esize)
386 				goto done;
387 			if (fill_file(kd, &kf, NULL, 0, process.ps_textvp,
388 			    &process, KERN_FILE_TEXT, proc.p_pid) == -1)
389 				goto cleanup;
390 			memcpy(where, &kf, esize);
391 			where += esize;
392 			buflen -= esize;
393 			n++;
394 		}
395 		if (filed.fd_cdir) {
396 			if (buflen < esize)
397 				goto done;
398 			if (fill_file(kd, &kf, NULL, 0, filed.fd_cdir,
399 			    &process, KERN_FILE_CDIR, proc.p_pid) == -1)
400 				goto cleanup;
401 			memcpy(where, &kf, esize);
402 			where += esize;
403 			buflen -= esize;
404 			n++;
405 		}
406 		if (filed.fd_rdir) {
407 			if (buflen < esize)
408 				goto done;
409 			if (fill_file(kd, &kf, NULL, 0, filed.fd_rdir,
410 			    &process, KERN_FILE_RDIR, proc.p_pid) == -1)
411 				goto cleanup;
412 			memcpy(where, &kf, esize);
413 			where += esize;
414 			buflen -= esize;
415 			n++;
416 		}
417 		if (process.ps_tracevp) {
418 			if (buflen < esize)
419 				goto done;
420 			if (fill_file(kd, &kf, NULL, 0, process.ps_tracevp,
421 			    &process, KERN_FILE_TRACE, proc.p_pid) == -1)
422 				goto cleanup;
423 			memcpy(where, &kf, esize);
424 			where += esize;
425 			buflen -= esize;
426 			n++;
427 		}
428 
429 		if (filed.fd_nfiles < 0 ||
430 		    filed.fd_lastfile >= filed.fd_nfiles ||
431 		    filed.fd_freefile > filed.fd_lastfile + 1) {
432 			_kvm_err(kd, kd->program,
433 			    "filedesc corrupted at %lx for pid %d",
434 			    (u_long)process.ps_fd, proc.p_pid);
435 			goto cleanup;
436 		}
437 
438 		for (i = 0; i < filed.fd_nfiles; i++) {
439 			if (buflen < esize)
440 				goto done;
441 			if ((fp = filed.fd_ofiles[i]) == NULL)
442 				continue;
443 			if (KREAD(kd, (u_long)fp, &file)) {
444 				_kvm_err(kd, kd->program, "can't read file");
445 				goto cleanup;
446 			}
447 			if (fill_file(kd, &kf, &file, (u_long)fp, NULL,
448 			    &process, i, proc.p_pid) == -1)
449 				goto cleanup;
450 			memcpy(where, &kf, esize);
451 			where += esize;
452 			buflen -= esize;
453 			n++;
454 		}
455 	}
456 done:
457 	*cnt = n;
458 	free(filebuf);
459 	return (kd->filebase);
460 cleanup:
461 	free(filebuf);
462 	return (NULL);
463 }
464 
465 static int
466 fill_file(kvm_t *kd, struct kinfo_file *kf, struct file *fp, u_long fpaddr,
467     struct vnode *vp, struct process *pr, int fd, pid_t pid)
468 {
469 	struct ucred f_cred;
470 
471 	memset(kf, 0, sizeof(*kf));
472 
473 	kf->fd_fd = fd;		/* might not really be an fd */
474 
475 	if (fp != NULL) {
476 		/* Fill in f_cred */
477 		if (KREAD(kd, (u_long)fp->f_cred, &f_cred)) {
478 			_kvm_err(kd, kd->program, "can't read f_cred");
479 			return (-1);
480 		}
481 
482 		kf->f_fileaddr = PTRTOINT64(fpaddr);
483 		kf->f_flag = fp->f_flag;
484 		kf->f_iflags = fp->f_iflags;
485 		kf->f_type = fp->f_type;
486 		kf->f_count = fp->f_count;
487 		kf->f_msgcount = fp->f_msgcount;
488 		kf->f_ucred = PTRTOINT64(fp->f_cred);
489 		kf->f_uid = f_cred.cr_uid;
490 		kf->f_gid = f_cred.cr_gid;
491 		kf->f_ops = PTRTOINT64(fp->f_ops);
492 		kf->f_offset = fp->f_offset;
493 		kf->f_data = PTRTOINT64(fp->f_data);
494 		kf->f_usecount = 0;
495 
496 		kf->f_rxfer = fp->f_rxfer;
497 		kf->f_rwfer = fp->f_wxfer;
498 		kf->f_seek = fp->f_seek;
499 		kf->f_rbytes = fp->f_rbytes;
500 		kf->f_wbytes = fp->f_wbytes;
501 	} else if (vp != NULL) {
502 		/* fake it */
503 		kf->f_type = DTYPE_VNODE;
504 		kf->f_flag = FREAD;
505 		if (fd == KERN_FILE_TRACE)
506 			kf->f_flag |= FWRITE;
507 		kf->f_data = PTRTOINT64(vp);
508 	}
509 
510 	/* information about the object associated with this file */
511 	switch (kf->f_type) {
512 	case DTYPE_VNODE: {
513 		struct vnode vbuf;
514 
515 		if (KREAD(kd, (u_long)(fp ? fp->f_data : vp), &vbuf)) {
516 			_kvm_err(kd, kd->program, "can't read vnode");
517 			return (-1);
518 		}
519 		vp = &vbuf;
520 
521 		kf->v_un = PTRTOINT64(vp->v_un.vu_socket);
522 		kf->v_type = vp->v_type;
523 		kf->v_tag = vp->v_tag;
524 		kf->v_flag = vp->v_flag;
525 		kf->v_data = PTRTOINT64(vp->v_data);
526 		kf->v_mount = PTRTOINT64(vp->v_mount);
527 
528 		if (vp->v_mount != NULL) {
529 			struct mount mount;
530 
531 			if (KREAD(kd, (u_long)vp->v_mount, &mount)) {
532 				_kvm_err(kd, kd->program, "can't read v_mount");
533 				return (-1);
534 			}
535 
536 			strlcpy(kf->f_mntonname, mount.mnt_stat.f_mntonname,
537 			    sizeof(kf->f_mntonname));
538 		}
539 
540 		/* Fill in va_fsid, va_fileid, va_mode, va_size, va_rdev */
541 		filestat(kd, kf, vp);
542 		break;
543 	    }
544 
545 	case DTYPE_SOCKET: {
546 		struct socket sock;
547 		struct sosplice ssp;
548 		struct protosw protosw;
549 		struct domain domain;
550 
551 		if (KREAD(kd, (u_long)fp->f_data, &sock)) {
552 			_kvm_err(kd, kd->program, "can't read socket");
553 			return (-1);
554 		}
555 
556 		kf->so_type = sock.so_type;
557 		kf->so_state = sock.so_state;
558 		kf->so_pcb = PTRTOINT64(sock.so_pcb);
559 		if (KREAD(kd, (u_long)sock.so_proto, &protosw)) {
560 			_kvm_err(kd, kd->program, "can't read protosw");
561 			return (-1);
562 		}
563 		kf->so_protocol = protosw.pr_protocol;
564 		if (KREAD(kd, (u_long)protosw.pr_domain, &domain)) {
565 			_kvm_err(kd, kd->program, "can't read domain");
566 			return (-1);
567 		}
568 		kf->so_family = domain.dom_family;
569 		kf->so_rcv_cc = sock.so_rcv.sb_cc;
570 		kf->so_snd_cc = sock.so_snd.sb_cc;
571 		if (sock.so_sp) {
572 			if (KREAD(kd, (u_long)sock.so_sp, &ssp)) {
573 				_kvm_err(kd, kd->program, "can't read splice");
574 				return (-1);
575 			}
576 			if (ssp.ssp_socket) {
577 				kf->so_splice = PTRTOINT64(ssp.ssp_socket);
578 				kf->so_splicelen = ssp.ssp_len;
579 			} else if (ssp.ssp_soback) {
580 				kf->so_splicelen = -1;
581 			}
582 		}
583 		if (!sock.so_pcb)
584 			break;
585 		switch (kf->so_family) {
586 		case AF_INET: {
587 			struct inpcb inpcb;
588 
589 			if (KREAD(kd, (u_long)sock.so_pcb, &inpcb)) {
590 				_kvm_err(kd, kd->program, "can't read inpcb");
591 				return (-1);
592 			}
593 			kf->inp_ppcb = PTRTOINT64(inpcb.inp_ppcb);
594 			kf->inp_lport = inpcb.inp_lport;
595 			kf->inp_laddru[0] = inpcb.inp_laddr.s_addr;
596 			kf->inp_fport = inpcb.inp_fport;
597 			kf->inp_faddru[0] = inpcb.inp_faddr.s_addr;
598 			kf->inp_rtableid = inpcb.inp_rtableid;
599 			if (sock.so_type == SOCK_RAW)
600 				kf->inp_proto = inpcb.inp_ip.ip_p;
601 			if (protosw.pr_protocol == IPPROTO_TCP) {
602 				struct tcpcb tcpcb;
603 				if (KREAD(kd, (u_long)inpcb.inp_ppcb, &tcpcb)) {
604 					_kvm_err(kd, kd->program,
605 					    "can't read tcpcb");
606 					return (-1);
607 				}
608 				kf->t_rcv_wnd = tcpcb.rcv_wnd;
609 				kf->t_snd_wnd = tcpcb.snd_wnd;
610 				kf->t_snd_cwnd = tcpcb.snd_cwnd;
611 				kf->t_state = tcpcb.t_state;
612 			}
613 			break;
614 		    }
615 		case AF_INET6: {
616 			struct inpcb inpcb;
617 #define s6_addr32 __u6_addr.__u6_addr32
618 
619 			if (KREAD(kd, (u_long)sock.so_pcb, &inpcb)) {
620 				_kvm_err(kd, kd->program, "can't read inpcb");
621 				return (-1);
622 			}
623 			kf->inp_ppcb = PTRTOINT64(inpcb.inp_ppcb);
624 			kf->inp_lport = inpcb.inp_lport;
625 			kf->inp_laddru[0] = inpcb.inp_laddr6.s6_addr32[0];
626 			kf->inp_laddru[1] = inpcb.inp_laddr6.s6_addr32[1];
627 			kf->inp_laddru[2] = inpcb.inp_laddr6.s6_addr32[2];
628 			kf->inp_laddru[3] = inpcb.inp_laddr6.s6_addr32[3];
629 			kf->inp_fport = inpcb.inp_fport;
630 			kf->inp_faddru[0] = inpcb.inp_laddr6.s6_addr32[0];
631 			kf->inp_faddru[1] = inpcb.inp_faddr6.s6_addr32[1];
632 			kf->inp_faddru[2] = inpcb.inp_faddr6.s6_addr32[2];
633 			kf->inp_faddru[3] = inpcb.inp_faddr6.s6_addr32[3];
634 			kf->inp_rtableid = inpcb.inp_rtableid;
635 			if (sock.so_type == SOCK_RAW)
636 				kf->inp_proto = inpcb.inp_ipv6.ip6_nxt;
637 			if (protosw.pr_protocol == IPPROTO_TCP) {
638 				struct tcpcb tcpcb;
639 				if (KREAD(kd, (u_long)inpcb.inp_ppcb, &tcpcb)) {
640 					_kvm_err(kd, kd->program,
641 					    "can't read tcpcb");
642 					return (-1);
643 				}
644 				kf->t_rcv_wnd = tcpcb.rcv_wnd;
645 				kf->t_snd_wnd = tcpcb.snd_wnd;
646 				kf->t_snd_cwnd = tcpcb.snd_cwnd;
647 				kf->t_state = tcpcb.t_state;
648 			}
649 			break;
650 		    }
651 		case AF_UNIX: {
652 			struct unpcb unpcb;
653 
654 			if (KREAD(kd, (u_long)sock.so_pcb, &unpcb)) {
655 				_kvm_err(kd, kd->program, "can't read unpcb");
656 				return (-1);
657 			}
658 			kf->unp_conn	= PTRTOINT64(unpcb.unp_conn);
659 			kf->unp_refs	= PTRTOINT64(
660 			    SLIST_FIRST(&unpcb.unp_refs));
661 			kf->unp_nextref	= PTRTOINT64(
662 			    SLIST_NEXT(&unpcb, unp_nextref));
663 			kf->v_un	= PTRTOINT64(unpcb.unp_vnode);
664 			if (unpcb.unp_addr != NULL) {
665 				struct mbuf mb;
666 				struct sockaddr_un un;
667 
668 				if (KREAD(kd, (u_long)unpcb.unp_addr, &mb)) {
669 					_kvm_err(kd, kd->program,
670 					    "can't read sockaddr_un mbuf");
671 					return (-1);
672 				}
673 				if (KREAD(kd, (u_long)mb.m_data, &un)) {
674 					_kvm_err(kd, kd->program,
675 					    "can't read sockaddr_un");
676 					return (-1);
677 				}
678 
679 				kf->unp_addr = PTRTOINT64(unpcb.unp_addr);
680 				memcpy(kf->unp_path, un.sun_path, un.sun_len
681 				    - offsetof(struct sockaddr_un,sun_path));
682 			}
683 
684 			break;
685 		    }
686 		}
687 		break;
688 	    }
689 
690 	case DTYPE_PIPE: {
691 		struct pipe pipe;
692 
693 		if (KREAD(kd, (u_long)fp->f_data, &pipe)) {
694 			_kvm_err(kd, kd->program, "can't read pipe");
695 			return (-1);
696 		}
697 		kf->pipe_peer = PTRTOINT64(pipe.pipe_peer);
698 		kf->pipe_state = pipe.pipe_state;
699 		break;
700 	    }
701 
702 	case DTYPE_KQUEUE: {
703 		struct kqueue kqi;
704 
705 		if (KREAD(kd, (u_long)fp->f_data, &kqi)) {
706 			_kvm_err(kd, kd->program, "can't read kqi");
707 			return (-1);
708 		}
709 		kf->kq_count = kqi.kq_count;
710 		kf->kq_state = kqi.kq_state;
711 		break;
712 	    }
713 	case DTYPE_SYSTRACE: {
714 		struct fsystrace f;
715 
716 		if (KREAD(kd, (u_long)fp->f_data, &f)) {
717 			_kvm_err(kd, kd->program, "can't read fsystrace");
718 			return (-1);
719 		}
720 		kf->str_npolicies = f.npolicies;
721 		break;
722 	    }
723 	}
724 
725 	/* per-process information for KERN_FILE_BY[PU]ID */
726 	if (pr != NULL) {
727 		kf->p_pid = pid;
728 		kf->p_uid = pr->ps_ucred->cr_uid;
729 		kf->p_gid = pr->ps_ucred->cr_gid;
730 		kf->p_tid = -1;
731 		strlcpy(kf->p_comm, pr->ps_mainproc->p_comm,
732 		    sizeof(kf->p_comm));
733 		if (pr->ps_fd != NULL)
734 			kf->fd_ofileflags = pr->ps_fd->fd_ofileflags[fd];
735 	}
736 
737 	return (0);
738 }
739 
740 mode_t
741 _kvm_getftype(enum vtype v_type)
742 {
743 	mode_t ftype = 0;
744 
745 	switch (v_type) {
746 	case VREG:
747 		ftype = S_IFREG;
748 		break;
749 	case VDIR:
750 		ftype = S_IFDIR;
751 		break;
752 	case VBLK:
753 		ftype = S_IFBLK;
754 		break;
755 	case VCHR:
756 		ftype = S_IFCHR;
757 		break;
758 	case VLNK:
759 		ftype = S_IFLNK;
760 		break;
761 	case VSOCK:
762 		ftype = S_IFSOCK;
763 		break;
764 	case VFIFO:
765 		ftype = S_IFIFO;
766 		break;
767 	case VNON:
768 	case VBAD:
769 		break;
770 	}
771 
772 	return (ftype);
773 }
774 
775 static int
776 ufs_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
777 {
778 	struct inode inode;
779 	struct ufs1_dinode di1;
780 
781 	if (KREAD(kd, (u_long)VTOI(vp), &inode)) {
782 		_kvm_err(kd, kd->program, "can't read inode at %p", VTOI(vp));
783 		return (-1);
784 	}
785 
786 	if (KREAD(kd, (u_long)inode.i_din1, &di1)) {
787 		_kvm_err(kd, kd->program, "can't read dinode at %p",
788 		    inode.i_din1);
789 		return (-1);
790 	}
791 
792 	inode.i_din1 = &di1;
793 
794 	kf->va_fsid = inode.i_dev & 0xffff;
795 	kf->va_fileid = (long)inode.i_number;
796 	kf->va_mode = inode.i_ffs1_mode;
797 	kf->va_size = inode.i_ffs1_size;
798 	kf->va_rdev = inode.i_ffs1_rdev;
799 
800 	return (0);
801 }
802 
803 static int
804 ext2fs_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
805 {
806 	struct inode inode;
807 	struct ext2fs_dinode e2di;
808 
809 	if (KREAD(kd, (u_long)VTOI(vp), &inode)) {
810 		_kvm_err(kd, kd->program, "can't read inode at %p", VTOI(vp));
811 		return (-1);
812 	}
813 
814 	if (KREAD(kd, (u_long)inode.i_e2din, &e2di)) {
815 		_kvm_err(kd, kd->program, "can't read dinode at %p",
816 		    inode.i_e2din);
817 		return (-1);
818 	}
819 
820 	inode.i_e2din = &e2di;
821 
822 	kf->va_fsid = inode.i_dev & 0xffff;
823 	kf->va_fileid = (long)inode.i_number;
824 	kf->va_mode = inode.i_e2fs_mode;
825 	kf->va_size = inode.i_e2fs_size;
826 	kf->va_rdev = 0;	/* XXX */
827 
828 	return (0);
829 }
830 
831 static int
832 msdos_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
833 {
834 	struct denode de;
835 	struct msdosfsmount mp;
836 
837 	if (KREAD(kd, (u_long)VTODE(vp), &de)) {
838 		_kvm_err(kd, kd->program, "can't read denode at %p", VTODE(vp));
839 		return (-1);
840 	}
841 	if (KREAD(kd, (u_long)de.de_pmp, &mp)) {
842 		_kvm_err(kd, kd->program, "can't read mount struct at %p",
843 		    de.de_pmp);
844 		return (-1);
845 	}
846 
847 	kf->va_fsid = de.de_dev & 0xffff;
848 	kf->va_fileid = 0; /* XXX see msdosfs_vptofh() for more info */
849 	kf->va_mode = (mp.pm_mask & 0777) | _kvm_getftype(vp->v_type);
850 	kf->va_size = de.de_FileSize;
851 	kf->va_rdev = 0;  /* msdosfs doesn't support device files */
852 
853 	return (0);
854 }
855 
856 static int
857 nfs_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
858 {
859 	struct nfsnode nfsnode;
860 
861 	if (KREAD(kd, (u_long)VTONFS(vp), &nfsnode)) {
862 		_kvm_err(kd, kd->program, "can't read nfsnode at %p",
863 		    VTONFS(vp));
864 		return (-1);
865 	}
866 	kf->va_fsid = nfsnode.n_vattr.va_fsid;
867 	kf->va_fileid = nfsnode.n_vattr.va_fileid;
868 	kf->va_size = nfsnode.n_size;
869 	kf->va_rdev = nfsnode.n_vattr.va_rdev;
870 	kf->va_mode = (mode_t)nfsnode.n_vattr.va_mode | _kvm_getftype(vp->v_type);
871 
872 	return (0);
873 }
874 
875 static int
876 spec_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
877 {
878 	struct specinfo		specinfo;
879 	struct vnode		parent;
880 
881 	if (KREAD(kd, (u_long)vp->v_specinfo, &specinfo)) {
882 		_kvm_err(kd, kd->program, "can't read specinfo at %p",
883 		     vp->v_specinfo);
884 		return (-1);
885 	}
886 
887 	vp->v_specinfo = &specinfo;
888 
889 	if (KREAD(kd, (u_long)vp->v_specparent, &parent)) {
890 		_kvm_err(kd, kd->program, "can't read parent vnode at %p",
891 		     vp->v_specparent);
892 		return (-1);
893 	}
894 
895 	if (ufs_filestat(kd, kf, vp))
896 		return (-1);
897 
898 	return (0);
899 }
900 
901 static int
902 filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
903 {
904 	int ret = 0;
905 
906 	if (vp->v_type != VNON && vp->v_type != VBAD) {
907 		switch (vp->v_tag) {
908 		case VT_UFS:
909 		case VT_MFS:
910 			ret = ufs_filestat(kd, kf, vp);
911 			break;
912 		case VT_NFS:
913 			ret = nfs_filestat(kd, kf, vp);
914 			break;
915 		case VT_EXT2FS:
916 			ret = ext2fs_filestat(kd, kf, vp);
917 			break;
918 		case VT_ISOFS:
919 			ret = _kvm_stat_cd9660(kd, kf, vp);
920 			break;
921 		case VT_MSDOSFS:
922 			ret = msdos_filestat(kd, kf, vp);
923 			break;
924 		case VT_UDF:
925 			ret = _kvm_stat_udf(kd, kf, vp);
926 			break;
927 		case VT_NTFS:
928 			ret = _kvm_stat_ntfs(kd, kf, vp);
929 			break;
930 		case VT_NON:
931 			if (vp->v_flag & VCLONE)
932 				ret = spec_filestat(kd, kf, vp);
933 			break;
934 		default:
935 			ret = -1;
936 			break;
937 		}
938 	}
939 	return (ret);
940 }
941