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; 1373d91be41SRobert Watson int error, i, name[4]; 1383d91be41SRobert Watson const char *str; 1393d91be41SRobert Watson size_t len; 1403d91be41SRobert Watson 1413d91be41SRobert Watson if (!hflag) 1425a246d29SRobert Watson printf("%5s %-16s %3s %1s %1s %-8s %3s %7s %-3s %-12s\n", 1435a246d29SRobert Watson "PID", "COMM", "FD", "T", "V", "FLAGS", "REF", "OFFSET", 1445a246d29SRobert Watson "PRO", "NAME"); 1453d91be41SRobert Watson 1463d91be41SRobert Watson name[0] = CTL_KERN; 1473d91be41SRobert Watson name[1] = KERN_PROC; 1483d91be41SRobert Watson name[2] = KERN_PROC_FILEDESC; 1493d91be41SRobert Watson name[3] = pid; 1503d91be41SRobert Watson 1513d91be41SRobert Watson error = sysctl(name, 4, NULL, &len, NULL, 0); 1523d91be41SRobert Watson if (error < 0 && errno != ESRCH && errno != EPERM) { 1533d91be41SRobert Watson warn("sysctl: kern.proc.filedesc: %d", pid); 1543d91be41SRobert Watson return; 1553d91be41SRobert Watson } 1563d91be41SRobert Watson if (error < 0) 1573d91be41SRobert Watson return; 1583d91be41SRobert Watson 1593d91be41SRobert Watson freep = kif = malloc(len); 1603d91be41SRobert Watson if (kif == NULL) 1613d91be41SRobert Watson err(-1, "malloc"); 1623d91be41SRobert Watson 1633d91be41SRobert Watson if (sysctl(name, 4, kif, &len, NULL, 0) < 0) { 1643d91be41SRobert Watson warn("sysctl: kern.proc.filedesc %d", pid); 1653d91be41SRobert Watson free(freep); 1663d91be41SRobert Watson return; 1673d91be41SRobert Watson } 1683d91be41SRobert Watson 1693d91be41SRobert Watson for (i = 0; i < len / sizeof(*kif); i++, kif++) { 1703d91be41SRobert Watson if (kif->kf_structsize != sizeof(*kif)) 1713d91be41SRobert Watson errx(-1, "kinfo_file mismatch"); 1723d91be41SRobert Watson printf("%5d ", pid); 1735a246d29SRobert Watson printf("%-16s ", kipp->ki_comm); 1743d91be41SRobert Watson printf("%3d ", kif->kf_fd); 1753d91be41SRobert Watson switch (kif->kf_type) { 1763d91be41SRobert Watson case KF_TYPE_VNODE: 1773d91be41SRobert Watson str = "v"; 1783d91be41SRobert Watson break; 1793d91be41SRobert Watson 1803d91be41SRobert Watson case KF_TYPE_SOCKET: 1813d91be41SRobert Watson str = "s"; 1823d91be41SRobert Watson break; 1833d91be41SRobert Watson 1843d91be41SRobert Watson case KF_TYPE_PIPE: 1853d91be41SRobert Watson str = "p"; 1863d91be41SRobert Watson break; 1873d91be41SRobert Watson 1883d91be41SRobert Watson case KF_TYPE_FIFO: 1893d91be41SRobert Watson str = "f"; 1903d91be41SRobert Watson break; 1913d91be41SRobert Watson 1923d91be41SRobert Watson case KF_TYPE_KQUEUE: 1933d91be41SRobert Watson str = "k"; 1943d91be41SRobert Watson break; 1953d91be41SRobert Watson 1963d91be41SRobert Watson case KF_TYPE_CRYPTO: 1973d91be41SRobert Watson str = "c"; 1983d91be41SRobert Watson break; 1993d91be41SRobert Watson 2003d91be41SRobert Watson case KF_TYPE_MQUEUE: 2013d91be41SRobert Watson str = "m"; 2023d91be41SRobert Watson break; 2033d91be41SRobert Watson 2043d91be41SRobert Watson case KF_TYPE_NONE: 2053d91be41SRobert Watson case KF_TYPE_UNKNOWN: 2063d91be41SRobert Watson default: 2073d91be41SRobert Watson str = "?"; 2083d91be41SRobert Watson break; 2093d91be41SRobert Watson } 2103d91be41SRobert Watson printf("%1s ", str); 2113d91be41SRobert Watson str = "-"; 2123d91be41SRobert Watson if (kif->kf_type == KF_TYPE_VNODE) { 2133d91be41SRobert Watson switch (kif->kf_vnode_type) { 2143d91be41SRobert Watson case KF_VTYPE_VREG: 2153d91be41SRobert Watson str = "r"; 2163d91be41SRobert Watson break; 2173d91be41SRobert Watson 2183d91be41SRobert Watson case KF_VTYPE_VDIR: 2193d91be41SRobert Watson str = "d"; 2203d91be41SRobert Watson break; 2213d91be41SRobert Watson 2223d91be41SRobert Watson case KF_VTYPE_VBLK: 2233d91be41SRobert Watson str = "b"; 2243d91be41SRobert Watson break; 2253d91be41SRobert Watson 2263d91be41SRobert Watson case KF_VTYPE_VCHR: 2273d91be41SRobert Watson str = "c"; 2283d91be41SRobert Watson break; 2293d91be41SRobert Watson 2303d91be41SRobert Watson case KF_VTYPE_VLNK: 2313d91be41SRobert Watson str = "l"; 2323d91be41SRobert Watson break; 2333d91be41SRobert Watson 2343d91be41SRobert Watson case KF_VTYPE_VSOCK: 2353d91be41SRobert Watson str = "s"; 2363d91be41SRobert Watson break; 2373d91be41SRobert Watson 2383d91be41SRobert Watson case KF_VTYPE_VFIFO: 2393d91be41SRobert Watson str = "f"; 2403d91be41SRobert Watson break; 2413d91be41SRobert Watson 2423d91be41SRobert Watson case KF_VTYPE_VBAD: 2433d91be41SRobert Watson str = "x"; 2443d91be41SRobert Watson break; 2453d91be41SRobert Watson 2463d91be41SRobert Watson case KF_VTYPE_VNON: 2473d91be41SRobert Watson case KF_VTYPE_UNKNOWN: 2483d91be41SRobert Watson default: 2493d91be41SRobert Watson str = "?"; 2503d91be41SRobert Watson break; 2513d91be41SRobert Watson } 2523d91be41SRobert Watson } 2533d91be41SRobert Watson printf("%1s ", str); 2543d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_READ ? "r" : "-"); 2553d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_WRITE ? "w" : "-"); 2563d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_APPEND ? "a" : "-"); 2573d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_ASYNC ? "s" : "-"); 2583d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_FSYNC ? "f" : "-"); 2593d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_NONBLOCK ? "n" : "-"); 2603d91be41SRobert Watson printf("%s", kif->kf_flags & KF_FLAG_DIRECT ? "d" : "-"); 2613d91be41SRobert Watson printf("%s ", kif->kf_flags & KF_FLAG_HASLOCK ? "l" : "-"); 2623d91be41SRobert Watson printf("%3d ", kif->kf_ref_count); 2633d91be41SRobert Watson printf("%7jd ", (intmax_t)kif->kf_offset); 2643d91be41SRobert Watson 2653d91be41SRobert Watson switch (kif->kf_type) { 2663d91be41SRobert Watson case KF_TYPE_VNODE: 2673d91be41SRobert Watson case KF_TYPE_FIFO: 2685a246d29SRobert Watson printf("%-3s ", "-"); 2695a246d29SRobert Watson printf("%-18s", kif->kf_path); 2703d91be41SRobert Watson break; 2713d91be41SRobert Watson 2723d91be41SRobert Watson case KF_TYPE_SOCKET: 2735a246d29SRobert Watson printf("%-3s ", 2743d91be41SRobert Watson protocol_to_string(kif->kf_sock_domain, 2753d91be41SRobert Watson kif->kf_sock_type, kif->kf_sock_protocol)); 2763d91be41SRobert Watson /* 2773d91be41SRobert Watson * While generally we like to print two addresses, 2783d91be41SRobert Watson * local and peer, for sockets, it turns out to be 2793d91be41SRobert Watson * more useful to print the first non-nul address for 2803d91be41SRobert Watson * local sockets, as typically they aren't bound and 2813d91be41SRobert Watson * connected, and the path strings can get long. 2823d91be41SRobert Watson */ 2833d91be41SRobert Watson if (kif->kf_sock_domain == AF_LOCAL) { 2843d91be41SRobert Watson struct sockaddr_un *sun = 2853d91be41SRobert Watson (struct sockaddr_un *)&kif->kf_sa_local; 2863d91be41SRobert Watson 2873d91be41SRobert Watson if (sun->sun_path[0] != 0) 2883d91be41SRobert Watson print_address(&kif->kf_sa_local); 2893d91be41SRobert Watson else 2903d91be41SRobert Watson print_address(&kif->kf_sa_peer); 2913d91be41SRobert Watson } else { 2923d91be41SRobert Watson print_address(&kif->kf_sa_local); 2933d91be41SRobert Watson printf(" "); 2943d91be41SRobert Watson print_address(&kif->kf_sa_peer); 2953d91be41SRobert Watson } 2963d91be41SRobert Watson break; 2973d91be41SRobert Watson 2983d91be41SRobert Watson default: 2995a246d29SRobert Watson printf("%-3s ", "-"); 3005a246d29SRobert Watson printf("%-18s", "-"); 3013d91be41SRobert Watson } 3023d91be41SRobert Watson 3033d91be41SRobert Watson printf("\n"); 3043d91be41SRobert Watson } 3053d91be41SRobert Watson free(freep); 3063d91be41SRobert Watson } 307