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