xref: /openbsd-src/lib/libkvm/kvm_file2.c (revision 5b859c19fe53bbea08f5c342e0a4470e99f883e1)
1 /*	$OpenBSD: kvm_file2.c,v 1.40 2014/11/19 13:35:36 krw 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 
101 #ifdef INET6
102 #include <netinet/ip6.h>
103 #include <netinet6/ip6_var.h>
104 #endif
105 
106 #include <nlist.h>
107 #include <kvm.h>
108 #include <db.h>
109 #include <stddef.h>
110 #include <stdlib.h>
111 #include <string.h>
112 #include <unistd.h>
113 
114 #include "kvm_private.h"
115 #include "kvm_file.h"
116 
117 static struct kinfo_file *kvm_deadfile_byfile(kvm_t *, int, int,
118     size_t, int *);
119 static struct kinfo_file *kvm_deadfile_byid(kvm_t *, int, int,
120     size_t, int *);
121 static int fill_file(kvm_t *, struct kinfo_file *, struct file *, u_long,
122     struct vnode *, struct process *, int, pid_t);
123 static int filestat(kvm_t *, struct kinfo_file *, struct vnode *);
124 
125 LIST_HEAD(processlist, process);
126 
127 struct kinfo_file *
128 kvm_getfiles(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
129 {
130 	int mib[6], rv;
131 	size_t size;
132 
133 	if (kd->filebase != NULL) {
134 		free(kd->filebase);
135 		/*
136 		 * Clear this pointer in case this call fails.  Otherwise,
137 		 * kvm_close() will free it again.
138 		 */
139 		kd->filebase = 0;
140 	}
141 
142 	if (ISALIVE(kd)) {
143 		mib[0] = CTL_KERN;
144 		mib[1] = KERN_FILE;
145 		mib[2] = op;
146 		mib[3] = arg;
147 		mib[4] = esize;
148 		mib[5] = 0;
149 
150 		/* find size and alloc buffer */
151 		rv = sysctl(mib, 6, NULL, &size, NULL, 0);
152 		if (rv == -1) {
153 			if (kd->vmfd != -1)
154 				goto deadway;
155 			_kvm_syserr(kd, kd->program, "kvm_getfiles");
156 			return (NULL);
157 		}
158 		kd->filebase = _kvm_malloc(kd, size);
159 		if (kd->filebase == NULL)
160 			return (NULL);
161 
162 		/* get actual data */
163 		mib[5] = size / esize;
164 		rv = sysctl(mib, 6, kd->filebase, &size, NULL, 0);
165 		if (rv == -1) {
166 			_kvm_syserr(kd, kd->program, "kvm_getfiles");
167 			return (NULL);
168 		}
169 		*cnt = size / esize;
170 		return (kd->filebase);
171 	} else {
172 		if (esize > sizeof(struct kinfo_file)) {
173 			_kvm_syserr(kd, kd->program,
174 			    "kvm_getfiles: unknown fields requested: libkvm out of date?");
175 			return (NULL);
176 		}
177 	    deadway:
178 		switch (op) {
179 		case KERN_FILE_BYFILE:
180 			if (arg != 0) {
181 				_kvm_err(kd, kd->program,
182 				    "%d: invalid argument", arg);
183 				return (NULL);
184 			}
185 			return (kvm_deadfile_byfile(kd, op, arg, esize, cnt));
186 			break;
187 		case KERN_FILE_BYPID:
188 		case KERN_FILE_BYUID:
189 			return (kvm_deadfile_byid(kd, op, arg, esize, cnt));
190 			break;
191 		default:
192 			return (NULL);
193 		}
194 	}
195 }
196 
197 static struct kinfo_file *
198 kvm_deadfile_byfile(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
199 {
200 	struct nlist nl[3], *p;
201 	size_t buflen;
202 	int n = 0;
203 	char *where;
204 	struct kinfo_file kf;
205 	struct file *fp, file;
206 	struct filelist filehead;
207 	int nfiles;
208 
209 	nl[0].n_name = "_filehead";
210 	nl[1].n_name = "_nfiles";
211 	nl[2].n_name = 0;
212 
213 	if (kvm_nlist(kd, nl) != 0) {
214 		for (p = nl; p->n_type != 0; ++p)
215 			;
216 		_kvm_err(kd, kd->program,
217 			 "%s: no such symbol", p->n_name);
218 		return (NULL);
219 	}
220 	if (KREAD(kd, nl[0].n_value, &filehead)) {
221 		_kvm_err(kd, kd->program, "can't read filehead");
222 		return (NULL);
223 	}
224 	if (KREAD(kd, nl[1].n_value, &nfiles)) {
225 		_kvm_err(kd, kd->program, "can't read nfiles");
226 		return (NULL);
227 	}
228 	where = _kvm_reallocarray(kd, NULL, nfiles, esize);
229 	kd->filebase = (void *)where;
230 	if (kd->filebase == NULL)
231 		return (NULL);
232 	buflen = nfiles * esize;
233 
234 	for (fp = LIST_FIRST(&filehead);
235 	    fp != NULL && esize <= buflen;
236 	    fp = LIST_NEXT(&file, f_list)) {
237 		if (KREAD(kd, (u_long)fp, &file)) {
238 			_kvm_err(kd, kd->program, "can't read kfp");
239 			return (NULL);
240 		}
241 		if (fill_file(kd, &kf, &file, (u_long)fp, NULL, NULL, 0, 0)
242 		    == -1)
243 			return (NULL);
244 		memcpy(where, &kf, esize);
245 		where += esize;
246 		buflen -= esize;
247 		n++;
248 	}
249 	if (n != nfiles) {
250 		_kvm_err(kd, kd->program, "inconsistent nfiles");
251 		return (NULL);
252 	}
253 	*cnt = n;
254 	return (kd->filebase);
255 }
256 
257 static struct kinfo_file *
258 kvm_deadfile_byid(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
259 {
260 	size_t buflen;
261 	struct nlist nl[4], *np;
262 	int n = 0;
263 	char *where;
264 	struct kinfo_file kf;
265 	struct file *fp, file;
266 	struct filelist filehead;
267 	struct filedesc0 filed0;
268 #define filed	filed0.fd_fd
269 	struct processlist allprocess;
270 	struct proc proc;
271 	struct process *pr, process;
272 	struct ucred ucred;
273 	char *filebuf = NULL;
274 	int i, nfiles;
275 
276 	nl[0].n_name = "_filehead";
277 	nl[1].n_name = "_nfiles";
278 	nl[2].n_name = "_allprocess";
279 	nl[3].n_name = 0;
280 
281 	if (kvm_nlist(kd, nl) != 0) {
282 		for (np = nl; np->n_type != 0; ++np)
283 			;
284 		_kvm_err(kd, kd->program,
285 			 "%s: no such symbol", np->n_name);
286 		return (NULL);
287 	}
288 	if (KREAD(kd, nl[0].n_value, &filehead)) {
289 		_kvm_err(kd, kd->program, "can't read filehead");
290 		return (NULL);
291 	}
292 	if (KREAD(kd, nl[1].n_value, &nfiles)) {
293 		_kvm_err(kd, kd->program, "can't read nfiles");
294 		return (NULL);
295 	}
296 	if (KREAD(kd, nl[2].n_value, &allprocess)) {
297 		_kvm_err(kd, kd->program, "can't read allprocess");
298 		return (NULL);
299 	}
300 	/* this may be more room than we need but counting is expensive */
301 	where = _kvm_reallocarray(kd, NULL, nfiles + 10, esize);
302 	kd->filebase = (void *)where;
303 	if (kd->filebase == NULL)
304 		return (NULL);
305 	buflen = (nfiles + 10) * esize;
306 
307 	for (pr = LIST_FIRST(&allprocess);
308 	    pr != NULL;
309 	    pr = LIST_NEXT(&process, ps_list)) {
310 		if (KREAD(kd, (u_long)pr, &process)) {
311 			_kvm_err(kd, kd->program, "can't read process at %lx",
312 			    (u_long)pr);
313 			goto cleanup;
314 		}
315 
316 		/* skip system, exiting, embryonic and undead processes */
317 		if (process.ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING))
318 			continue;
319 
320 		if (process.ps_mainproc == NULL)
321 			continue;
322 		if (KREAD(kd, (u_long)process.ps_mainproc, &proc)) {
323 			_kvm_err(kd, kd->program, "can't read proc at %lx",
324 			    (u_long)process.ps_mainproc);
325 			goto cleanup;
326 		}
327 
328 		if (op == KERN_FILE_BYPID && arg > 0 &&
329 		    proc.p_pid != (pid_t)arg) {
330 				/* not the pid we are looking for */
331 				continue;
332 		}
333 
334 		if (KREAD(kd, (u_long)process.ps_ucred, &ucred)) {
335 			_kvm_err(kd, kd->program, "can't read ucred at %lx",
336 			    (u_long)process.ps_ucred);
337 			goto cleanup;
338 		}
339 		process.ps_mainproc = &proc;
340 		proc.p_p = &process;
341 		process.ps_ucred = &ucred;
342 
343 		if (op == KERN_FILE_BYUID && arg >= 0 &&
344 		    process.ps_ucred->cr_uid != (uid_t)arg) {
345 			/* not the uid we are looking for */
346 			continue;
347 		}
348 
349 		if (KREAD(kd, (u_long)process.ps_fd, &filed0)) {
350 			_kvm_err(kd, kd->program, "can't read filedesc at %lx",
351 			    (u_long)process.ps_fd);
352 			goto cleanup;
353 		}
354 		if ((char *)process.ps_fd + offsetof(struct filedesc0,fd_dfiles)
355 		    == (char *)filed.fd_ofiles) {
356 			filed.fd_ofiles = filed0.fd_dfiles;
357 			filed.fd_ofileflags = filed0.fd_dfileflags;
358 		} else {
359 			size_t fsize;
360 			char *tmp = reallocarray(filebuf,
361 			    filed.fd_nfiles, OFILESIZE);
362 
363 			fsize = filed.fd_nfiles * OFILESIZE;
364 			if (tmp == NULL) {
365 				_kvm_syserr(kd, kd->program, "realloc ofiles");
366 				goto cleanup;
367 			}
368 			filebuf = tmp;
369 			if (kvm_read(kd, (u_long)filed.fd_ofiles, filebuf,
370 			    fsize) != fsize) {
371 				_kvm_err(kd, kd->program,
372 				    "can't read fd_ofiles");
373 				goto cleanup;
374 			}
375 			filed.fd_ofiles = (void *)filebuf;
376 			filed.fd_ofileflags = filebuf +
377 			    (filed.fd_nfiles * sizeof(struct file *));
378 		}
379 		process.ps_fd = &filed;
380 
381 		if (process.ps_textvp) {
382 			if (buflen < esize)
383 				goto done;
384 			if (fill_file(kd, &kf, NULL, 0, process.ps_textvp,
385 			    &process, KERN_FILE_TEXT, proc.p_pid) == -1)
386 				goto cleanup;
387 			memcpy(where, &kf, esize);
388 			where += esize;
389 			buflen -= esize;
390 			n++;
391 		}
392 		if (filed.fd_cdir) {
393 			if (buflen < esize)
394 				goto done;
395 			if (fill_file(kd, &kf, NULL, 0, filed.fd_cdir,
396 			    &process, KERN_FILE_CDIR, proc.p_pid) == -1)
397 				goto cleanup;
398 			memcpy(where, &kf, esize);
399 			where += esize;
400 			buflen -= esize;
401 			n++;
402 		}
403 		if (filed.fd_rdir) {
404 			if (buflen < esize)
405 				goto done;
406 			if (fill_file(kd, &kf, NULL, 0, filed.fd_rdir,
407 			    &process, KERN_FILE_RDIR, proc.p_pid) == -1)
408 				goto cleanup;
409 			memcpy(where, &kf, esize);
410 			where += esize;
411 			buflen -= esize;
412 			n++;
413 		}
414 		if (process.ps_tracevp) {
415 			if (buflen < esize)
416 				goto done;
417 			if (fill_file(kd, &kf, NULL, 0, process.ps_tracevp,
418 			    &process, KERN_FILE_TRACE, proc.p_pid) == -1)
419 				goto cleanup;
420 			memcpy(where, &kf, esize);
421 			where += esize;
422 			buflen -= esize;
423 			n++;
424 		}
425 
426 		if (filed.fd_nfiles < 0 ||
427 		    filed.fd_lastfile >= filed.fd_nfiles ||
428 		    filed.fd_freefile > filed.fd_lastfile + 1) {
429 			_kvm_err(kd, kd->program,
430 			    "filedesc corrupted at %lx for pid %d",
431 			    (u_long)process.ps_fd, proc.p_pid);
432 			goto cleanup;
433 		}
434 
435 		for (i = 0; i < filed.fd_nfiles; i++) {
436 			if (buflen < esize)
437 				goto done;
438 			if ((fp = filed.fd_ofiles[i]) == NULL)
439 				continue;
440 			if (KREAD(kd, (u_long)fp, &file)) {
441 				_kvm_err(kd, kd->program, "can't read file");
442 				goto cleanup;
443 			}
444 			if (fill_file(kd, &kf, &file, (u_long)fp, NULL,
445 			    &process, i, proc.p_pid) == -1)
446 				goto cleanup;
447 			memcpy(where, &kf, esize);
448 			where += esize;
449 			buflen -= esize;
450 			n++;
451 		}
452 	}
453 done:
454 	*cnt = n;
455 	free(filebuf);
456 	return (kd->filebase);
457 cleanup:
458 	free(filebuf);
459 	return (NULL);
460 }
461 
462 static int
463 fill_file(kvm_t *kd, struct kinfo_file *kf, struct file *fp, u_long fpaddr,
464     struct vnode *vp, struct process *pr, int fd, pid_t pid)
465 {
466 	struct ucred f_cred;
467 
468 	memset(kf, 0, sizeof(*kf));
469 
470 	kf->fd_fd = fd;		/* might not really be an fd */
471 
472 	if (fp != NULL) {
473 		/* Fill in f_cred */
474 		if (KREAD(kd, (u_long)fp->f_cred, &f_cred)) {
475 			_kvm_err(kd, kd->program, "can't read f_cred");
476 			return (-1);
477 		}
478 
479 		kf->f_fileaddr = PTRTOINT64(fpaddr);
480 		kf->f_flag = fp->f_flag;
481 		kf->f_iflags = fp->f_iflags;
482 		kf->f_type = fp->f_type;
483 		kf->f_count = fp->f_count;
484 		kf->f_msgcount = fp->f_msgcount;
485 		kf->f_ucred = PTRTOINT64(fp->f_cred);
486 		kf->f_uid = f_cred.cr_uid;
487 		kf->f_gid = f_cred.cr_gid;
488 		kf->f_ops = PTRTOINT64(fp->f_ops);
489 		kf->f_offset = fp->f_offset;
490 		kf->f_data = PTRTOINT64(fp->f_data);
491 		kf->f_usecount = 0;
492 
493 		kf->f_rxfer = fp->f_rxfer;
494 		kf->f_rwfer = fp->f_wxfer;
495 		kf->f_seek = fp->f_seek;
496 		kf->f_rbytes = fp->f_rbytes;
497 		kf->f_wbytes = fp->f_wbytes;
498 	} else if (vp != NULL) {
499 		/* fake it */
500 		kf->f_type = DTYPE_VNODE;
501 		kf->f_flag = FREAD;
502 		if (fd == KERN_FILE_TRACE)
503 			kf->f_flag |= FWRITE;
504 		kf->f_data = PTRTOINT64(vp);
505 	}
506 
507 	/* information about the object associated with this file */
508 	switch (kf->f_type) {
509 	case DTYPE_VNODE: {
510 		struct vnode vbuf;
511 
512 		if (KREAD(kd, (u_long)(fp ? fp->f_data : vp), &vbuf)) {
513 			_kvm_err(kd, kd->program, "can't read vnode");
514 			return (-1);
515 		}
516 		vp = &vbuf;
517 
518 		kf->v_un = PTRTOINT64(vp->v_un.vu_socket);
519 		kf->v_type = vp->v_type;
520 		kf->v_tag = vp->v_tag;
521 		kf->v_flag = vp->v_flag;
522 		kf->v_data = PTRTOINT64(vp->v_data);
523 		kf->v_mount = PTRTOINT64(vp->v_mount);
524 
525 		if (vp->v_mount != NULL) {
526 			struct mount mount;
527 
528 			if (KREAD(kd, (u_long)vp->v_mount, &mount)) {
529 				_kvm_err(kd, kd->program, "can't read v_mount");
530 				return (-1);
531 			}
532 
533 			strlcpy(kf->f_mntonname, mount.mnt_stat.f_mntonname,
534 			    sizeof(kf->f_mntonname));
535 		}
536 
537 		/* Fill in va_fsid, va_fileid, va_mode, va_size, va_rdev */
538 		filestat(kd, kf, vp);
539 		break;
540 	    }
541 
542 	case DTYPE_SOCKET: {
543 		struct socket sock;
544 		struct sosplice ssp;
545 		struct protosw protosw;
546 		struct domain domain;
547 
548 		if (KREAD(kd, (u_long)fp->f_data, &sock)) {
549 			_kvm_err(kd, kd->program, "can't read socket");
550 			return (-1);
551 		}
552 
553 		kf->so_type = sock.so_type;
554 		kf->so_state = sock.so_state;
555 		kf->so_pcb = PTRTOINT64(sock.so_pcb);
556 		if (KREAD(kd, (u_long)sock.so_proto, &protosw)) {
557 			_kvm_err(kd, kd->program, "can't read protosw");
558 			return (-1);
559 		}
560 		kf->so_protocol = protosw.pr_protocol;
561 		if (KREAD(kd, (u_long)protosw.pr_domain, &domain)) {
562 			_kvm_err(kd, kd->program, "can't read domain");
563 			return (-1);
564 		}
565 		kf->so_family = domain.dom_family;
566 		kf->so_rcv_cc = sock.so_rcv.sb_cc;
567 		kf->so_snd_cc = sock.so_snd.sb_cc;
568 		if (sock.so_sp) {
569 			if (KREAD(kd, (u_long)sock.so_sp, &ssp)) {
570 				_kvm_err(kd, kd->program, "can't read splice");
571 				return (-1);
572 			}
573 			if (ssp.ssp_socket) {
574 				kf->so_splice = PTRTOINT64(ssp.ssp_socket);
575 				kf->so_splicelen = ssp.ssp_len;
576 			} else if (ssp.ssp_soback) {
577 				kf->so_splicelen = -1;
578 			}
579 		}
580 		if (!sock.so_pcb)
581 			break;
582 		switch (kf->so_family) {
583 		case AF_INET: {
584 			struct inpcb inpcb;
585 
586 			if (KREAD(kd, (u_long)sock.so_pcb, &inpcb)) {
587 				_kvm_err(kd, kd->program, "can't read inpcb");
588 				return (-1);
589 			}
590 			kf->inp_ppcb = PTRTOINT64(inpcb.inp_ppcb);
591 			kf->inp_lport = inpcb.inp_lport;
592 			kf->inp_laddru[0] = inpcb.inp_laddr.s_addr;
593 			kf->inp_fport = inpcb.inp_fport;
594 			kf->inp_faddru[0] = inpcb.inp_faddr.s_addr;
595 			kf->inp_rtableid = inpcb.inp_rtableid;
596 			break;
597 		    }
598 		case AF_INET6: {
599 			struct inpcb inpcb;
600 #define s6_addr32 __u6_addr.__u6_addr32
601 
602 			if (KREAD(kd, (u_long)sock.so_pcb, &inpcb)) {
603 				_kvm_err(kd, kd->program, "can't read inpcb");
604 				return (-1);
605 			}
606 			kf->inp_ppcb = PTRTOINT64(inpcb.inp_ppcb);
607 			kf->inp_lport = inpcb.inp_lport;
608 			kf->inp_laddru[0] = inpcb.inp_laddr6.s6_addr32[0];
609 			kf->inp_laddru[1] = inpcb.inp_laddr6.s6_addr32[1];
610 			kf->inp_laddru[2] = inpcb.inp_laddr6.s6_addr32[2];
611 			kf->inp_laddru[3] = inpcb.inp_laddr6.s6_addr32[3];
612 			kf->inp_fport = inpcb.inp_fport;
613 			kf->inp_faddru[0] = inpcb.inp_laddr6.s6_addr32[0];
614 			kf->inp_faddru[1] = inpcb.inp_faddr6.s6_addr32[1];
615 			kf->inp_faddru[2] = inpcb.inp_faddr6.s6_addr32[2];
616 			kf->inp_faddru[3] = inpcb.inp_faddr6.s6_addr32[3];
617 			kf->inp_rtableid = inpcb.inp_rtableid;
618 			break;
619 		    }
620 		case AF_UNIX: {
621 			struct unpcb unpcb;
622 
623 			if (KREAD(kd, (u_long)sock.so_pcb, &unpcb)) {
624 				_kvm_err(kd, kd->program, "can't read unpcb");
625 				return (-1);
626 			}
627 			kf->unp_conn	= PTRTOINT64(unpcb.unp_conn);
628 			kf->unp_refs	= PTRTOINT64(unpcb.unp_refs);
629 			kf->unp_nextref	= PTRTOINT64(unpcb.unp_nextref);
630 			kf->v_un	= PTRTOINT64(unpcb.unp_vnode);
631 			if (unpcb.unp_addr != NULL) {
632 				struct mbuf mb;
633 				struct sockaddr_un un;
634 
635 				if (KREAD(kd, (u_long)unpcb.unp_addr, &mb)) {
636 					_kvm_err(kd, kd->program,
637 					    "can't read sockaddr_un mbuf");
638 					return (-1);
639 				}
640 				if (KREAD(kd, (u_long)mb.m_data, &un)) {
641 					_kvm_err(kd, kd->program,
642 					    "can't read sockaddr_un");
643 					return (-1);
644 				}
645 
646 				kf->unp_addr = PTRTOINT64(unpcb.unp_addr);
647 				memcpy(kf->unp_path, un.sun_path, un.sun_len
648 				    - offsetof(struct sockaddr_un,sun_path));
649 			}
650 
651 			break;
652 		    }
653 		}
654 		break;
655 	    }
656 
657 	case DTYPE_PIPE: {
658 		struct pipe pipe;
659 
660 		if (KREAD(kd, (u_long)fp->f_data, &pipe)) {
661 			_kvm_err(kd, kd->program, "can't read pipe");
662 			return (-1);
663 		}
664 		kf->pipe_peer = PTRTOINT64(pipe.pipe_peer);
665 		kf->pipe_state = pipe.pipe_state;
666 		break;
667 	    }
668 
669 	case DTYPE_KQUEUE: {
670 		struct kqueue kqi;
671 
672 		if (KREAD(kd, (u_long)fp->f_data, &kqi)) {
673 			_kvm_err(kd, kd->program, "can't read kqi");
674 			return (-1);
675 		}
676 		kf->kq_count = kqi.kq_count;
677 		kf->kq_state = kqi.kq_state;
678 		break;
679 	    }
680 	case DTYPE_SYSTRACE: {
681 		struct fsystrace f;
682 
683 		if (KREAD(kd, (u_long)fp->f_data, &f)) {
684 			_kvm_err(kd, kd->program, "can't read fsystrace");
685 			return (-1);
686 		}
687 		kf->str_npolicies = f.npolicies;
688 		break;
689 	    }
690 	}
691 
692 	/* per-process information for KERN_FILE_BY[PU]ID */
693 	if (pr != NULL) {
694 		kf->p_pid = pid;
695 		kf->p_uid = pr->ps_ucred->cr_uid;
696 		kf->p_gid = pr->ps_ucred->cr_gid;
697 		kf->p_tid = -1;
698 		strlcpy(kf->p_comm, pr->ps_mainproc->p_comm,
699 		    sizeof(kf->p_comm));
700 		if (pr->ps_fd != NULL)
701 			kf->fd_ofileflags = pr->ps_fd->fd_ofileflags[fd];
702 	}
703 
704 	return (0);
705 }
706 
707 mode_t
708 _kvm_getftype(enum vtype v_type)
709 {
710 	mode_t ftype = 0;
711 
712 	switch (v_type) {
713 	case VREG:
714 		ftype = S_IFREG;
715 		break;
716 	case VDIR:
717 		ftype = S_IFDIR;
718 		break;
719 	case VBLK:
720 		ftype = S_IFBLK;
721 		break;
722 	case VCHR:
723 		ftype = S_IFCHR;
724 		break;
725 	case VLNK:
726 		ftype = S_IFLNK;
727 		break;
728 	case VSOCK:
729 		ftype = S_IFSOCK;
730 		break;
731 	case VFIFO:
732 		ftype = S_IFIFO;
733 		break;
734 	case VNON:
735 	case VBAD:
736 		break;
737 	}
738 
739 	return (ftype);
740 }
741 
742 static int
743 ufs_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
744 {
745 	struct inode inode;
746 	struct ufs1_dinode di1;
747 
748 	if (KREAD(kd, (u_long)VTOI(vp), &inode)) {
749 		_kvm_err(kd, kd->program, "can't read inode at %p", VTOI(vp));
750 		return (-1);
751 	}
752 
753 	if (KREAD(kd, (u_long)inode.i_din1, &di1)) {
754 		_kvm_err(kd, kd->program, "can't read dinode at %p",
755 		    inode.i_din1);
756 		return (-1);
757 	}
758 
759 	inode.i_din1 = &di1;
760 
761 	kf->va_fsid = inode.i_dev & 0xffff;
762 	kf->va_fileid = (long)inode.i_number;
763 	kf->va_mode = inode.i_ffs1_mode;
764 	kf->va_size = inode.i_ffs1_size;
765 	kf->va_rdev = inode.i_ffs1_rdev;
766 
767 	return (0);
768 }
769 
770 static int
771 ext2fs_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
772 {
773 	struct inode inode;
774 	struct ext2fs_dinode e2di;
775 
776 	if (KREAD(kd, (u_long)VTOI(vp), &inode)) {
777 		_kvm_err(kd, kd->program, "can't read inode at %p", VTOI(vp));
778 		return (-1);
779 	}
780 
781 	if (KREAD(kd, (u_long)inode.i_e2din, &e2di)) {
782 		_kvm_err(kd, kd->program, "can't read dinode at %p",
783 		    inode.i_e2din);
784 		return (-1);
785 	}
786 
787 	inode.i_e2din = &e2di;
788 
789 	kf->va_fsid = inode.i_dev & 0xffff;
790 	kf->va_fileid = (long)inode.i_number;
791 	kf->va_mode = inode.i_e2fs_mode;
792 	kf->va_size = inode.i_e2fs_size;
793 	kf->va_rdev = 0;	/* XXX */
794 
795 	return (0);
796 }
797 
798 static int
799 msdos_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
800 {
801 	struct denode de;
802 	struct msdosfsmount mp;
803 
804 	if (KREAD(kd, (u_long)VTODE(vp), &de)) {
805 		_kvm_err(kd, kd->program, "can't read denode at %p", VTODE(vp));
806 		return (-1);
807 	}
808 	if (KREAD(kd, (u_long)de.de_pmp, &mp)) {
809 		_kvm_err(kd, kd->program, "can't read mount struct at %p",
810 		    de.de_pmp);
811 		return (-1);
812 	}
813 
814 	kf->va_fsid = de.de_dev & 0xffff;
815 	kf->va_fileid = 0; /* XXX see msdosfs_vptofh() for more info */
816 	kf->va_mode = (mp.pm_mask & 0777) | _kvm_getftype(vp->v_type);
817 	kf->va_size = de.de_FileSize;
818 	kf->va_rdev = 0;  /* msdosfs doesn't support device files */
819 
820 	return (0);
821 }
822 
823 static int
824 nfs_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
825 {
826 	struct nfsnode nfsnode;
827 
828 	if (KREAD(kd, (u_long)VTONFS(vp), &nfsnode)) {
829 		_kvm_err(kd, kd->program, "can't read nfsnode at %p",
830 		    VTONFS(vp));
831 		return (-1);
832 	}
833 	kf->va_fsid = nfsnode.n_vattr.va_fsid;
834 	kf->va_fileid = nfsnode.n_vattr.va_fileid;
835 	kf->va_size = nfsnode.n_size;
836 	kf->va_rdev = nfsnode.n_vattr.va_rdev;
837 	kf->va_mode = (mode_t)nfsnode.n_vattr.va_mode | _kvm_getftype(vp->v_type);
838 
839 	return (0);
840 }
841 
842 static int
843 spec_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
844 {
845 	struct specinfo		specinfo;
846 	struct vnode		parent;
847 
848 	if (KREAD(kd, (u_long)vp->v_specinfo, &specinfo)) {
849 		_kvm_err(kd, kd->program, "can't read specinfo at %p",
850 		     vp->v_specinfo);
851 		return (-1);
852 	}
853 
854 	vp->v_specinfo = &specinfo;
855 
856 	if (KREAD(kd, (u_long)vp->v_specparent, &parent)) {
857 		_kvm_err(kd, kd->program, "can't read parent vnode at %p",
858 		     vp->v_specparent);
859 		return (-1);
860 	}
861 
862 	if (ufs_filestat(kd, kf, vp))
863 		return (-1);
864 
865 	return (0);
866 }
867 
868 static int
869 filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
870 {
871 	int ret = 0;
872 
873 	if (vp->v_type != VNON && vp->v_type != VBAD) {
874 		switch (vp->v_tag) {
875 		case VT_UFS:
876 		case VT_MFS:
877 			ret = ufs_filestat(kd, kf, vp);
878 			break;
879 		case VT_NFS:
880 			ret = nfs_filestat(kd, kf, vp);
881 			break;
882 		case VT_EXT2FS:
883 			ret = ext2fs_filestat(kd, kf, vp);
884 			break;
885 		case VT_ISOFS:
886 			ret = _kvm_stat_cd9660(kd, kf, vp);
887 			break;
888 		case VT_MSDOSFS:
889 			ret = msdos_filestat(kd, kf, vp);
890 			break;
891 		case VT_UDF:
892 			ret = _kvm_stat_udf(kd, kf, vp);
893 			break;
894 		case VT_NTFS:
895 			ret = _kvm_stat_ntfs(kd, kf, vp);
896 			break;
897 		case VT_NON:
898 			if (vp->v_flag & VCLONE)
899 				ret = spec_filestat(kd, kf, vp);
900 			break;
901 		default:
902 			ret = -1;
903 			break;
904 		}
905 	}
906 	return (ret);
907 }
908