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