xref: /freebsd/usr.bin/procstat/procstat_files.c (revision bc093719ca478fe10b938cef32c30b528042cbcd)
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