13d91be41SRobert Watson /*- 23d91be41SRobert Watson * Copyright (c) 2007 Robert N. M. Watson 33d91be41SRobert Watson * All rights reserved. 43d91be41SRobert Watson * 53d91be41SRobert Watson * Redistribution and use in source and binary forms, with or without 63d91be41SRobert Watson * modification, are permitted provided that the following conditions 73d91be41SRobert Watson * are met: 83d91be41SRobert Watson * 1. Redistributions of source code must retain the above copyright 93d91be41SRobert Watson * notice, this list of conditions and the following disclaimer. 103d91be41SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 113d91be41SRobert Watson * notice, this list of conditions and the following disclaimer in the 123d91be41SRobert Watson * documentation and/or other materials provided with the distribution. 133d91be41SRobert Watson * 143d91be41SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 153d91be41SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 163d91be41SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 173d91be41SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 183d91be41SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 193d91be41SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 203d91be41SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 213d91be41SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 223d91be41SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 233d91be41SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 243d91be41SRobert Watson * SUCH DAMAGE. 253d91be41SRobert Watson * 263d91be41SRobert Watson * $FreeBSD$ 273d91be41SRobert Watson */ 283d91be41SRobert Watson 293d91be41SRobert Watson #include <sys/types.h> 303d91be41SRobert Watson #include <sys/socket.h> 313d91be41SRobert Watson #include <sys/sysctl.h> 323d91be41SRobert Watson #include <sys/un.h> 333d91be41SRobert Watson #include <sys/user.h> 343d91be41SRobert Watson 353d91be41SRobert Watson #include <netinet/in.h> 363d91be41SRobert Watson 373d91be41SRobert Watson #include <arpa/inet.h> 383d91be41SRobert Watson 393d91be41SRobert Watson #include <err.h> 403d91be41SRobert Watson #include <inttypes.h> 413d91be41SRobert Watson #include <stdio.h> 423d91be41SRobert Watson #include <stdlib.h> 433d91be41SRobert Watson #include <string.h> 443d91be41SRobert Watson 453d91be41SRobert Watson #include "procstat.h" 463d91be41SRobert Watson 473d91be41SRobert Watson static const char * 483d91be41SRobert Watson protocol_to_string(int domain, int type, int protocol) 493d91be41SRobert Watson { 503d91be41SRobert Watson 513d91be41SRobert Watson switch (domain) { 523d91be41SRobert Watson case AF_INET: 533d91be41SRobert Watson case AF_INET6: 543d91be41SRobert Watson switch (protocol) { 553d91be41SRobert Watson case IPPROTO_TCP: 563d91be41SRobert Watson return ("TCP"); 573d91be41SRobert Watson case IPPROTO_UDP: 583d91be41SRobert Watson return ("UDP"); 593d91be41SRobert Watson case IPPROTO_ICMP: 605a246d29SRobert Watson return ("ICM"); 613d91be41SRobert Watson case IPPROTO_RAW: 623d91be41SRobert Watson return ("RAW"); 633d91be41SRobert Watson case IPPROTO_SCTP: 645a246d29SRobert Watson return ("SCT"); 655a246d29SRobert Watson case IPPROTO_DIVERT: 665a246d29SRobert Watson return ("IPD"); 673d91be41SRobert Watson default: 685a246d29SRobert Watson return ("IP?"); 693d91be41SRobert Watson } 703d91be41SRobert Watson 713d91be41SRobert Watson case AF_LOCAL: 723d91be41SRobert Watson switch (type) { 733d91be41SRobert Watson case SOCK_STREAM: 745a246d29SRobert Watson return ("UDS"); 753d91be41SRobert Watson case SOCK_DGRAM: 765a246d29SRobert Watson return ("UDD"); 773d91be41SRobert Watson default: 785a246d29SRobert Watson return ("UD?"); 793d91be41SRobert Watson } 803d91be41SRobert Watson default: 815a246d29SRobert Watson return ("?"); 823d91be41SRobert Watson } 833d91be41SRobert Watson } 843d91be41SRobert Watson 853d91be41SRobert Watson static void 863d91be41SRobert Watson addr_to_string(struct sockaddr_storage *ss, char *buffer, int buflen) 873d91be41SRobert Watson { 883d91be41SRobert Watson char buffer2[INET6_ADDRSTRLEN]; 893d91be41SRobert Watson struct sockaddr_in6 *sin6; 903d91be41SRobert Watson struct sockaddr_in *sin; 913d91be41SRobert Watson struct sockaddr_un *sun; 923d91be41SRobert Watson 933d91be41SRobert Watson switch (ss->ss_family) { 943d91be41SRobert Watson case AF_LOCAL: 953d91be41SRobert Watson sun = (struct sockaddr_un *)ss; 963d91be41SRobert Watson if (strlen(sun->sun_path) == 0) 973d91be41SRobert Watson strlcpy(buffer, "-", buflen); 983d91be41SRobert Watson else 993d91be41SRobert Watson strlcpy(buffer, sun->sun_path, buflen); 1003d91be41SRobert Watson break; 1013d91be41SRobert Watson 1023d91be41SRobert Watson case AF_INET: 1033d91be41SRobert Watson sin = (struct sockaddr_in *)ss; 1043d91be41SRobert Watson snprintf(buffer, buflen, "%s:%d", inet_ntoa(sin->sin_addr), 1053d91be41SRobert Watson ntohs(sin->sin_port)); 1063d91be41SRobert Watson break; 1073d91be41SRobert Watson 1083d91be41SRobert Watson case AF_INET6: 1093d91be41SRobert Watson sin6 = (struct sockaddr_in6 *)ss; 1103d91be41SRobert Watson if (inet_ntop(AF_INET6, &sin6->sin6_addr, buffer2, 1113d91be41SRobert Watson sizeof(buffer2)) != NULL) 1123d91be41SRobert Watson snprintf(buffer, buflen, "%s.%d", buffer2, 1133d91be41SRobert Watson ntohs(sin6->sin6_port)); 1143d91be41SRobert Watson else 1153d91be41SRobert Watson strlcpy(buffer, "-", sizeof(buffer)); 1163d91be41SRobert Watson break; 1173d91be41SRobert Watson 1183d91be41SRobert Watson default: 1193d91be41SRobert Watson strlcpy(buffer, "", buflen); 1203d91be41SRobert Watson break; 1213d91be41SRobert Watson } 1223d91be41SRobert Watson } 1233d91be41SRobert Watson 1243d91be41SRobert Watson static void 1253d91be41SRobert Watson print_address(struct sockaddr_storage *ss) 1263d91be41SRobert Watson { 1273d91be41SRobert Watson char addr[PATH_MAX]; 1283d91be41SRobert Watson 1293d91be41SRobert Watson addr_to_string(ss, addr, sizeof(addr)); 1305a246d29SRobert Watson printf("%s", addr); 1313d91be41SRobert Watson } 1323d91be41SRobert Watson 1333d91be41SRobert Watson void 1343d91be41SRobert Watson procstat_files(pid_t pid, struct kinfo_proc *kipp) 1353d91be41SRobert Watson { 1363d91be41SRobert Watson struct kinfo_file *freep, *kif; 13797ce0ae6SDavid Malone int error, name[4]; 13897ce0ae6SDavid Malone unsigned int i; 1393d91be41SRobert Watson const char *str; 1403d91be41SRobert Watson size_t len; 1413d91be41SRobert Watson 1423d91be41SRobert Watson if (!hflag) 143f2805949SJoe Marcus Clarke printf("%5s %-16s %4s %1s %1s %-8s %3s %7s %-3s %-12s\n", 1445a246d29SRobert Watson "PID", "COMM", "FD", "T", "V", "FLAGS", "REF", "OFFSET", 1455a246d29SRobert Watson "PRO", "NAME"); 1463d91be41SRobert Watson 1473d91be41SRobert Watson name[0] = CTL_KERN; 1483d91be41SRobert Watson name[1] = KERN_PROC; 1493d91be41SRobert Watson name[2] = KERN_PROC_FILEDESC; 1503d91be41SRobert Watson name[3] = pid; 1513d91be41SRobert Watson 1523d91be41SRobert Watson error = sysctl(name, 4, NULL, &len, NULL, 0); 1533d91be41SRobert Watson if (error < 0 && errno != ESRCH && errno != EPERM) { 1543d91be41SRobert Watson warn("sysctl: kern.proc.filedesc: %d", pid); 1553d91be41SRobert Watson return; 1563d91be41SRobert Watson } 1573d91be41SRobert Watson if (error < 0) 1583d91be41SRobert Watson return; 1593d91be41SRobert Watson 1603d91be41SRobert Watson freep = kif = malloc(len); 1613d91be41SRobert Watson if (kif == NULL) 1623d91be41SRobert Watson err(-1, "malloc"); 1633d91be41SRobert Watson 1643d91be41SRobert Watson if (sysctl(name, 4, kif, &len, NULL, 0) < 0) { 1653d91be41SRobert Watson warn("sysctl: kern.proc.filedesc %d", pid); 1663d91be41SRobert Watson free(freep); 1673d91be41SRobert Watson return; 1683d91be41SRobert Watson } 1693d91be41SRobert Watson 1703d91be41SRobert Watson for (i = 0; i < len / sizeof(*kif); i++, kif++) { 1713d91be41SRobert Watson if (kif->kf_structsize != sizeof(*kif)) 1723d91be41SRobert Watson errx(-1, "kinfo_file mismatch"); 1733d91be41SRobert Watson printf("%5d ", pid); 1745a246d29SRobert Watson printf("%-16s ", kipp->ki_comm); 175f2805949SJoe Marcus Clarke switch (kif->kf_fd) { 176f2805949SJoe Marcus Clarke case KF_FD_TYPE_CWD: 177f2805949SJoe Marcus Clarke printf(" cwd "); 178f2805949SJoe Marcus Clarke break; 179f2805949SJoe Marcus Clarke 180f2805949SJoe Marcus Clarke case KF_FD_TYPE_ROOT: 181f2805949SJoe Marcus Clarke printf("root "); 182f2805949SJoe Marcus Clarke break; 183f2805949SJoe Marcus Clarke 184f2805949SJoe Marcus Clarke case KF_FD_TYPE_JAIL: 185f2805949SJoe Marcus Clarke printf("jail "); 186f2805949SJoe Marcus Clarke break; 187f2805949SJoe Marcus Clarke 188f2805949SJoe Marcus Clarke default: 189f2805949SJoe Marcus Clarke printf("%4d ", kif->kf_fd); 190f2805949SJoe Marcus Clarke break; 191f2805949SJoe Marcus Clarke } 1923d91be41SRobert Watson switch (kif->kf_type) { 1933d91be41SRobert Watson case KF_TYPE_VNODE: 1943d91be41SRobert Watson str = "v"; 1953d91be41SRobert Watson break; 1963d91be41SRobert Watson 1973d91be41SRobert Watson case KF_TYPE_SOCKET: 1983d91be41SRobert Watson str = "s"; 1993d91be41SRobert Watson break; 2003d91be41SRobert Watson 2013d91be41SRobert Watson case KF_TYPE_PIPE: 2023d91be41SRobert Watson str = "p"; 2033d91be41SRobert Watson break; 2043d91be41SRobert Watson 2053d91be41SRobert Watson case KF_TYPE_FIFO: 2063d91be41SRobert Watson str = "f"; 2073d91be41SRobert Watson break; 2083d91be41SRobert Watson 2093d91be41SRobert Watson case KF_TYPE_KQUEUE: 2103d91be41SRobert Watson str = "k"; 2113d91be41SRobert Watson break; 2123d91be41SRobert Watson 2133d91be41SRobert Watson case KF_TYPE_CRYPTO: 2143d91be41SRobert Watson str = "c"; 2153d91be41SRobert Watson break; 2163d91be41SRobert Watson 2173d91be41SRobert Watson case KF_TYPE_MQUEUE: 2183d91be41SRobert Watson str = "m"; 2193d91be41SRobert Watson break; 2203d91be41SRobert Watson 22187cb56f6SRobert Watson case KF_TYPE_SHM: 22287cb56f6SRobert Watson str = "h"; 22387cb56f6SRobert Watson break; 22487cb56f6SRobert Watson 225bc093719SEd Schouten case KF_TYPE_PTS: 226bc093719SEd Schouten str = "t"; 227bc093719SEd Schouten break; 228bc093719SEd Schouten 2296bc1e9cdSJohn Baldwin case KF_TYPE_SEM: 2306bc1e9cdSJohn Baldwin str = "e"; 2316bc1e9cdSJohn Baldwin break; 2326bc1e9cdSJohn Baldwin 2333d91be41SRobert Watson case KF_TYPE_NONE: 2343d91be41SRobert Watson case KF_TYPE_UNKNOWN: 2353d91be41SRobert Watson default: 2363d91be41SRobert Watson str = "?"; 2373d91be41SRobert Watson break; 2383d91be41SRobert Watson } 2393d91be41SRobert Watson printf("%1s ", str); 2403d91be41SRobert Watson str = "-"; 2413d91be41SRobert Watson if (kif->kf_type == KF_TYPE_VNODE) { 2423d91be41SRobert Watson switch (kif->kf_vnode_type) { 2433d91be41SRobert Watson case KF_VTYPE_VREG: 2443d91be41SRobert Watson str = "r"; 2453d91be41SRobert Watson break; 2463d91be41SRobert Watson 2473d91be41SRobert Watson case KF_VTYPE_VDIR: 2483d91be41SRobert Watson str = "d"; 2493d91be41SRobert Watson break; 2503d91be41SRobert Watson 2513d91be41SRobert Watson case KF_VTYPE_VBLK: 2523d91be41SRobert Watson str = "b"; 2533d91be41SRobert Watson break; 2543d91be41SRobert Watson 2553d91be41SRobert Watson case KF_VTYPE_VCHR: 2563d91be41SRobert Watson str = "c"; 2573d91be41SRobert Watson break; 2583d91be41SRobert Watson 2593d91be41SRobert Watson case KF_VTYPE_VLNK: 2603d91be41SRobert Watson str = "l"; 2613d91be41SRobert Watson break; 2623d91be41SRobert Watson 2633d91be41SRobert Watson case KF_VTYPE_VSOCK: 2643d91be41SRobert Watson str = "s"; 2653d91be41SRobert Watson break; 2663d91be41SRobert Watson 2673d91be41SRobert Watson case KF_VTYPE_VFIFO: 2683d91be41SRobert Watson str = "f"; 2693d91be41SRobert Watson break; 2703d91be41SRobert Watson 2713d91be41SRobert Watson case KF_VTYPE_VBAD: 2723d91be41SRobert Watson str = "x"; 2733d91be41SRobert Watson break; 2743d91be41SRobert Watson 2753d91be41SRobert Watson case KF_VTYPE_VNON: 2763d91be41SRobert Watson case KF_VTYPE_UNKNOWN: 2773d91be41SRobert Watson default: 2783d91be41SRobert Watson str = "?"; 2793d91be41SRobert Watson break; 2803d91be41SRobert Watson } 2813d91be41SRobert Watson } 2823d91be41SRobert Watson printf("%1s ", str); 2833d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_READ ? "r" : "-"); 2843d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_WRITE ? "w" : "-"); 2853d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_APPEND ? "a" : "-"); 2863d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_ASYNC ? "s" : "-"); 2873d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_FSYNC ? "f" : "-"); 2883d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_NONBLOCK ? "n" : "-"); 2893d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_DIRECT ? "d" : "-"); 2903d91be41SRobert Watson printf("%s ", kif->kf_flags & KF_FLAG_HASLOCK ? "l" : "-"); 291f2805949SJoe Marcus Clarke if (kif->kf_ref_count > -1) 2923d91be41SRobert Watson printf("%3d ", kif->kf_ref_count); 293f2805949SJoe Marcus Clarke else 294f2805949SJoe Marcus Clarke printf("%3c ", '-'); 295f2805949SJoe Marcus Clarke if (kif->kf_offset > -1) 2963d91be41SRobert Watson printf("%7jd ", (intmax_t)kif->kf_offset); 297f2805949SJoe Marcus Clarke else 298f2805949SJoe Marcus Clarke printf("%7c ", '-'); 2993d91be41SRobert Watson 3003d91be41SRobert Watson switch (kif->kf_type) { 3013d91be41SRobert Watson case KF_TYPE_VNODE: 3023d91be41SRobert Watson case KF_TYPE_FIFO: 303bc093719SEd Schouten case KF_TYPE_PTS: 3045a246d29SRobert Watson printf("%-3s ", "-"); 3055a246d29SRobert Watson printf("%-18s", kif->kf_path); 3063d91be41SRobert Watson break; 3073d91be41SRobert Watson 3083d91be41SRobert Watson case KF_TYPE_SOCKET: 3095a246d29SRobert Watson printf("%-3s ", 3103d91be41SRobert Watson protocol_to_string(kif->kf_sock_domain, 3113d91be41SRobert Watson kif->kf_sock_type, kif->kf_sock_protocol)); 3123d91be41SRobert Watson /* 3133d91be41SRobert Watson * While generally we like to print two addresses, 3143d91be41SRobert Watson * local and peer, for sockets, it turns out to be 3153d91be41SRobert Watson * more useful to print the first non-nul address for 3163d91be41SRobert Watson * local sockets, as typically they aren't bound and 3173d91be41SRobert Watson * connected, and the path strings can get long. 3183d91be41SRobert Watson */ 3193d91be41SRobert Watson if (kif->kf_sock_domain == AF_LOCAL) { 3203d91be41SRobert Watson struct sockaddr_un *sun = 3213d91be41SRobert Watson (struct sockaddr_un *)&kif->kf_sa_local; 3223d91be41SRobert Watson 3233d91be41SRobert Watson if (sun->sun_path[0] != 0) 3243d91be41SRobert Watson print_address(&kif->kf_sa_local); 3253d91be41SRobert Watson else 3263d91be41SRobert Watson print_address(&kif->kf_sa_peer); 3273d91be41SRobert Watson } else { 3283d91be41SRobert Watson print_address(&kif->kf_sa_local); 3293d91be41SRobert Watson printf(" "); 3303d91be41SRobert Watson print_address(&kif->kf_sa_peer); 3313d91be41SRobert Watson } 3323d91be41SRobert Watson break; 3333d91be41SRobert Watson 3343d91be41SRobert Watson default: 3355a246d29SRobert Watson printf("%-3s ", "-"); 3365a246d29SRobert Watson printf("%-18s", "-"); 3373d91be41SRobert Watson } 3383d91be41SRobert Watson 3393d91be41SRobert Watson printf("\n"); 3403d91be41SRobert Watson } 3413d91be41SRobert Watson free(freep); 3423d91be41SRobert Watson } 343