1*0daf62d9SStanislav Sedov /*- 2*0daf62d9SStanislav Sedov * Copyright (c) 2009 Stanislav Sedov <[email protected]> 3*0daf62d9SStanislav Sedov * Copyright (c) 1988, 1993 4*0daf62d9SStanislav Sedov * The Regents of the University of California. All rights reserved. 5*0daf62d9SStanislav Sedov * 6*0daf62d9SStanislav Sedov * Redistribution and use in source and binary forms, with or without 7*0daf62d9SStanislav Sedov * modification, are permitted provided that the following conditions 8*0daf62d9SStanislav Sedov * are met: 9*0daf62d9SStanislav Sedov * 1. Redistributions of source code must retain the above copyright 10*0daf62d9SStanislav Sedov * notice, this list of conditions and the following disclaimer. 11*0daf62d9SStanislav Sedov * 2. Redistributions in binary form must reproduce the above copyright 12*0daf62d9SStanislav Sedov * notice, this list of conditions and the following disclaimer in the 13*0daf62d9SStanislav Sedov * documentation and/or other materials provided with the distribution. 14*0daf62d9SStanislav Sedov * 3. All advertising materials mentioning features or use of this software 15*0daf62d9SStanislav Sedov * must display the following acknowledgement: 16*0daf62d9SStanislav Sedov * This product includes software developed by the University of 17*0daf62d9SStanislav Sedov * California, Berkeley and its contributors. 18*0daf62d9SStanislav Sedov * 4. Neither the name of the University nor the names of its contributors 19*0daf62d9SStanislav Sedov * may be used to endorse or promote products derived from this software 20*0daf62d9SStanislav Sedov * without specific prior written permission. 21*0daf62d9SStanislav Sedov * 22*0daf62d9SStanislav Sedov * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23*0daf62d9SStanislav Sedov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24*0daf62d9SStanislav Sedov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25*0daf62d9SStanislav Sedov * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26*0daf62d9SStanislav Sedov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27*0daf62d9SStanislav Sedov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28*0daf62d9SStanislav Sedov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29*0daf62d9SStanislav Sedov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30*0daf62d9SStanislav Sedov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31*0daf62d9SStanislav Sedov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32*0daf62d9SStanislav Sedov * SUCH DAMAGE. 33*0daf62d9SStanislav Sedov */ 34*0daf62d9SStanislav Sedov 35*0daf62d9SStanislav Sedov #include <sys/cdefs.h> 36*0daf62d9SStanislav Sedov __FBSDID("$FreeBSD$"); 37*0daf62d9SStanislav Sedov 38*0daf62d9SStanislav Sedov #include <sys/param.h> 39*0daf62d9SStanislav Sedov #include <sys/time.h> 40*0daf62d9SStanislav Sedov #include <sys/proc.h> 41*0daf62d9SStanislav Sedov #include <sys/user.h> 42*0daf62d9SStanislav Sedov #include <sys/stat.h> 43*0daf62d9SStanislav Sedov #include <sys/vnode.h> 44*0daf62d9SStanislav Sedov #include <sys/socket.h> 45*0daf62d9SStanislav Sedov #include <sys/socketvar.h> 46*0daf62d9SStanislav Sedov #include <sys/domain.h> 47*0daf62d9SStanislav Sedov #include <sys/protosw.h> 48*0daf62d9SStanislav Sedov #include <sys/un.h> 49*0daf62d9SStanislav Sedov #include <sys/unpcb.h> 50*0daf62d9SStanislav Sedov #include <sys/sysctl.h> 51*0daf62d9SStanislav Sedov #include <sys/tty.h> 52*0daf62d9SStanislav Sedov #include <sys/filedesc.h> 53*0daf62d9SStanislav Sedov #include <sys/queue.h> 54*0daf62d9SStanislav Sedov #define _WANT_FILE 55*0daf62d9SStanislav Sedov #include <sys/file.h> 56*0daf62d9SStanislav Sedov #include <sys/conf.h> 57*0daf62d9SStanislav Sedov #define _KERNEL 58*0daf62d9SStanislav Sedov #include <sys/mount.h> 59*0daf62d9SStanislav Sedov #include <sys/pipe.h> 60*0daf62d9SStanislav Sedov #include <ufs/ufs/quota.h> 61*0daf62d9SStanislav Sedov #include <ufs/ufs/inode.h> 62*0daf62d9SStanislav Sedov #include <fs/devfs/devfs.h> 63*0daf62d9SStanislav Sedov #include <fs/devfs/devfs_int.h> 64*0daf62d9SStanislav Sedov #undef _KERNEL 65*0daf62d9SStanislav Sedov #include <nfs/nfsproto.h> 66*0daf62d9SStanislav Sedov #include <nfsclient/nfs.h> 67*0daf62d9SStanislav Sedov #include <nfsclient/nfsnode.h> 68*0daf62d9SStanislav Sedov 69*0daf62d9SStanislav Sedov #include <vm/vm.h> 70*0daf62d9SStanislav Sedov #include <vm/vm_map.h> 71*0daf62d9SStanislav Sedov #include <vm/vm_object.h> 72*0daf62d9SStanislav Sedov 73*0daf62d9SStanislav Sedov #include <net/route.h> 74*0daf62d9SStanislav Sedov #include <netinet/in.h> 75*0daf62d9SStanislav Sedov #include <netinet/in_systm.h> 76*0daf62d9SStanislav Sedov #include <netinet/ip.h> 77*0daf62d9SStanislav Sedov #include <netinet/in_pcb.h> 78*0daf62d9SStanislav Sedov 79*0daf62d9SStanislav Sedov #include <assert.h> 80*0daf62d9SStanislav Sedov #include <ctype.h> 81*0daf62d9SStanislav Sedov #include <err.h> 82*0daf62d9SStanislav Sedov #include <fcntl.h> 83*0daf62d9SStanislav Sedov #include <kvm.h> 84*0daf62d9SStanislav Sedov #include <libutil.h> 85*0daf62d9SStanislav Sedov #include <limits.h> 86*0daf62d9SStanislav Sedov #include <paths.h> 87*0daf62d9SStanislav Sedov #include <pwd.h> 88*0daf62d9SStanislav Sedov #include <stdio.h> 89*0daf62d9SStanislav Sedov #include <stdlib.h> 90*0daf62d9SStanislav Sedov #include <stddef.h> 91*0daf62d9SStanislav Sedov #include <string.h> 92*0daf62d9SStanislav Sedov #include <unistd.h> 93*0daf62d9SStanislav Sedov #include <netdb.h> 94*0daf62d9SStanislav Sedov 95*0daf62d9SStanislav Sedov #include <libprocstat.h> 96*0daf62d9SStanislav Sedov #include "libprocstat_internal.h" 97*0daf62d9SStanislav Sedov #include "common_kvm.h" 98*0daf62d9SStanislav Sedov 99*0daf62d9SStanislav Sedov int statfs(const char *, struct statfs *); /* XXX */ 100*0daf62d9SStanislav Sedov 101*0daf62d9SStanislav Sedov #define PROCSTAT_KVM 1 102*0daf62d9SStanislav Sedov #define PROCSTAT_SYSCTL 2 103*0daf62d9SStanislav Sedov 104*0daf62d9SStanislav Sedov static char *getmnton(kvm_t *kd, struct mount *m); 105*0daf62d9SStanislav Sedov static struct filestat_list *procstat_getfiles_kvm( 106*0daf62d9SStanislav Sedov struct procstat *procstat, struct kinfo_proc *kp, int mmapped); 107*0daf62d9SStanislav Sedov static struct filestat_list *procstat_getfiles_sysctl( 108*0daf62d9SStanislav Sedov struct procstat *procstat, struct kinfo_proc *kp, int mmapped); 109*0daf62d9SStanislav Sedov static int procstat_get_pipe_info_sysctl(struct filestat *fst, 110*0daf62d9SStanislav Sedov struct pipestat *pipe, char *errbuf); 111*0daf62d9SStanislav Sedov static int procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst, 112*0daf62d9SStanislav Sedov struct pipestat *pipe, char *errbuf); 113*0daf62d9SStanislav Sedov static int procstat_get_pts_info_sysctl(struct filestat *fst, 114*0daf62d9SStanislav Sedov struct ptsstat *pts, char *errbuf); 115*0daf62d9SStanislav Sedov static int procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst, 116*0daf62d9SStanislav Sedov struct ptsstat *pts, char *errbuf); 117*0daf62d9SStanislav Sedov static int procstat_get_socket_info_sysctl(struct filestat *fst, 118*0daf62d9SStanislav Sedov struct sockstat *sock, char *errbuf); 119*0daf62d9SStanislav Sedov static int procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst, 120*0daf62d9SStanislav Sedov struct sockstat *sock, char *errbuf); 121*0daf62d9SStanislav Sedov static int to_filestat_flags(int flags); 122*0daf62d9SStanislav Sedov static int procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst, 123*0daf62d9SStanislav Sedov struct vnstat *vn, char *errbuf); 124*0daf62d9SStanislav Sedov static int procstat_get_vnode_info_sysctl(struct filestat *fst, 125*0daf62d9SStanislav Sedov struct vnstat *vn, char *errbuf); 126*0daf62d9SStanislav Sedov static int vntype2psfsttype(int type); 127*0daf62d9SStanislav Sedov 128*0daf62d9SStanislav Sedov void 129*0daf62d9SStanislav Sedov procstat_close(struct procstat *procstat) 130*0daf62d9SStanislav Sedov { 131*0daf62d9SStanislav Sedov 132*0daf62d9SStanislav Sedov assert(procstat); 133*0daf62d9SStanislav Sedov if (procstat->type == PROCSTAT_KVM) 134*0daf62d9SStanislav Sedov kvm_close(procstat->kd); 135*0daf62d9SStanislav Sedov } 136*0daf62d9SStanislav Sedov 137*0daf62d9SStanislav Sedov struct procstat * 138*0daf62d9SStanislav Sedov procstat_open_sysctl(void) 139*0daf62d9SStanislav Sedov { 140*0daf62d9SStanislav Sedov struct procstat *procstat; 141*0daf62d9SStanislav Sedov 142*0daf62d9SStanislav Sedov procstat = calloc(1, sizeof(*procstat)); 143*0daf62d9SStanislav Sedov if (procstat == NULL) { 144*0daf62d9SStanislav Sedov warn("malloc()"); 145*0daf62d9SStanislav Sedov return (NULL); 146*0daf62d9SStanislav Sedov } 147*0daf62d9SStanislav Sedov procstat->type = PROCSTAT_SYSCTL; 148*0daf62d9SStanislav Sedov return (procstat); 149*0daf62d9SStanislav Sedov } 150*0daf62d9SStanislav Sedov 151*0daf62d9SStanislav Sedov struct procstat * 152*0daf62d9SStanislav Sedov procstat_open_kvm(const char *nlistf, const char *memf) 153*0daf62d9SStanislav Sedov { 154*0daf62d9SStanislav Sedov struct procstat *procstat; 155*0daf62d9SStanislav Sedov kvm_t *kd; 156*0daf62d9SStanislav Sedov char buf[_POSIX2_LINE_MAX]; 157*0daf62d9SStanislav Sedov 158*0daf62d9SStanislav Sedov procstat = calloc(1, sizeof(*procstat)); 159*0daf62d9SStanislav Sedov if (procstat == NULL) { 160*0daf62d9SStanislav Sedov warn("malloc()"); 161*0daf62d9SStanislav Sedov return (NULL); 162*0daf62d9SStanislav Sedov } 163*0daf62d9SStanislav Sedov kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf); 164*0daf62d9SStanislav Sedov if (kd == NULL) { 165*0daf62d9SStanislav Sedov warnx("kvm_openfiles(): %s", buf); 166*0daf62d9SStanislav Sedov free(procstat); 167*0daf62d9SStanislav Sedov return (NULL); 168*0daf62d9SStanislav Sedov } 169*0daf62d9SStanislav Sedov procstat->type = PROCSTAT_KVM; 170*0daf62d9SStanislav Sedov procstat->kd = kd; 171*0daf62d9SStanislav Sedov return (procstat); 172*0daf62d9SStanislav Sedov } 173*0daf62d9SStanislav Sedov 174*0daf62d9SStanislav Sedov struct kinfo_proc * 175*0daf62d9SStanislav Sedov procstat_getprocs(struct procstat *procstat, int what, int arg, 176*0daf62d9SStanislav Sedov unsigned int *count) 177*0daf62d9SStanislav Sedov { 178*0daf62d9SStanislav Sedov struct kinfo_proc *p0, *p; 179*0daf62d9SStanislav Sedov size_t len; 180*0daf62d9SStanislav Sedov int name[4]; 181*0daf62d9SStanislav Sedov int error; 182*0daf62d9SStanislav Sedov 183*0daf62d9SStanislav Sedov assert(procstat); 184*0daf62d9SStanislav Sedov assert(count); 185*0daf62d9SStanislav Sedov p = NULL; 186*0daf62d9SStanislav Sedov if (procstat->type == PROCSTAT_KVM) { 187*0daf62d9SStanislav Sedov p0 = kvm_getprocs(procstat->kd, what, arg, count); 188*0daf62d9SStanislav Sedov if (p0 == NULL || count == 0) 189*0daf62d9SStanislav Sedov return (NULL); 190*0daf62d9SStanislav Sedov len = *count * sizeof(*p); 191*0daf62d9SStanislav Sedov p = malloc(len); 192*0daf62d9SStanislav Sedov if (p == NULL) { 193*0daf62d9SStanislav Sedov warnx("malloc(%zd)", len); 194*0daf62d9SStanislav Sedov goto fail; 195*0daf62d9SStanislav Sedov } 196*0daf62d9SStanislav Sedov bcopy(p0, p, len); 197*0daf62d9SStanislav Sedov return (p); 198*0daf62d9SStanislav Sedov } else if (procstat->type == PROCSTAT_SYSCTL) { 199*0daf62d9SStanislav Sedov len = 0; 200*0daf62d9SStanislav Sedov name[0] = CTL_KERN; 201*0daf62d9SStanislav Sedov name[1] = KERN_PROC; 202*0daf62d9SStanislav Sedov name[2] = what; 203*0daf62d9SStanislav Sedov name[3] = arg; 204*0daf62d9SStanislav Sedov error = sysctl(name, 4, NULL, &len, NULL, 0); 205*0daf62d9SStanislav Sedov if (error < 0 && errno != EPERM) { 206*0daf62d9SStanislav Sedov warn("sysctl(kern.proc)"); 207*0daf62d9SStanislav Sedov goto fail; 208*0daf62d9SStanislav Sedov } 209*0daf62d9SStanislav Sedov if (len == 0) { 210*0daf62d9SStanislav Sedov warnx("no processes?"); 211*0daf62d9SStanislav Sedov goto fail; 212*0daf62d9SStanislav Sedov } 213*0daf62d9SStanislav Sedov p = malloc(len); 214*0daf62d9SStanislav Sedov if (p == NULL) { 215*0daf62d9SStanislav Sedov warnx("malloc(%zd)", len); 216*0daf62d9SStanislav Sedov goto fail; 217*0daf62d9SStanislav Sedov } 218*0daf62d9SStanislav Sedov error = sysctl(name, 4, p, &len, NULL, 0); 219*0daf62d9SStanislav Sedov if (error < 0 && errno != EPERM) { 220*0daf62d9SStanislav Sedov warn("sysctl(kern.proc)"); 221*0daf62d9SStanislav Sedov goto fail; 222*0daf62d9SStanislav Sedov } 223*0daf62d9SStanislav Sedov /* Perform simple consistency checks. */ 224*0daf62d9SStanislav Sedov if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) { 225*0daf62d9SStanislav Sedov warnx("kinfo_proc structure size mismatch"); 226*0daf62d9SStanislav Sedov goto fail; 227*0daf62d9SStanislav Sedov } 228*0daf62d9SStanislav Sedov *count = len / sizeof(*p); 229*0daf62d9SStanislav Sedov return (p); 230*0daf62d9SStanislav Sedov } else { 231*0daf62d9SStanislav Sedov warnx("unknown access method"); 232*0daf62d9SStanislav Sedov return (NULL); 233*0daf62d9SStanislav Sedov } 234*0daf62d9SStanislav Sedov fail: 235*0daf62d9SStanislav Sedov if (p) 236*0daf62d9SStanislav Sedov free(p); 237*0daf62d9SStanislav Sedov return (NULL); 238*0daf62d9SStanislav Sedov } 239*0daf62d9SStanislav Sedov 240*0daf62d9SStanislav Sedov void 241*0daf62d9SStanislav Sedov procstat_freeprocs(struct procstat *procstat __unused, struct kinfo_proc *p) 242*0daf62d9SStanislav Sedov { 243*0daf62d9SStanislav Sedov 244*0daf62d9SStanislav Sedov if (p != NULL) 245*0daf62d9SStanislav Sedov free(p); 246*0daf62d9SStanislav Sedov p = NULL; 247*0daf62d9SStanislav Sedov } 248*0daf62d9SStanislav Sedov 249*0daf62d9SStanislav Sedov struct filestat_list * 250*0daf62d9SStanislav Sedov procstat_getfiles(struct procstat *procstat, struct kinfo_proc *kp, int mmapped) 251*0daf62d9SStanislav Sedov { 252*0daf62d9SStanislav Sedov 253*0daf62d9SStanislav Sedov if (procstat->type == PROCSTAT_SYSCTL) 254*0daf62d9SStanislav Sedov return (procstat_getfiles_sysctl(procstat, kp, mmapped)); 255*0daf62d9SStanislav Sedov else if (procstat->type == PROCSTAT_KVM) 256*0daf62d9SStanislav Sedov return (procstat_getfiles_kvm(procstat, kp, mmapped)); 257*0daf62d9SStanislav Sedov else 258*0daf62d9SStanislav Sedov return (NULL); 259*0daf62d9SStanislav Sedov } 260*0daf62d9SStanislav Sedov 261*0daf62d9SStanislav Sedov void 262*0daf62d9SStanislav Sedov procstat_freefiles(struct procstat *procstat, struct filestat_list *head) 263*0daf62d9SStanislav Sedov { 264*0daf62d9SStanislav Sedov struct filestat *fst, *tmp; 265*0daf62d9SStanislav Sedov 266*0daf62d9SStanislav Sedov STAILQ_FOREACH_SAFE(fst, head, next, tmp) { 267*0daf62d9SStanislav Sedov if (fst->fs_path != NULL) 268*0daf62d9SStanislav Sedov free(fst->fs_path); 269*0daf62d9SStanislav Sedov free(fst); 270*0daf62d9SStanislav Sedov } 271*0daf62d9SStanislav Sedov free(head); 272*0daf62d9SStanislav Sedov if (procstat->vmentries != NULL) { 273*0daf62d9SStanislav Sedov free (procstat->vmentries); 274*0daf62d9SStanislav Sedov procstat->vmentries = NULL; 275*0daf62d9SStanislav Sedov } 276*0daf62d9SStanislav Sedov if (procstat->files != NULL) { 277*0daf62d9SStanislav Sedov free (procstat->files); 278*0daf62d9SStanislav Sedov procstat->files = NULL; 279*0daf62d9SStanislav Sedov } 280*0daf62d9SStanislav Sedov } 281*0daf62d9SStanislav Sedov 282*0daf62d9SStanislav Sedov static struct filestat * 283*0daf62d9SStanislav Sedov filestat_new_entry(void *typedep, int type, int fd, int fflags, int uflags, 284*0daf62d9SStanislav Sedov int refcount, off_t offset, char *path) 285*0daf62d9SStanislav Sedov { 286*0daf62d9SStanislav Sedov struct filestat *entry; 287*0daf62d9SStanislav Sedov 288*0daf62d9SStanislav Sedov entry = calloc(1, sizeof(*entry)); 289*0daf62d9SStanislav Sedov if (entry == NULL) { 290*0daf62d9SStanislav Sedov warn("malloc()"); 291*0daf62d9SStanislav Sedov return (NULL); 292*0daf62d9SStanislav Sedov } 293*0daf62d9SStanislav Sedov entry->fs_typedep = typedep; 294*0daf62d9SStanislav Sedov entry->fs_fflags = fflags; 295*0daf62d9SStanislav Sedov entry->fs_uflags = uflags; 296*0daf62d9SStanislav Sedov entry->fs_fd = fd; 297*0daf62d9SStanislav Sedov entry->fs_type = type; 298*0daf62d9SStanislav Sedov entry->fs_ref_count = refcount; 299*0daf62d9SStanislav Sedov entry->fs_offset = offset; 300*0daf62d9SStanislav Sedov entry->fs_path = path; 301*0daf62d9SStanislav Sedov return (entry); 302*0daf62d9SStanislav Sedov } 303*0daf62d9SStanislav Sedov 304*0daf62d9SStanislav Sedov static struct vnode * 305*0daf62d9SStanislav Sedov getctty(kvm_t *kd, struct kinfo_proc *kp) 306*0daf62d9SStanislav Sedov { 307*0daf62d9SStanislav Sedov struct pgrp pgrp; 308*0daf62d9SStanislav Sedov struct proc proc; 309*0daf62d9SStanislav Sedov struct session sess; 310*0daf62d9SStanislav Sedov int error; 311*0daf62d9SStanislav Sedov 312*0daf62d9SStanislav Sedov assert(kp); 313*0daf62d9SStanislav Sedov error = kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc, 314*0daf62d9SStanislav Sedov sizeof(proc)); 315*0daf62d9SStanislav Sedov if (error == 0) { 316*0daf62d9SStanislav Sedov warnx("can't read proc struct at %p for pid %d", 317*0daf62d9SStanislav Sedov kp->ki_paddr, kp->ki_pid); 318*0daf62d9SStanislav Sedov return (NULL); 319*0daf62d9SStanislav Sedov } 320*0daf62d9SStanislav Sedov if (proc.p_pgrp == NULL) 321*0daf62d9SStanislav Sedov return (NULL); 322*0daf62d9SStanislav Sedov error = kvm_read_all(kd, (unsigned long)proc.p_pgrp, &pgrp, 323*0daf62d9SStanislav Sedov sizeof(pgrp)); 324*0daf62d9SStanislav Sedov if (error == 0) { 325*0daf62d9SStanislav Sedov warnx("can't read pgrp struct at %p for pid %d", 326*0daf62d9SStanislav Sedov proc.p_pgrp, kp->ki_pid); 327*0daf62d9SStanislav Sedov return (NULL); 328*0daf62d9SStanislav Sedov } 329*0daf62d9SStanislav Sedov error = kvm_read_all(kd, (unsigned long)pgrp.pg_session, &sess, 330*0daf62d9SStanislav Sedov sizeof(sess)); 331*0daf62d9SStanislav Sedov if (error == 0) { 332*0daf62d9SStanislav Sedov warnx("can't read session struct at %p for pid %d", 333*0daf62d9SStanislav Sedov pgrp.pg_session, kp->ki_pid); 334*0daf62d9SStanislav Sedov return (NULL); 335*0daf62d9SStanislav Sedov } 336*0daf62d9SStanislav Sedov return (sess.s_ttyvp); 337*0daf62d9SStanislav Sedov } 338*0daf62d9SStanislav Sedov 339*0daf62d9SStanislav Sedov static struct filestat_list * 340*0daf62d9SStanislav Sedov procstat_getfiles_kvm(struct procstat *procstat, struct kinfo_proc *kp, int mmapped) 341*0daf62d9SStanislav Sedov { 342*0daf62d9SStanislav Sedov struct file file; 343*0daf62d9SStanislav Sedov struct filedesc filed; 344*0daf62d9SStanislav Sedov struct vm_map_entry vmentry; 345*0daf62d9SStanislav Sedov struct vm_object object; 346*0daf62d9SStanislav Sedov struct vmspace vmspace; 347*0daf62d9SStanislav Sedov vm_map_entry_t entryp; 348*0daf62d9SStanislav Sedov vm_map_t map; 349*0daf62d9SStanislav Sedov vm_object_t objp; 350*0daf62d9SStanislav Sedov struct vnode *vp; 351*0daf62d9SStanislav Sedov struct file **ofiles; 352*0daf62d9SStanislav Sedov struct filestat *entry; 353*0daf62d9SStanislav Sedov struct filestat_list *head; 354*0daf62d9SStanislav Sedov kvm_t *kd; 355*0daf62d9SStanislav Sedov void *data; 356*0daf62d9SStanislav Sedov int i, fflags; 357*0daf62d9SStanislav Sedov int prot, type; 358*0daf62d9SStanislav Sedov unsigned int nfiles; 359*0daf62d9SStanislav Sedov 360*0daf62d9SStanislav Sedov assert(procstat); 361*0daf62d9SStanislav Sedov kd = procstat->kd; 362*0daf62d9SStanislav Sedov if (kd == NULL) 363*0daf62d9SStanislav Sedov return (NULL); 364*0daf62d9SStanislav Sedov if (kp->ki_fd == NULL) 365*0daf62d9SStanislav Sedov return (NULL); 366*0daf62d9SStanislav Sedov if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &filed, 367*0daf62d9SStanislav Sedov sizeof(filed))) { 368*0daf62d9SStanislav Sedov warnx("can't read filedesc at %p", (void *)kp->ki_fd); 369*0daf62d9SStanislav Sedov return (NULL); 370*0daf62d9SStanislav Sedov } 371*0daf62d9SStanislav Sedov 372*0daf62d9SStanislav Sedov /* 373*0daf62d9SStanislav Sedov * Allocate list head. 374*0daf62d9SStanislav Sedov */ 375*0daf62d9SStanislav Sedov head = malloc(sizeof(*head)); 376*0daf62d9SStanislav Sedov if (head == NULL) 377*0daf62d9SStanislav Sedov return (NULL); 378*0daf62d9SStanislav Sedov STAILQ_INIT(head); 379*0daf62d9SStanislav Sedov 380*0daf62d9SStanislav Sedov /* root directory vnode, if one. */ 381*0daf62d9SStanislav Sedov if (filed.fd_rdir) { 382*0daf62d9SStanislav Sedov entry = filestat_new_entry(filed.fd_rdir, PS_FST_TYPE_VNODE, -1, 383*0daf62d9SStanislav Sedov PS_FST_FFLAG_READ, PS_FST_UFLAG_RDIR, 0, 0, NULL); 384*0daf62d9SStanislav Sedov if (entry != NULL) 385*0daf62d9SStanislav Sedov STAILQ_INSERT_TAIL(head, entry, next); 386*0daf62d9SStanislav Sedov } 387*0daf62d9SStanislav Sedov /* current working directory vnode. */ 388*0daf62d9SStanislav Sedov if (filed.fd_cdir) { 389*0daf62d9SStanislav Sedov entry = filestat_new_entry(filed.fd_cdir, PS_FST_TYPE_VNODE, -1, 390*0daf62d9SStanislav Sedov PS_FST_FFLAG_READ, PS_FST_UFLAG_CDIR, 0, 0, NULL); 391*0daf62d9SStanislav Sedov if (entry != NULL) 392*0daf62d9SStanislav Sedov STAILQ_INSERT_TAIL(head, entry, next); 393*0daf62d9SStanislav Sedov } 394*0daf62d9SStanislav Sedov /* jail root, if any. */ 395*0daf62d9SStanislav Sedov if (filed.fd_jdir) { 396*0daf62d9SStanislav Sedov entry = filestat_new_entry(filed.fd_jdir, PS_FST_TYPE_VNODE, -1, 397*0daf62d9SStanislav Sedov PS_FST_FFLAG_READ, PS_FST_UFLAG_JAIL, 0, 0, NULL); 398*0daf62d9SStanislav Sedov if (entry != NULL) 399*0daf62d9SStanislav Sedov STAILQ_INSERT_TAIL(head, entry, next); 400*0daf62d9SStanislav Sedov } 401*0daf62d9SStanislav Sedov /* ktrace vnode, if one */ 402*0daf62d9SStanislav Sedov if (kp->ki_tracep) { 403*0daf62d9SStanislav Sedov entry = filestat_new_entry(kp->ki_tracep, PS_FST_TYPE_VNODE, -1, 404*0daf62d9SStanislav Sedov PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE, 405*0daf62d9SStanislav Sedov PS_FST_UFLAG_TRACE, 0, 0, NULL); 406*0daf62d9SStanislav Sedov if (entry != NULL) 407*0daf62d9SStanislav Sedov STAILQ_INSERT_TAIL(head, entry, next); 408*0daf62d9SStanislav Sedov } 409*0daf62d9SStanislav Sedov /* text vnode, if one */ 410*0daf62d9SStanislav Sedov if (kp->ki_textvp) { 411*0daf62d9SStanislav Sedov entry = filestat_new_entry(kp->ki_textvp, PS_FST_TYPE_VNODE, -1, 412*0daf62d9SStanislav Sedov PS_FST_FFLAG_READ, PS_FST_UFLAG_TEXT, 0, 0, NULL); 413*0daf62d9SStanislav Sedov if (entry != NULL) 414*0daf62d9SStanislav Sedov STAILQ_INSERT_TAIL(head, entry, next); 415*0daf62d9SStanislav Sedov } 416*0daf62d9SStanislav Sedov /* Controlling terminal. */ 417*0daf62d9SStanislav Sedov if ((vp = getctty(kd, kp)) != NULL) { 418*0daf62d9SStanislav Sedov entry = filestat_new_entry(vp, PS_FST_TYPE_VNODE, -1, 419*0daf62d9SStanislav Sedov PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE, 420*0daf62d9SStanislav Sedov PS_FST_UFLAG_CTTY, 0, 0, NULL); 421*0daf62d9SStanislav Sedov if (entry != NULL) 422*0daf62d9SStanislav Sedov STAILQ_INSERT_TAIL(head, entry, next); 423*0daf62d9SStanislav Sedov } 424*0daf62d9SStanislav Sedov 425*0daf62d9SStanislav Sedov nfiles = filed.fd_lastfile + 1; 426*0daf62d9SStanislav Sedov ofiles = malloc(nfiles * sizeof(struct file *)); 427*0daf62d9SStanislav Sedov if (ofiles == NULL) { 428*0daf62d9SStanislav Sedov warn("malloc(%zd)", nfiles * sizeof(struct file *)); 429*0daf62d9SStanislav Sedov goto do_mmapped; 430*0daf62d9SStanislav Sedov } 431*0daf62d9SStanislav Sedov if (!kvm_read_all(kd, (unsigned long)filed.fd_ofiles, ofiles, 432*0daf62d9SStanislav Sedov nfiles * sizeof(struct file *))) { 433*0daf62d9SStanislav Sedov warnx("cannot read file structures at %p", 434*0daf62d9SStanislav Sedov (void *)filed.fd_ofiles); 435*0daf62d9SStanislav Sedov free(ofiles); 436*0daf62d9SStanislav Sedov goto do_mmapped; 437*0daf62d9SStanislav Sedov } 438*0daf62d9SStanislav Sedov for (i = 0; i <= filed.fd_lastfile; i++) { 439*0daf62d9SStanislav Sedov if (ofiles[i] == NULL) 440*0daf62d9SStanislav Sedov continue; 441*0daf62d9SStanislav Sedov if (!kvm_read_all(kd, (unsigned long)ofiles[i], &file, 442*0daf62d9SStanislav Sedov sizeof(struct file))) { 443*0daf62d9SStanislav Sedov warnx("can't read file %d at %p", i, 444*0daf62d9SStanislav Sedov (void *)ofiles[i]); 445*0daf62d9SStanislav Sedov continue; 446*0daf62d9SStanislav Sedov } 447*0daf62d9SStanislav Sedov switch (file.f_type) { 448*0daf62d9SStanislav Sedov case DTYPE_VNODE: 449*0daf62d9SStanislav Sedov type = PS_FST_TYPE_VNODE; 450*0daf62d9SStanislav Sedov data = file.f_vnode; 451*0daf62d9SStanislav Sedov break; 452*0daf62d9SStanislav Sedov case DTYPE_SOCKET: 453*0daf62d9SStanislav Sedov type = PS_FST_TYPE_SOCKET; 454*0daf62d9SStanislav Sedov data = file.f_data; 455*0daf62d9SStanislav Sedov break; 456*0daf62d9SStanislav Sedov case DTYPE_PIPE: 457*0daf62d9SStanislav Sedov type = PS_FST_TYPE_PIPE; 458*0daf62d9SStanislav Sedov data = file.f_data; 459*0daf62d9SStanislav Sedov break; 460*0daf62d9SStanislav Sedov case DTYPE_FIFO: 461*0daf62d9SStanislav Sedov type = PS_FST_TYPE_FIFO; 462*0daf62d9SStanislav Sedov data = file.f_vnode; 463*0daf62d9SStanislav Sedov break; 464*0daf62d9SStanislav Sedov #ifdef DTYPE_PTS 465*0daf62d9SStanislav Sedov case DTYPE_PTS: 466*0daf62d9SStanislav Sedov type = PS_FST_TYPE_PTS; 467*0daf62d9SStanislav Sedov data = file.f_data; 468*0daf62d9SStanislav Sedov break; 469*0daf62d9SStanislav Sedov #endif 470*0daf62d9SStanislav Sedov default: 471*0daf62d9SStanislav Sedov continue; 472*0daf62d9SStanislav Sedov } 473*0daf62d9SStanislav Sedov entry = filestat_new_entry(data, type, i, 474*0daf62d9SStanislav Sedov to_filestat_flags(file.f_flag), 0, 0, 0, NULL); 475*0daf62d9SStanislav Sedov if (entry != NULL) 476*0daf62d9SStanislav Sedov STAILQ_INSERT_TAIL(head, entry, next); 477*0daf62d9SStanislav Sedov } 478*0daf62d9SStanislav Sedov free(ofiles); 479*0daf62d9SStanislav Sedov 480*0daf62d9SStanislav Sedov do_mmapped: 481*0daf62d9SStanislav Sedov 482*0daf62d9SStanislav Sedov /* 483*0daf62d9SStanislav Sedov * Process mmapped files if requested. 484*0daf62d9SStanislav Sedov */ 485*0daf62d9SStanislav Sedov if (mmapped) { 486*0daf62d9SStanislav Sedov if (!kvm_read_all(kd, (unsigned long)kp->ki_vmspace, &vmspace, 487*0daf62d9SStanislav Sedov sizeof(vmspace))) { 488*0daf62d9SStanislav Sedov warnx("can't read vmspace at %p", 489*0daf62d9SStanislav Sedov (void *)kp->ki_vmspace); 490*0daf62d9SStanislav Sedov goto exit; 491*0daf62d9SStanislav Sedov } 492*0daf62d9SStanislav Sedov map = &vmspace.vm_map; 493*0daf62d9SStanislav Sedov 494*0daf62d9SStanislav Sedov for (entryp = map->header.next; 495*0daf62d9SStanislav Sedov entryp != &kp->ki_vmspace->vm_map.header; 496*0daf62d9SStanislav Sedov entryp = vmentry.next) { 497*0daf62d9SStanislav Sedov if (!kvm_read_all(kd, (unsigned long)entryp, &vmentry, 498*0daf62d9SStanislav Sedov sizeof(vmentry))) { 499*0daf62d9SStanislav Sedov warnx("can't read vm_map_entry at %p", 500*0daf62d9SStanislav Sedov (void *)entryp); 501*0daf62d9SStanislav Sedov continue; 502*0daf62d9SStanislav Sedov } 503*0daf62d9SStanislav Sedov if (vmentry.eflags & MAP_ENTRY_IS_SUB_MAP) 504*0daf62d9SStanislav Sedov continue; 505*0daf62d9SStanislav Sedov if ((objp = vmentry.object.vm_object) == NULL) 506*0daf62d9SStanislav Sedov continue; 507*0daf62d9SStanislav Sedov for (; objp; objp = object.backing_object) { 508*0daf62d9SStanislav Sedov if (!kvm_read_all(kd, (unsigned long)objp, 509*0daf62d9SStanislav Sedov &object, sizeof(object))) { 510*0daf62d9SStanislav Sedov warnx("can't read vm_object at %p", 511*0daf62d9SStanislav Sedov (void *)objp); 512*0daf62d9SStanislav Sedov break; 513*0daf62d9SStanislav Sedov } 514*0daf62d9SStanislav Sedov } 515*0daf62d9SStanislav Sedov 516*0daf62d9SStanislav Sedov /* We want only vnode objects. */ 517*0daf62d9SStanislav Sedov if (object.type != OBJT_VNODE) 518*0daf62d9SStanislav Sedov continue; 519*0daf62d9SStanislav Sedov 520*0daf62d9SStanislav Sedov prot = vmentry.protection; 521*0daf62d9SStanislav Sedov fflags = 0; 522*0daf62d9SStanislav Sedov if (prot & VM_PROT_READ) 523*0daf62d9SStanislav Sedov fflags = PS_FST_FFLAG_READ; 524*0daf62d9SStanislav Sedov if (prot & VM_PROT_WRITE) 525*0daf62d9SStanislav Sedov fflags |= PS_FST_FFLAG_WRITE; 526*0daf62d9SStanislav Sedov 527*0daf62d9SStanislav Sedov /* 528*0daf62d9SStanislav Sedov * Create filestat entry. 529*0daf62d9SStanislav Sedov */ 530*0daf62d9SStanislav Sedov entry = filestat_new_entry(object.handle, 531*0daf62d9SStanislav Sedov PS_FST_TYPE_VNODE, -1, fflags, 532*0daf62d9SStanislav Sedov PS_FST_UFLAG_MMAP, 0, 0, NULL); 533*0daf62d9SStanislav Sedov if (entry != NULL) 534*0daf62d9SStanislav Sedov STAILQ_INSERT_TAIL(head, entry, next); 535*0daf62d9SStanislav Sedov } 536*0daf62d9SStanislav Sedov } 537*0daf62d9SStanislav Sedov exit: 538*0daf62d9SStanislav Sedov return (head); 539*0daf62d9SStanislav Sedov } 540*0daf62d9SStanislav Sedov 541*0daf62d9SStanislav Sedov /* 542*0daf62d9SStanislav Sedov * kinfo types to filestat translation. 543*0daf62d9SStanislav Sedov */ 544*0daf62d9SStanislav Sedov static int 545*0daf62d9SStanislav Sedov kinfo_type2fst(int kftype) 546*0daf62d9SStanislav Sedov { 547*0daf62d9SStanislav Sedov static struct { 548*0daf62d9SStanislav Sedov int kf_type; 549*0daf62d9SStanislav Sedov int fst_type; 550*0daf62d9SStanislav Sedov } kftypes2fst[] = { 551*0daf62d9SStanislav Sedov { KF_TYPE_CRYPTO, PS_FST_TYPE_CRYPTO }, 552*0daf62d9SStanislav Sedov { KF_TYPE_FIFO, PS_FST_TYPE_FIFO }, 553*0daf62d9SStanislav Sedov { KF_TYPE_KQUEUE, PS_FST_TYPE_KQUEUE }, 554*0daf62d9SStanislav Sedov { KF_TYPE_MQUEUE, PS_FST_TYPE_MQUEUE }, 555*0daf62d9SStanislav Sedov { KF_TYPE_NONE, PS_FST_TYPE_NONE }, 556*0daf62d9SStanislav Sedov { KF_TYPE_PIPE, PS_FST_TYPE_PIPE }, 557*0daf62d9SStanislav Sedov { KF_TYPE_PTS, PS_FST_TYPE_PTS }, 558*0daf62d9SStanislav Sedov { KF_TYPE_SEM, PS_FST_TYPE_SEM }, 559*0daf62d9SStanislav Sedov { KF_TYPE_SHM, PS_FST_TYPE_SHM }, 560*0daf62d9SStanislav Sedov { KF_TYPE_SOCKET, PS_FST_TYPE_SOCKET }, 561*0daf62d9SStanislav Sedov { KF_TYPE_VNODE, PS_FST_TYPE_VNODE }, 562*0daf62d9SStanislav Sedov { KF_TYPE_UNKNOWN, PS_FST_TYPE_UNKNOWN } 563*0daf62d9SStanislav Sedov }; 564*0daf62d9SStanislav Sedov #define NKFTYPES (sizeof(kftypes2fst) / sizeof(*kftypes2fst)) 565*0daf62d9SStanislav Sedov unsigned int i; 566*0daf62d9SStanislav Sedov 567*0daf62d9SStanislav Sedov for (i = 0; i < NKFTYPES; i++) 568*0daf62d9SStanislav Sedov if (kftypes2fst[i].kf_type == kftype) 569*0daf62d9SStanislav Sedov break; 570*0daf62d9SStanislav Sedov if (i == NKFTYPES) 571*0daf62d9SStanislav Sedov return (PS_FST_TYPE_UNKNOWN); 572*0daf62d9SStanislav Sedov return (kftypes2fst[i].fst_type); 573*0daf62d9SStanislav Sedov } 574*0daf62d9SStanislav Sedov 575*0daf62d9SStanislav Sedov /* 576*0daf62d9SStanislav Sedov * kinfo flags to filestat translation. 577*0daf62d9SStanislav Sedov */ 578*0daf62d9SStanislav Sedov static int 579*0daf62d9SStanislav Sedov kinfo_fflags2fst(int kfflags) 580*0daf62d9SStanislav Sedov { 581*0daf62d9SStanislav Sedov static struct { 582*0daf62d9SStanislav Sedov int kf_flag; 583*0daf62d9SStanislav Sedov int fst_flag; 584*0daf62d9SStanislav Sedov } kfflags2fst[] = { 585*0daf62d9SStanislav Sedov { KF_FLAG_APPEND, PS_FST_FFLAG_APPEND }, 586*0daf62d9SStanislav Sedov { KF_FLAG_ASYNC, PS_FST_FFLAG_ASYNC }, 587*0daf62d9SStanislav Sedov { KF_FLAG_CREAT, PS_FST_FFLAG_CREAT }, 588*0daf62d9SStanislav Sedov { KF_FLAG_DIRECT, PS_FST_FFLAG_DIRECT }, 589*0daf62d9SStanislav Sedov { KF_FLAG_EXCL, PS_FST_FFLAG_EXCL }, 590*0daf62d9SStanislav Sedov { KF_FLAG_EXEC, PS_FST_FFLAG_EXEC }, 591*0daf62d9SStanislav Sedov { KF_FLAG_EXLOCK, PS_FST_FFLAG_EXLOCK }, 592*0daf62d9SStanislav Sedov { KF_FLAG_FSYNC, PS_FST_FFLAG_SYNC }, 593*0daf62d9SStanislav Sedov { KF_FLAG_HASLOCK, PS_FST_FFLAG_HASLOCK }, 594*0daf62d9SStanislav Sedov { KF_FLAG_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW }, 595*0daf62d9SStanislav Sedov { KF_FLAG_NONBLOCK, PS_FST_FFLAG_NONBLOCK }, 596*0daf62d9SStanislav Sedov { KF_FLAG_READ, PS_FST_FFLAG_READ }, 597*0daf62d9SStanislav Sedov { KF_FLAG_SHLOCK, PS_FST_FFLAG_SHLOCK }, 598*0daf62d9SStanislav Sedov { KF_FLAG_TRUNC, PS_FST_FFLAG_TRUNC }, 599*0daf62d9SStanislav Sedov { KF_FLAG_WRITE, PS_FST_FFLAG_WRITE } 600*0daf62d9SStanislav Sedov }; 601*0daf62d9SStanislav Sedov #define NKFFLAGS (sizeof(kfflags2fst) / sizeof(*kfflags2fst)) 602*0daf62d9SStanislav Sedov unsigned int i; 603*0daf62d9SStanislav Sedov int flags; 604*0daf62d9SStanislav Sedov 605*0daf62d9SStanislav Sedov flags = 0; 606*0daf62d9SStanislav Sedov for (i = 0; i < NKFFLAGS; i++) 607*0daf62d9SStanislav Sedov if ((kfflags & kfflags2fst[i].kf_flag) != 0) 608*0daf62d9SStanislav Sedov flags |= kfflags2fst[i].fst_flag; 609*0daf62d9SStanislav Sedov return (flags); 610*0daf62d9SStanislav Sedov } 611*0daf62d9SStanislav Sedov 612*0daf62d9SStanislav Sedov static int 613*0daf62d9SStanislav Sedov kinfo_uflags2fst(int fd) 614*0daf62d9SStanislav Sedov { 615*0daf62d9SStanislav Sedov 616*0daf62d9SStanislav Sedov switch (fd) { 617*0daf62d9SStanislav Sedov case KF_FD_TYPE_CTTY: 618*0daf62d9SStanislav Sedov return (PS_FST_UFLAG_CTTY); 619*0daf62d9SStanislav Sedov case KF_FD_TYPE_CWD: 620*0daf62d9SStanislav Sedov return (PS_FST_UFLAG_CDIR); 621*0daf62d9SStanislav Sedov case KF_FD_TYPE_JAIL: 622*0daf62d9SStanislav Sedov return (PS_FST_UFLAG_JAIL); 623*0daf62d9SStanislav Sedov case KF_FD_TYPE_TEXT: 624*0daf62d9SStanislav Sedov return (PS_FST_UFLAG_TEXT); 625*0daf62d9SStanislav Sedov case KF_FD_TYPE_TRACE: 626*0daf62d9SStanislav Sedov return (PS_FST_UFLAG_TRACE); 627*0daf62d9SStanislav Sedov case KF_FD_TYPE_ROOT: 628*0daf62d9SStanislav Sedov return (PS_FST_UFLAG_RDIR); 629*0daf62d9SStanislav Sedov } 630*0daf62d9SStanislav Sedov return (0); 631*0daf62d9SStanislav Sedov } 632*0daf62d9SStanislav Sedov 633*0daf62d9SStanislav Sedov static struct filestat_list * 634*0daf62d9SStanislav Sedov procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp, int mmapped) 635*0daf62d9SStanislav Sedov { 636*0daf62d9SStanislav Sedov struct kinfo_file *kif, *files; 637*0daf62d9SStanislav Sedov struct kinfo_vmentry *kve, *vmentries; 638*0daf62d9SStanislav Sedov struct filestat_list *head; 639*0daf62d9SStanislav Sedov struct filestat *entry; 640*0daf62d9SStanislav Sedov char *path; 641*0daf62d9SStanislav Sedov off_t offset; 642*0daf62d9SStanislav Sedov int cnt, fd, fflags; 643*0daf62d9SStanislav Sedov int i, type, uflags; 644*0daf62d9SStanislav Sedov int refcount; 645*0daf62d9SStanislav Sedov 646*0daf62d9SStanislav Sedov assert(kp); 647*0daf62d9SStanislav Sedov if (kp->ki_fd == NULL) 648*0daf62d9SStanislav Sedov return (NULL); 649*0daf62d9SStanislav Sedov 650*0daf62d9SStanislav Sedov files = kinfo_getfile(kp->ki_pid, &cnt); 651*0daf62d9SStanislav Sedov if (files == NULL && errno != EPERM) { 652*0daf62d9SStanislav Sedov warn("kinfo_getfile()"); 653*0daf62d9SStanislav Sedov return (NULL); 654*0daf62d9SStanislav Sedov } 655*0daf62d9SStanislav Sedov procstat->files = files; 656*0daf62d9SStanislav Sedov 657*0daf62d9SStanislav Sedov /* 658*0daf62d9SStanislav Sedov * Allocate list head. 659*0daf62d9SStanislav Sedov */ 660*0daf62d9SStanislav Sedov head = malloc(sizeof(*head)); 661*0daf62d9SStanislav Sedov if (head == NULL) 662*0daf62d9SStanislav Sedov return (NULL); 663*0daf62d9SStanislav Sedov STAILQ_INIT(head); 664*0daf62d9SStanislav Sedov for (i = 0; i < cnt; i++) { 665*0daf62d9SStanislav Sedov kif = &files[i]; 666*0daf62d9SStanislav Sedov 667*0daf62d9SStanislav Sedov type = kinfo_type2fst(kif->kf_type); 668*0daf62d9SStanislav Sedov fd = kif->kf_fd >= 0 ? kif->kf_fd : -1; 669*0daf62d9SStanislav Sedov fflags = kinfo_fflags2fst(kif->kf_flags); 670*0daf62d9SStanislav Sedov uflags = kinfo_uflags2fst(kif->kf_fd); 671*0daf62d9SStanislav Sedov refcount = kif->kf_ref_count; 672*0daf62d9SStanislav Sedov offset = kif->kf_offset; 673*0daf62d9SStanislav Sedov if (*kif->kf_path != '\0') 674*0daf62d9SStanislav Sedov path = strdup(kif->kf_path); 675*0daf62d9SStanislav Sedov else 676*0daf62d9SStanislav Sedov path = NULL; 677*0daf62d9SStanislav Sedov 678*0daf62d9SStanislav Sedov /* 679*0daf62d9SStanislav Sedov * Create filestat entry. 680*0daf62d9SStanislav Sedov */ 681*0daf62d9SStanislav Sedov entry = filestat_new_entry(kif, type, fd, fflags, uflags, 682*0daf62d9SStanislav Sedov refcount, offset, path); 683*0daf62d9SStanislav Sedov if (entry != NULL) 684*0daf62d9SStanislav Sedov STAILQ_INSERT_TAIL(head, entry, next); 685*0daf62d9SStanislav Sedov } 686*0daf62d9SStanislav Sedov if (mmapped != 0) { 687*0daf62d9SStanislav Sedov vmentries = kinfo_getvmmap(kp->ki_pid, &cnt); 688*0daf62d9SStanislav Sedov procstat->vmentries = vmentries; 689*0daf62d9SStanislav Sedov if (vmentries == NULL || cnt == 0) 690*0daf62d9SStanislav Sedov goto fail; 691*0daf62d9SStanislav Sedov for (i = 0; i < cnt; i++) { 692*0daf62d9SStanislav Sedov kve = &vmentries[i]; 693*0daf62d9SStanislav Sedov if (kve->kve_type != KVME_TYPE_VNODE) 694*0daf62d9SStanislav Sedov continue; 695*0daf62d9SStanislav Sedov fflags = 0; 696*0daf62d9SStanislav Sedov if (kve->kve_protection & KVME_PROT_READ) 697*0daf62d9SStanislav Sedov fflags = PS_FST_FFLAG_READ; 698*0daf62d9SStanislav Sedov if (kve->kve_protection & KVME_PROT_WRITE) 699*0daf62d9SStanislav Sedov fflags |= PS_FST_FFLAG_WRITE; 700*0daf62d9SStanislav Sedov offset = kve->kve_offset; 701*0daf62d9SStanislav Sedov refcount = kve->kve_ref_count; 702*0daf62d9SStanislav Sedov if (*kve->kve_path != '\0') 703*0daf62d9SStanislav Sedov path = strdup(kve->kve_path); 704*0daf62d9SStanislav Sedov else 705*0daf62d9SStanislav Sedov path = NULL; 706*0daf62d9SStanislav Sedov entry = filestat_new_entry(kve, PS_FST_TYPE_VNODE, -1, 707*0daf62d9SStanislav Sedov fflags, PS_FST_UFLAG_MMAP, refcount, offset, path); 708*0daf62d9SStanislav Sedov if (entry != NULL) 709*0daf62d9SStanislav Sedov STAILQ_INSERT_TAIL(head, entry, next); 710*0daf62d9SStanislav Sedov } 711*0daf62d9SStanislav Sedov } 712*0daf62d9SStanislav Sedov fail: 713*0daf62d9SStanislav Sedov return (head); 714*0daf62d9SStanislav Sedov } 715*0daf62d9SStanislav Sedov 716*0daf62d9SStanislav Sedov int 717*0daf62d9SStanislav Sedov procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst, 718*0daf62d9SStanislav Sedov struct pipestat *ps, char *errbuf) 719*0daf62d9SStanislav Sedov { 720*0daf62d9SStanislav Sedov 721*0daf62d9SStanislav Sedov assert(ps); 722*0daf62d9SStanislav Sedov if (procstat->type == PROCSTAT_KVM) { 723*0daf62d9SStanislav Sedov return (procstat_get_pipe_info_kvm(procstat->kd, fst, ps, 724*0daf62d9SStanislav Sedov errbuf)); 725*0daf62d9SStanislav Sedov } else if (procstat->type == PROCSTAT_SYSCTL) { 726*0daf62d9SStanislav Sedov return (procstat_get_pipe_info_sysctl(fst, ps, errbuf)); 727*0daf62d9SStanislav Sedov } else { 728*0daf62d9SStanislav Sedov warnx("unknow access method: %d", procstat->type); 729*0daf62d9SStanislav Sedov snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 730*0daf62d9SStanislav Sedov return (1); 731*0daf62d9SStanislav Sedov } 732*0daf62d9SStanislav Sedov } 733*0daf62d9SStanislav Sedov 734*0daf62d9SStanislav Sedov static int 735*0daf62d9SStanislav Sedov procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst, 736*0daf62d9SStanislav Sedov struct pipestat *ps, char *errbuf) 737*0daf62d9SStanislav Sedov { 738*0daf62d9SStanislav Sedov struct pipe pi; 739*0daf62d9SStanislav Sedov void *pipep; 740*0daf62d9SStanislav Sedov 741*0daf62d9SStanislav Sedov assert(kd); 742*0daf62d9SStanislav Sedov assert(ps); 743*0daf62d9SStanislav Sedov assert(fst); 744*0daf62d9SStanislav Sedov bzero(ps, sizeof(*ps)); 745*0daf62d9SStanislav Sedov pipep = fst->fs_typedep; 746*0daf62d9SStanislav Sedov if (pipep == NULL) 747*0daf62d9SStanislav Sedov goto fail; 748*0daf62d9SStanislav Sedov if (!kvm_read_all(kd, (unsigned long)pipep, &pi, sizeof(struct pipe))) { 749*0daf62d9SStanislav Sedov warnx("can't read pipe at %p", (void *)pipep); 750*0daf62d9SStanislav Sedov goto fail; 751*0daf62d9SStanislav Sedov } 752*0daf62d9SStanislav Sedov ps->addr = (uintptr_t)pipep; 753*0daf62d9SStanislav Sedov ps->peer = (uintptr_t)pi.pipe_peer; 754*0daf62d9SStanislav Sedov ps->buffer_cnt = pi.pipe_buffer.cnt; 755*0daf62d9SStanislav Sedov return (0); 756*0daf62d9SStanislav Sedov 757*0daf62d9SStanislav Sedov fail: 758*0daf62d9SStanislav Sedov snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 759*0daf62d9SStanislav Sedov return (1); 760*0daf62d9SStanislav Sedov } 761*0daf62d9SStanislav Sedov 762*0daf62d9SStanislav Sedov static int 763*0daf62d9SStanislav Sedov procstat_get_pipe_info_sysctl(struct filestat *fst, struct pipestat *ps, 764*0daf62d9SStanislav Sedov char *errbuf __unused) 765*0daf62d9SStanislav Sedov { 766*0daf62d9SStanislav Sedov struct kinfo_file *kif; 767*0daf62d9SStanislav Sedov 768*0daf62d9SStanislav Sedov assert(ps); 769*0daf62d9SStanislav Sedov assert(fst); 770*0daf62d9SStanislav Sedov bzero(ps, sizeof(*ps)); 771*0daf62d9SStanislav Sedov kif = fst->fs_typedep; 772*0daf62d9SStanislav Sedov if (kif == NULL) 773*0daf62d9SStanislav Sedov return (1); 774*0daf62d9SStanislav Sedov ps->addr = kif->kf_un.kf_pipe.kf_pipe_addr; 775*0daf62d9SStanislav Sedov ps->peer = kif->kf_un.kf_pipe.kf_pipe_peer; 776*0daf62d9SStanislav Sedov ps->buffer_cnt = kif->kf_un.kf_pipe.kf_pipe_buffer_cnt; 777*0daf62d9SStanislav Sedov return (0); 778*0daf62d9SStanislav Sedov } 779*0daf62d9SStanislav Sedov 780*0daf62d9SStanislav Sedov int 781*0daf62d9SStanislav Sedov procstat_get_pts_info(struct procstat *procstat, struct filestat *fst, 782*0daf62d9SStanislav Sedov struct ptsstat *pts, char *errbuf) 783*0daf62d9SStanislav Sedov { 784*0daf62d9SStanislav Sedov 785*0daf62d9SStanislav Sedov assert(pts); 786*0daf62d9SStanislav Sedov if (procstat->type == PROCSTAT_KVM) { 787*0daf62d9SStanislav Sedov return (procstat_get_pts_info_kvm(procstat->kd, fst, pts, 788*0daf62d9SStanislav Sedov errbuf)); 789*0daf62d9SStanislav Sedov } else if (procstat->type == PROCSTAT_SYSCTL) { 790*0daf62d9SStanislav Sedov return (procstat_get_pts_info_sysctl(fst, pts, errbuf)); 791*0daf62d9SStanislav Sedov } else { 792*0daf62d9SStanislav Sedov warnx("unknow access method: %d", procstat->type); 793*0daf62d9SStanislav Sedov snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 794*0daf62d9SStanislav Sedov return (1); 795*0daf62d9SStanislav Sedov } 796*0daf62d9SStanislav Sedov } 797*0daf62d9SStanislav Sedov 798*0daf62d9SStanislav Sedov static int 799*0daf62d9SStanislav Sedov procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst, 800*0daf62d9SStanislav Sedov struct ptsstat *pts, char *errbuf) 801*0daf62d9SStanislav Sedov { 802*0daf62d9SStanislav Sedov struct tty tty; 803*0daf62d9SStanislav Sedov void *ttyp; 804*0daf62d9SStanislav Sedov 805*0daf62d9SStanislav Sedov assert(kd); 806*0daf62d9SStanislav Sedov assert(pts); 807*0daf62d9SStanislav Sedov assert(fst); 808*0daf62d9SStanislav Sedov bzero(pts, sizeof(*pts)); 809*0daf62d9SStanislav Sedov ttyp = fst->fs_typedep; 810*0daf62d9SStanislav Sedov if (ttyp == NULL) 811*0daf62d9SStanislav Sedov goto fail; 812*0daf62d9SStanislav Sedov if (!kvm_read_all(kd, (unsigned long)ttyp, &tty, sizeof(struct tty))) { 813*0daf62d9SStanislav Sedov warnx("can't read tty at %p", (void *)ttyp); 814*0daf62d9SStanislav Sedov goto fail; 815*0daf62d9SStanislav Sedov } 816*0daf62d9SStanislav Sedov pts->dev = dev2udev(kd, tty.t_dev); 817*0daf62d9SStanislav Sedov (void)kdevtoname(kd, tty.t_dev, pts->devname); 818*0daf62d9SStanislav Sedov return (0); 819*0daf62d9SStanislav Sedov 820*0daf62d9SStanislav Sedov fail: 821*0daf62d9SStanislav Sedov snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 822*0daf62d9SStanislav Sedov return (1); 823*0daf62d9SStanislav Sedov } 824*0daf62d9SStanislav Sedov 825*0daf62d9SStanislav Sedov static int 826*0daf62d9SStanislav Sedov procstat_get_pts_info_sysctl(struct filestat *fst, struct ptsstat *pts, 827*0daf62d9SStanislav Sedov char *errbuf __unused) 828*0daf62d9SStanislav Sedov { 829*0daf62d9SStanislav Sedov struct kinfo_file *kif; 830*0daf62d9SStanislav Sedov 831*0daf62d9SStanislav Sedov assert(pts); 832*0daf62d9SStanislav Sedov assert(fst); 833*0daf62d9SStanislav Sedov bzero(pts, sizeof(*pts)); 834*0daf62d9SStanislav Sedov kif = fst->fs_typedep; 835*0daf62d9SStanislav Sedov if (kif == NULL) 836*0daf62d9SStanislav Sedov return (0); 837*0daf62d9SStanislav Sedov pts->dev = kif->kf_un.kf_pts.kf_pts_dev; 838*0daf62d9SStanislav Sedov strlcpy(pts->devname, kif->kf_path, sizeof(pts->devname)); 839*0daf62d9SStanislav Sedov return (0); 840*0daf62d9SStanislav Sedov } 841*0daf62d9SStanislav Sedov 842*0daf62d9SStanislav Sedov int 843*0daf62d9SStanislav Sedov procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst, 844*0daf62d9SStanislav Sedov struct vnstat *vn, char *errbuf) 845*0daf62d9SStanislav Sedov { 846*0daf62d9SStanislav Sedov 847*0daf62d9SStanislav Sedov assert(vn); 848*0daf62d9SStanislav Sedov if (procstat->type == PROCSTAT_KVM) { 849*0daf62d9SStanislav Sedov return (procstat_get_vnode_info_kvm(procstat->kd, fst, vn, 850*0daf62d9SStanislav Sedov errbuf)); 851*0daf62d9SStanislav Sedov } else if (procstat->type == PROCSTAT_SYSCTL) { 852*0daf62d9SStanislav Sedov return (procstat_get_vnode_info_sysctl(fst, vn, errbuf)); 853*0daf62d9SStanislav Sedov } else { 854*0daf62d9SStanislav Sedov warnx("unknow access method: %d", procstat->type); 855*0daf62d9SStanislav Sedov snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 856*0daf62d9SStanislav Sedov return (1); 857*0daf62d9SStanislav Sedov } 858*0daf62d9SStanislav Sedov } 859*0daf62d9SStanislav Sedov 860*0daf62d9SStanislav Sedov static int 861*0daf62d9SStanislav Sedov procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst, 862*0daf62d9SStanislav Sedov struct vnstat *vn, char *errbuf) 863*0daf62d9SStanislav Sedov { 864*0daf62d9SStanislav Sedov /* Filesystem specific handlers. */ 865*0daf62d9SStanislav Sedov #define FSTYPE(fst) {#fst, fst##_filestat} 866*0daf62d9SStanislav Sedov struct { 867*0daf62d9SStanislav Sedov const char *tag; 868*0daf62d9SStanislav Sedov int (*handler)(kvm_t *kd, struct vnode *vp, 869*0daf62d9SStanislav Sedov struct vnstat *vn); 870*0daf62d9SStanislav Sedov } fstypes[] = { 871*0daf62d9SStanislav Sedov FSTYPE(devfs), 872*0daf62d9SStanislav Sedov FSTYPE(isofs), 873*0daf62d9SStanislav Sedov FSTYPE(msdosfs), 874*0daf62d9SStanislav Sedov FSTYPE(nfs), 875*0daf62d9SStanislav Sedov FSTYPE(ntfs), 876*0daf62d9SStanislav Sedov FSTYPE(nwfs), 877*0daf62d9SStanislav Sedov FSTYPE(smbfs), 878*0daf62d9SStanislav Sedov FSTYPE(udf), 879*0daf62d9SStanislav Sedov FSTYPE(ufs), 880*0daf62d9SStanislav Sedov #ifdef ZFS 881*0daf62d9SStanislav Sedov FSTYPE(zfs), 882*0daf62d9SStanislav Sedov #endif 883*0daf62d9SStanislav Sedov }; 884*0daf62d9SStanislav Sedov #define NTYPES (sizeof(fstypes) / sizeof(*fstypes)) 885*0daf62d9SStanislav Sedov struct vnode vnode; 886*0daf62d9SStanislav Sedov char tagstr[12]; 887*0daf62d9SStanislav Sedov void *vp; 888*0daf62d9SStanislav Sedov int error, found; 889*0daf62d9SStanislav Sedov unsigned int i; 890*0daf62d9SStanislav Sedov 891*0daf62d9SStanislav Sedov assert(kd); 892*0daf62d9SStanislav Sedov assert(vn); 893*0daf62d9SStanislav Sedov assert(fst); 894*0daf62d9SStanislav Sedov vp = fst->fs_typedep; 895*0daf62d9SStanislav Sedov if (vp == NULL) 896*0daf62d9SStanislav Sedov goto fail; 897*0daf62d9SStanislav Sedov error = kvm_read_all(kd, (unsigned long)vp, &vnode, sizeof(vnode)); 898*0daf62d9SStanislav Sedov if (error == 0) { 899*0daf62d9SStanislav Sedov warnx("can't read vnode at %p", (void *)vp); 900*0daf62d9SStanislav Sedov goto fail; 901*0daf62d9SStanislav Sedov } 902*0daf62d9SStanislav Sedov bzero(vn, sizeof(*vn)); 903*0daf62d9SStanislav Sedov vn->vn_type = vntype2psfsttype(vnode.v_type); 904*0daf62d9SStanislav Sedov if (vnode.v_type == VNON || vnode.v_type == VBAD) 905*0daf62d9SStanislav Sedov return (0); 906*0daf62d9SStanislav Sedov error = kvm_read_all(kd, (unsigned long)vnode.v_tag, tagstr, 907*0daf62d9SStanislav Sedov sizeof(tagstr)); 908*0daf62d9SStanislav Sedov if (error == 0) { 909*0daf62d9SStanislav Sedov warnx("can't read v_tag at %p", (void *)vp); 910*0daf62d9SStanislav Sedov goto fail; 911*0daf62d9SStanislav Sedov } 912*0daf62d9SStanislav Sedov tagstr[sizeof(tagstr) - 1] = '\0'; 913*0daf62d9SStanislav Sedov 914*0daf62d9SStanislav Sedov /* 915*0daf62d9SStanislav Sedov * Find appropriate handler. 916*0daf62d9SStanislav Sedov */ 917*0daf62d9SStanislav Sedov for (i = 0, found = 0; i < NTYPES; i++) 918*0daf62d9SStanislav Sedov if (!strcmp(fstypes[i].tag, tagstr)) { 919*0daf62d9SStanislav Sedov if (fstypes[i].handler(kd, &vnode, vn) != 0) { 920*0daf62d9SStanislav Sedov goto fail; 921*0daf62d9SStanislav Sedov } 922*0daf62d9SStanislav Sedov break; 923*0daf62d9SStanislav Sedov } 924*0daf62d9SStanislav Sedov if (i == NTYPES) { 925*0daf62d9SStanislav Sedov snprintf(errbuf, _POSIX2_LINE_MAX, "?(%s)", tagstr); 926*0daf62d9SStanislav Sedov return (1); 927*0daf62d9SStanislav Sedov } 928*0daf62d9SStanislav Sedov vn->vn_mntdir = getmnton(kd, vnode.v_mount); 929*0daf62d9SStanislav Sedov if ((vnode.v_type == VBLK || vnode.v_type == VCHR) && 930*0daf62d9SStanislav Sedov vnode.v_rdev != NULL){ 931*0daf62d9SStanislav Sedov vn->vn_dev = dev2udev(kd, vnode.v_rdev); 932*0daf62d9SStanislav Sedov (void)kdevtoname(kd, vnode.v_rdev, vn->vn_devname); 933*0daf62d9SStanislav Sedov } else { 934*0daf62d9SStanislav Sedov vn->vn_dev = -1; 935*0daf62d9SStanislav Sedov } 936*0daf62d9SStanislav Sedov return (0); 937*0daf62d9SStanislav Sedov 938*0daf62d9SStanislav Sedov fail: 939*0daf62d9SStanislav Sedov snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 940*0daf62d9SStanislav Sedov return (1); 941*0daf62d9SStanislav Sedov } 942*0daf62d9SStanislav Sedov 943*0daf62d9SStanislav Sedov /* 944*0daf62d9SStanislav Sedov * kinfo vnode type to filestat translation. 945*0daf62d9SStanislav Sedov */ 946*0daf62d9SStanislav Sedov static int 947*0daf62d9SStanislav Sedov kinfo_vtype2fst(int kfvtype) 948*0daf62d9SStanislav Sedov { 949*0daf62d9SStanislav Sedov static struct { 950*0daf62d9SStanislav Sedov int kf_vtype; 951*0daf62d9SStanislav Sedov int fst_vtype; 952*0daf62d9SStanislav Sedov } kfvtypes2fst[] = { 953*0daf62d9SStanislav Sedov { KF_VTYPE_VBAD, PS_FST_VTYPE_VBAD }, 954*0daf62d9SStanislav Sedov { KF_VTYPE_VBLK, PS_FST_VTYPE_VBLK }, 955*0daf62d9SStanislav Sedov { KF_VTYPE_VCHR, PS_FST_VTYPE_VCHR }, 956*0daf62d9SStanislav Sedov { KF_VTYPE_VDIR, PS_FST_VTYPE_VDIR }, 957*0daf62d9SStanislav Sedov { KF_VTYPE_VFIFO, PS_FST_VTYPE_VFIFO }, 958*0daf62d9SStanislav Sedov { KF_VTYPE_VLNK, PS_FST_VTYPE_VLNK }, 959*0daf62d9SStanislav Sedov { KF_VTYPE_VNON, PS_FST_VTYPE_VNON }, 960*0daf62d9SStanislav Sedov { KF_VTYPE_VREG, PS_FST_VTYPE_VREG }, 961*0daf62d9SStanislav Sedov { KF_VTYPE_VSOCK, PS_FST_VTYPE_VSOCK } 962*0daf62d9SStanislav Sedov }; 963*0daf62d9SStanislav Sedov #define NKFVTYPES (sizeof(kfvtypes2fst) / sizeof(*kfvtypes2fst)) 964*0daf62d9SStanislav Sedov unsigned int i; 965*0daf62d9SStanislav Sedov 966*0daf62d9SStanislav Sedov for (i = 0; i < NKFVTYPES; i++) 967*0daf62d9SStanislav Sedov if (kfvtypes2fst[i].kf_vtype == kfvtype) 968*0daf62d9SStanislav Sedov break; 969*0daf62d9SStanislav Sedov if (i == NKFVTYPES) 970*0daf62d9SStanislav Sedov return (PS_FST_VTYPE_UNKNOWN); 971*0daf62d9SStanislav Sedov return (kfvtypes2fst[i].fst_vtype); 972*0daf62d9SStanislav Sedov } 973*0daf62d9SStanislav Sedov 974*0daf62d9SStanislav Sedov static int 975*0daf62d9SStanislav Sedov procstat_get_vnode_info_sysctl(struct filestat *fst, struct vnstat *vn, 976*0daf62d9SStanislav Sedov char *errbuf) 977*0daf62d9SStanislav Sedov { 978*0daf62d9SStanislav Sedov struct statfs stbuf; 979*0daf62d9SStanislav Sedov struct kinfo_file *kif; 980*0daf62d9SStanislav Sedov struct kinfo_vmentry *kve; 981*0daf62d9SStanislav Sedov uint64_t fileid; 982*0daf62d9SStanislav Sedov uint64_t size; 983*0daf62d9SStanislav Sedov char *name, *path; 984*0daf62d9SStanislav Sedov uint32_t fsid; 985*0daf62d9SStanislav Sedov uint16_t mode; 986*0daf62d9SStanislav Sedov uint32_t rdev; 987*0daf62d9SStanislav Sedov int vntype; 988*0daf62d9SStanislav Sedov int status; 989*0daf62d9SStanislav Sedov 990*0daf62d9SStanislav Sedov assert(fst); 991*0daf62d9SStanislav Sedov assert(vn); 992*0daf62d9SStanislav Sedov bzero(vn, sizeof(*vn)); 993*0daf62d9SStanislav Sedov if (fst->fs_typedep == NULL) 994*0daf62d9SStanislav Sedov return (1); 995*0daf62d9SStanislav Sedov if (fst->fs_uflags & PS_FST_UFLAG_MMAP) { 996*0daf62d9SStanislav Sedov kve = fst->fs_typedep; 997*0daf62d9SStanislav Sedov fileid = kve->kve_vn_fileid; 998*0daf62d9SStanislav Sedov fsid = kve->kve_vn_fsid; 999*0daf62d9SStanislav Sedov mode = kve->kve_vn_mode; 1000*0daf62d9SStanislav Sedov path = kve->kve_path; 1001*0daf62d9SStanislav Sedov rdev = kve->kve_vn_rdev; 1002*0daf62d9SStanislav Sedov size = kve->kve_vn_size; 1003*0daf62d9SStanislav Sedov vntype = kinfo_vtype2fst(kve->kve_vn_type); 1004*0daf62d9SStanislav Sedov status = kve->kve_status; 1005*0daf62d9SStanislav Sedov } else { 1006*0daf62d9SStanislav Sedov kif = fst->fs_typedep; 1007*0daf62d9SStanislav Sedov fileid = kif->kf_un.kf_file.kf_file_fileid; 1008*0daf62d9SStanislav Sedov fsid = kif->kf_un.kf_file.kf_file_fsid; 1009*0daf62d9SStanislav Sedov mode = kif->kf_un.kf_file.kf_file_mode; 1010*0daf62d9SStanislav Sedov path = kif->kf_path; 1011*0daf62d9SStanislav Sedov rdev = kif->kf_un.kf_file.kf_file_rdev; 1012*0daf62d9SStanislav Sedov size = kif->kf_un.kf_file.kf_file_size; 1013*0daf62d9SStanislav Sedov vntype = kinfo_vtype2fst(kif->kf_vnode_type); 1014*0daf62d9SStanislav Sedov status = kif->kf_status; 1015*0daf62d9SStanislav Sedov } 1016*0daf62d9SStanislav Sedov vn->vn_type = vntype; 1017*0daf62d9SStanislav Sedov if (vntype == PS_FST_VTYPE_VNON || vntype == PS_FST_VTYPE_VBAD) 1018*0daf62d9SStanislav Sedov return (0); 1019*0daf62d9SStanislav Sedov if ((status & KF_ATTR_VALID) == 0) { 1020*0daf62d9SStanislav Sedov snprintf(errbuf, _POSIX2_LINE_MAX, "? (no info available)"); 1021*0daf62d9SStanislav Sedov return (1); 1022*0daf62d9SStanislav Sedov } 1023*0daf62d9SStanislav Sedov if (path && *path) { 1024*0daf62d9SStanislav Sedov statfs(path, &stbuf); 1025*0daf62d9SStanislav Sedov vn->vn_mntdir = strdup(stbuf.f_mntonname); 1026*0daf62d9SStanislav Sedov } else 1027*0daf62d9SStanislav Sedov vn->vn_mntdir = strdup("-"); 1028*0daf62d9SStanislav Sedov vn->vn_dev = rdev; 1029*0daf62d9SStanislav Sedov if (vntype == PS_FST_VTYPE_VBLK) { 1030*0daf62d9SStanislav Sedov name = devname(rdev, S_IFBLK); 1031*0daf62d9SStanislav Sedov if (name != NULL) 1032*0daf62d9SStanislav Sedov strlcpy(vn->vn_devname, name, 1033*0daf62d9SStanislav Sedov sizeof(vn->vn_devname)); 1034*0daf62d9SStanislav Sedov } else if (vntype == PS_FST_VTYPE_VCHR) { 1035*0daf62d9SStanislav Sedov name = devname(vn->vn_dev, S_IFCHR); 1036*0daf62d9SStanislav Sedov if (name != NULL) 1037*0daf62d9SStanislav Sedov strlcpy(vn->vn_devname, name, 1038*0daf62d9SStanislav Sedov sizeof(vn->vn_devname)); 1039*0daf62d9SStanislav Sedov } 1040*0daf62d9SStanislav Sedov vn->vn_fsid = fsid; 1041*0daf62d9SStanislav Sedov vn->vn_fileid = fileid; 1042*0daf62d9SStanislav Sedov vn->vn_size = size; 1043*0daf62d9SStanislav Sedov vn->vn_mode = mode; 1044*0daf62d9SStanislav Sedov return (0); 1045*0daf62d9SStanislav Sedov } 1046*0daf62d9SStanislav Sedov 1047*0daf62d9SStanislav Sedov int 1048*0daf62d9SStanislav Sedov procstat_get_socket_info(struct procstat *procstat, struct filestat *fst, 1049*0daf62d9SStanislav Sedov struct sockstat *sock, char *errbuf) 1050*0daf62d9SStanislav Sedov { 1051*0daf62d9SStanislav Sedov 1052*0daf62d9SStanislav Sedov assert(sock); 1053*0daf62d9SStanislav Sedov if (procstat->type == PROCSTAT_KVM) { 1054*0daf62d9SStanislav Sedov return (procstat_get_socket_info_kvm(procstat->kd, fst, sock, 1055*0daf62d9SStanislav Sedov errbuf)); 1056*0daf62d9SStanislav Sedov } else if (procstat->type == PROCSTAT_SYSCTL) { 1057*0daf62d9SStanislav Sedov return (procstat_get_socket_info_sysctl(fst, sock, errbuf)); 1058*0daf62d9SStanislav Sedov } else { 1059*0daf62d9SStanislav Sedov warnx("unknow access method: %d", procstat->type); 1060*0daf62d9SStanislav Sedov snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1061*0daf62d9SStanislav Sedov return (1); 1062*0daf62d9SStanislav Sedov } 1063*0daf62d9SStanislav Sedov } 1064*0daf62d9SStanislav Sedov 1065*0daf62d9SStanislav Sedov static int 1066*0daf62d9SStanislav Sedov procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst, 1067*0daf62d9SStanislav Sedov struct sockstat *sock, char *errbuf) 1068*0daf62d9SStanislav Sedov { 1069*0daf62d9SStanislav Sedov struct domain dom; 1070*0daf62d9SStanislav Sedov struct inpcb inpcb; 1071*0daf62d9SStanislav Sedov struct protosw proto; 1072*0daf62d9SStanislav Sedov struct socket s; 1073*0daf62d9SStanislav Sedov struct unpcb unpcb; 1074*0daf62d9SStanislav Sedov ssize_t len; 1075*0daf62d9SStanislav Sedov void *so; 1076*0daf62d9SStanislav Sedov 1077*0daf62d9SStanislav Sedov assert(kd); 1078*0daf62d9SStanislav Sedov assert(sock); 1079*0daf62d9SStanislav Sedov assert(fst); 1080*0daf62d9SStanislav Sedov bzero(sock, sizeof(*sock)); 1081*0daf62d9SStanislav Sedov so = fst->fs_typedep; 1082*0daf62d9SStanislav Sedov if (so == NULL) 1083*0daf62d9SStanislav Sedov goto fail; 1084*0daf62d9SStanislav Sedov sock->so_addr = (uintptr_t)so; 1085*0daf62d9SStanislav Sedov /* fill in socket */ 1086*0daf62d9SStanislav Sedov if (!kvm_read_all(kd, (unsigned long)so, &s, 1087*0daf62d9SStanislav Sedov sizeof(struct socket))) { 1088*0daf62d9SStanislav Sedov warnx("can't read sock at %p", (void *)so); 1089*0daf62d9SStanislav Sedov goto fail; 1090*0daf62d9SStanislav Sedov } 1091*0daf62d9SStanislav Sedov /* fill in protosw entry */ 1092*0daf62d9SStanislav Sedov if (!kvm_read_all(kd, (unsigned long)s.so_proto, &proto, 1093*0daf62d9SStanislav Sedov sizeof(struct protosw))) { 1094*0daf62d9SStanislav Sedov warnx("can't read protosw at %p", (void *)s.so_proto); 1095*0daf62d9SStanislav Sedov goto fail; 1096*0daf62d9SStanislav Sedov } 1097*0daf62d9SStanislav Sedov /* fill in domain */ 1098*0daf62d9SStanislav Sedov if (!kvm_read_all(kd, (unsigned long)proto.pr_domain, &dom, 1099*0daf62d9SStanislav Sedov sizeof(struct domain))) { 1100*0daf62d9SStanislav Sedov warnx("can't read domain at %p", 1101*0daf62d9SStanislav Sedov (void *)proto.pr_domain); 1102*0daf62d9SStanislav Sedov goto fail; 1103*0daf62d9SStanislav Sedov } 1104*0daf62d9SStanislav Sedov if ((len = kvm_read(kd, (unsigned long)dom.dom_name, sock->dname, 1105*0daf62d9SStanislav Sedov sizeof(sock->dname) - 1)) < 0) { 1106*0daf62d9SStanislav Sedov warnx("can't read domain name at %p", (void *)dom.dom_name); 1107*0daf62d9SStanislav Sedov sock->dname[0] = '\0'; 1108*0daf62d9SStanislav Sedov } 1109*0daf62d9SStanislav Sedov else 1110*0daf62d9SStanislav Sedov sock->dname[len] = '\0'; 1111*0daf62d9SStanislav Sedov 1112*0daf62d9SStanislav Sedov /* 1113*0daf62d9SStanislav Sedov * Fill in known data. 1114*0daf62d9SStanislav Sedov */ 1115*0daf62d9SStanislav Sedov sock->type = s.so_type; 1116*0daf62d9SStanislav Sedov sock->proto = proto.pr_protocol; 1117*0daf62d9SStanislav Sedov sock->dom_family = dom.dom_family; 1118*0daf62d9SStanislav Sedov sock->so_pcb = (uintptr_t)s.so_pcb; 1119*0daf62d9SStanislav Sedov 1120*0daf62d9SStanislav Sedov /* 1121*0daf62d9SStanislav Sedov * Protocol specific data. 1122*0daf62d9SStanislav Sedov */ 1123*0daf62d9SStanislav Sedov switch(dom.dom_family) { 1124*0daf62d9SStanislav Sedov case AF_INET: 1125*0daf62d9SStanislav Sedov case AF_INET6: 1126*0daf62d9SStanislav Sedov if (proto.pr_protocol == IPPROTO_TCP) { 1127*0daf62d9SStanislav Sedov if (s.so_pcb) { 1128*0daf62d9SStanislav Sedov if (kvm_read(kd, (u_long)s.so_pcb, 1129*0daf62d9SStanislav Sedov (char *)&inpcb, sizeof(struct inpcb)) 1130*0daf62d9SStanislav Sedov != sizeof(struct inpcb)) { 1131*0daf62d9SStanislav Sedov warnx("can't read inpcb at %p", 1132*0daf62d9SStanislav Sedov (void *)s.so_pcb); 1133*0daf62d9SStanislav Sedov } else 1134*0daf62d9SStanislav Sedov sock->inp_ppcb = 1135*0daf62d9SStanislav Sedov (uintptr_t)inpcb.inp_ppcb; 1136*0daf62d9SStanislav Sedov } 1137*0daf62d9SStanislav Sedov } 1138*0daf62d9SStanislav Sedov break; 1139*0daf62d9SStanislav Sedov case AF_UNIX: 1140*0daf62d9SStanislav Sedov if (s.so_pcb) { 1141*0daf62d9SStanislav Sedov if (kvm_read(kd, (u_long)s.so_pcb, (char *)&unpcb, 1142*0daf62d9SStanislav Sedov sizeof(struct unpcb)) != sizeof(struct unpcb)){ 1143*0daf62d9SStanislav Sedov warnx("can't read unpcb at %p", 1144*0daf62d9SStanislav Sedov (void *)s.so_pcb); 1145*0daf62d9SStanislav Sedov } else if (unpcb.unp_conn) { 1146*0daf62d9SStanislav Sedov sock->so_rcv_sb_state = s.so_rcv.sb_state; 1147*0daf62d9SStanislav Sedov sock->so_snd_sb_state = s.so_snd.sb_state; 1148*0daf62d9SStanislav Sedov sock->unp_conn = (uintptr_t)unpcb.unp_conn; 1149*0daf62d9SStanislav Sedov } 1150*0daf62d9SStanislav Sedov } 1151*0daf62d9SStanislav Sedov break; 1152*0daf62d9SStanislav Sedov default: 1153*0daf62d9SStanislav Sedov break; 1154*0daf62d9SStanislav Sedov } 1155*0daf62d9SStanislav Sedov return (0); 1156*0daf62d9SStanislav Sedov 1157*0daf62d9SStanislav Sedov fail: 1158*0daf62d9SStanislav Sedov snprintf(errbuf, _POSIX2_LINE_MAX, "error"); 1159*0daf62d9SStanislav Sedov return (1); 1160*0daf62d9SStanislav Sedov } 1161*0daf62d9SStanislav Sedov 1162*0daf62d9SStanislav Sedov static int 1163*0daf62d9SStanislav Sedov procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock, 1164*0daf62d9SStanislav Sedov char *errbuf __unused) 1165*0daf62d9SStanislav Sedov { 1166*0daf62d9SStanislav Sedov struct kinfo_file *kif; 1167*0daf62d9SStanislav Sedov 1168*0daf62d9SStanislav Sedov assert(sock); 1169*0daf62d9SStanislav Sedov assert(fst); 1170*0daf62d9SStanislav Sedov bzero(sock, sizeof(*sock)); 1171*0daf62d9SStanislav Sedov kif = fst->fs_typedep; 1172*0daf62d9SStanislav Sedov if (kif == NULL) 1173*0daf62d9SStanislav Sedov return (0); 1174*0daf62d9SStanislav Sedov 1175*0daf62d9SStanislav Sedov /* 1176*0daf62d9SStanislav Sedov * Fill in known data. 1177*0daf62d9SStanislav Sedov */ 1178*0daf62d9SStanislav Sedov sock->type = kif->kf_sock_type; 1179*0daf62d9SStanislav Sedov sock->proto = kif->kf_sock_protocol; 1180*0daf62d9SStanislav Sedov sock->dom_family = kif->kf_sock_domain; 1181*0daf62d9SStanislav Sedov sock->so_pcb = kif->kf_un.kf_sock.kf_sock_pcb; 1182*0daf62d9SStanislav Sedov strlcpy(sock->dname, kif->kf_path, sizeof(sock->dname)); 1183*0daf62d9SStanislav Sedov bcopy(&kif->kf_sa_local, &sock->sa_local, kif->kf_sa_local.ss_len); 1184*0daf62d9SStanislav Sedov bcopy(&kif->kf_sa_peer, &sock->sa_peer, kif->kf_sa_peer.ss_len); 1185*0daf62d9SStanislav Sedov 1186*0daf62d9SStanislav Sedov /* 1187*0daf62d9SStanislav Sedov * Protocol specific data. 1188*0daf62d9SStanislav Sedov */ 1189*0daf62d9SStanislav Sedov switch(sock->dom_family) { 1190*0daf62d9SStanislav Sedov case AF_INET: 1191*0daf62d9SStanislav Sedov case AF_INET6: 1192*0daf62d9SStanislav Sedov if (sock->proto == IPPROTO_TCP) 1193*0daf62d9SStanislav Sedov sock->inp_ppcb = kif->kf_un.kf_sock.kf_sock_inpcb; 1194*0daf62d9SStanislav Sedov break; 1195*0daf62d9SStanislav Sedov case AF_UNIX: 1196*0daf62d9SStanislav Sedov if (kif->kf_un.kf_sock.kf_sock_unpconn != 0) { 1197*0daf62d9SStanislav Sedov sock->so_rcv_sb_state = 1198*0daf62d9SStanislav Sedov kif->kf_un.kf_sock.kf_sock_rcv_sb_state; 1199*0daf62d9SStanislav Sedov sock->so_snd_sb_state = 1200*0daf62d9SStanislav Sedov kif->kf_un.kf_sock.kf_sock_snd_sb_state; 1201*0daf62d9SStanislav Sedov sock->unp_conn = 1202*0daf62d9SStanislav Sedov kif->kf_un.kf_sock.kf_sock_unpconn; 1203*0daf62d9SStanislav Sedov } 1204*0daf62d9SStanislav Sedov break; 1205*0daf62d9SStanislav Sedov default: 1206*0daf62d9SStanislav Sedov break; 1207*0daf62d9SStanislav Sedov } 1208*0daf62d9SStanislav Sedov return (0); 1209*0daf62d9SStanislav Sedov } 1210*0daf62d9SStanislav Sedov 1211*0daf62d9SStanislav Sedov /* 1212*0daf62d9SStanislav Sedov * Descriptor flags to filestat translation. 1213*0daf62d9SStanislav Sedov */ 1214*0daf62d9SStanislav Sedov static int 1215*0daf62d9SStanislav Sedov to_filestat_flags(int flags) 1216*0daf62d9SStanislav Sedov { 1217*0daf62d9SStanislav Sedov static struct { 1218*0daf62d9SStanislav Sedov int flag; 1219*0daf62d9SStanislav Sedov int fst_flag; 1220*0daf62d9SStanislav Sedov } fstflags[] = { 1221*0daf62d9SStanislav Sedov { FREAD, PS_FST_FFLAG_READ }, 1222*0daf62d9SStanislav Sedov { FWRITE, PS_FST_FFLAG_WRITE }, 1223*0daf62d9SStanislav Sedov { O_APPEND, PS_FST_FFLAG_APPEND }, 1224*0daf62d9SStanislav Sedov { O_ASYNC, PS_FST_FFLAG_ASYNC }, 1225*0daf62d9SStanislav Sedov { O_CREAT, PS_FST_FFLAG_CREAT }, 1226*0daf62d9SStanislav Sedov { O_DIRECT, PS_FST_FFLAG_DIRECT }, 1227*0daf62d9SStanislav Sedov { O_EXCL, PS_FST_FFLAG_EXCL }, 1228*0daf62d9SStanislav Sedov { O_EXEC, PS_FST_FFLAG_EXEC }, 1229*0daf62d9SStanislav Sedov { O_EXLOCK, PS_FST_FFLAG_EXLOCK }, 1230*0daf62d9SStanislav Sedov { O_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW }, 1231*0daf62d9SStanislav Sedov { O_NONBLOCK, PS_FST_FFLAG_NONBLOCK }, 1232*0daf62d9SStanislav Sedov { O_SHLOCK, PS_FST_FFLAG_SHLOCK }, 1233*0daf62d9SStanislav Sedov { O_SYNC, PS_FST_FFLAG_SYNC }, 1234*0daf62d9SStanislav Sedov { O_TRUNC, PS_FST_FFLAG_TRUNC } 1235*0daf62d9SStanislav Sedov }; 1236*0daf62d9SStanislav Sedov #define NFSTFLAGS (sizeof(fstflags) / sizeof(*fstflags)) 1237*0daf62d9SStanislav Sedov int fst_flags; 1238*0daf62d9SStanislav Sedov unsigned int i; 1239*0daf62d9SStanislav Sedov 1240*0daf62d9SStanislav Sedov fst_flags = 0; 1241*0daf62d9SStanislav Sedov for (i = 0; i < NFSTFLAGS; i++) 1242*0daf62d9SStanislav Sedov if (flags & fstflags[i].flag) 1243*0daf62d9SStanislav Sedov fst_flags |= fstflags[i].fst_flag; 1244*0daf62d9SStanislav Sedov return (fst_flags); 1245*0daf62d9SStanislav Sedov } 1246*0daf62d9SStanislav Sedov 1247*0daf62d9SStanislav Sedov /* 1248*0daf62d9SStanislav Sedov * Vnode type to filestate translation. 1249*0daf62d9SStanislav Sedov */ 1250*0daf62d9SStanislav Sedov static int 1251*0daf62d9SStanislav Sedov vntype2psfsttype(int type) 1252*0daf62d9SStanislav Sedov { 1253*0daf62d9SStanislav Sedov static struct { 1254*0daf62d9SStanislav Sedov int vtype; 1255*0daf62d9SStanislav Sedov int fst_vtype; 1256*0daf62d9SStanislav Sedov } vt2fst[] = { 1257*0daf62d9SStanislav Sedov { VBAD, PS_FST_VTYPE_VBAD }, 1258*0daf62d9SStanislav Sedov { VBLK, PS_FST_VTYPE_VBLK }, 1259*0daf62d9SStanislav Sedov { VCHR, PS_FST_VTYPE_VCHR }, 1260*0daf62d9SStanislav Sedov { VDIR, PS_FST_VTYPE_VDIR }, 1261*0daf62d9SStanislav Sedov { VFIFO, PS_FST_VTYPE_VFIFO }, 1262*0daf62d9SStanislav Sedov { VLNK, PS_FST_VTYPE_VLNK }, 1263*0daf62d9SStanislav Sedov { VNON, PS_FST_VTYPE_VNON }, 1264*0daf62d9SStanislav Sedov { VREG, PS_FST_VTYPE_VREG }, 1265*0daf62d9SStanislav Sedov { VSOCK, PS_FST_VTYPE_VSOCK } 1266*0daf62d9SStanislav Sedov }; 1267*0daf62d9SStanislav Sedov #define NVFTYPES (sizeof(vt2fst) / sizeof(*vt2fst)) 1268*0daf62d9SStanislav Sedov unsigned int i, fst_type; 1269*0daf62d9SStanislav Sedov 1270*0daf62d9SStanislav Sedov fst_type = PS_FST_VTYPE_UNKNOWN; 1271*0daf62d9SStanislav Sedov for (i = 0; i < NVFTYPES; i++) { 1272*0daf62d9SStanislav Sedov if (type == vt2fst[i].vtype) { 1273*0daf62d9SStanislav Sedov fst_type = vt2fst[i].fst_vtype; 1274*0daf62d9SStanislav Sedov break; 1275*0daf62d9SStanislav Sedov } 1276*0daf62d9SStanislav Sedov } 1277*0daf62d9SStanislav Sedov return (fst_type); 1278*0daf62d9SStanislav Sedov } 1279*0daf62d9SStanislav Sedov 1280*0daf62d9SStanislav Sedov static char * 1281*0daf62d9SStanislav Sedov getmnton(kvm_t *kd, struct mount *m) 1282*0daf62d9SStanislav Sedov { 1283*0daf62d9SStanislav Sedov static struct mount mnt; 1284*0daf62d9SStanislav Sedov static struct mtab { 1285*0daf62d9SStanislav Sedov struct mtab *next; 1286*0daf62d9SStanislav Sedov struct mount *m; 1287*0daf62d9SStanislav Sedov char mntonname[MNAMELEN + 1]; 1288*0daf62d9SStanislav Sedov } *mhead = NULL; 1289*0daf62d9SStanislav Sedov struct mtab *mt; 1290*0daf62d9SStanislav Sedov 1291*0daf62d9SStanislav Sedov for (mt = mhead; mt != NULL; mt = mt->next) 1292*0daf62d9SStanislav Sedov if (m == mt->m) 1293*0daf62d9SStanislav Sedov return (mt->mntonname); 1294*0daf62d9SStanislav Sedov if (!kvm_read_all(kd, (unsigned long)m, &mnt, sizeof(struct mount))) { 1295*0daf62d9SStanislav Sedov warnx("can't read mount table at %p", (void *)m); 1296*0daf62d9SStanislav Sedov return (NULL); 1297*0daf62d9SStanislav Sedov } 1298*0daf62d9SStanislav Sedov if ((mt = malloc(sizeof (struct mtab))) == NULL) 1299*0daf62d9SStanislav Sedov err(1, NULL); 1300*0daf62d9SStanislav Sedov mt->m = m; 1301*0daf62d9SStanislav Sedov bcopy(&mnt.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN); 1302*0daf62d9SStanislav Sedov mnt.mnt_stat.f_mntonname[MNAMELEN] = '\0'; 1303*0daf62d9SStanislav Sedov mt->next = mhead; 1304*0daf62d9SStanislav Sedov mhead = mt; 1305*0daf62d9SStanislav Sedov return (mt->mntonname); 1306*0daf62d9SStanislav Sedov } 1307