xref: /freebsd/usr.bin/procstat/procstat_files.c (revision 821df508e882ca532bec415852399c6558f22f7a)
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 
29e1f323f3SRobert Watson #include <sys/param.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 
39821df508SXin LI #include <err.h>
403d91be41SRobert Watson #include <inttypes.h>
413d91be41SRobert Watson #include <stdio.h>
423d91be41SRobert Watson #include <stdlib.h>
433d91be41SRobert Watson #include <string.h>
4443151ee6SPeter Wemm #include <libutil.h>
453d91be41SRobert Watson 
463d91be41SRobert Watson #include "procstat.h"
473d91be41SRobert Watson 
483d91be41SRobert Watson static const char *
493d91be41SRobert Watson protocol_to_string(int domain, int type, int protocol)
503d91be41SRobert Watson {
513d91be41SRobert Watson 
523d91be41SRobert Watson 	switch (domain) {
533d91be41SRobert Watson 	case AF_INET:
543d91be41SRobert Watson 	case AF_INET6:
553d91be41SRobert Watson 		switch (protocol) {
563d91be41SRobert Watson 		case IPPROTO_TCP:
573d91be41SRobert Watson 			return ("TCP");
583d91be41SRobert Watson 		case IPPROTO_UDP:
593d91be41SRobert Watson 			return ("UDP");
603d91be41SRobert Watson 		case IPPROTO_ICMP:
615a246d29SRobert Watson 			return ("ICM");
623d91be41SRobert Watson 		case IPPROTO_RAW:
633d91be41SRobert Watson 			return ("RAW");
643d91be41SRobert Watson 		case IPPROTO_SCTP:
655a246d29SRobert Watson 			return ("SCT");
665a246d29SRobert Watson 		case IPPROTO_DIVERT:
675a246d29SRobert Watson 			return ("IPD");
683d91be41SRobert Watson 		default:
695a246d29SRobert Watson 			return ("IP?");
703d91be41SRobert Watson 		}
713d91be41SRobert Watson 
723d91be41SRobert Watson 	case AF_LOCAL:
733d91be41SRobert Watson 		switch (type) {
743d91be41SRobert Watson 		case SOCK_STREAM:
755a246d29SRobert Watson 			return ("UDS");
763d91be41SRobert Watson 		case SOCK_DGRAM:
775a246d29SRobert Watson 			return ("UDD");
783d91be41SRobert Watson 		default:
795a246d29SRobert Watson 			return ("UD?");
803d91be41SRobert Watson 		}
813d91be41SRobert Watson 	default:
825a246d29SRobert Watson 		return ("?");
833d91be41SRobert Watson 	}
843d91be41SRobert Watson }
853d91be41SRobert Watson 
863d91be41SRobert Watson static void
873d91be41SRobert Watson addr_to_string(struct sockaddr_storage *ss, char *buffer, int buflen)
883d91be41SRobert Watson {
893d91be41SRobert Watson 	char buffer2[INET6_ADDRSTRLEN];
903d91be41SRobert Watson 	struct sockaddr_in6 *sin6;
913d91be41SRobert Watson 	struct sockaddr_in *sin;
923d91be41SRobert Watson 	struct sockaddr_un *sun;
933d91be41SRobert Watson 
943d91be41SRobert Watson 	switch (ss->ss_family) {
953d91be41SRobert Watson 	case AF_LOCAL:
963d91be41SRobert Watson 		sun = (struct sockaddr_un *)ss;
973d91be41SRobert Watson 		if (strlen(sun->sun_path) == 0)
983d91be41SRobert Watson 			strlcpy(buffer, "-", buflen);
993d91be41SRobert Watson 		else
1003d91be41SRobert Watson 			strlcpy(buffer, sun->sun_path, buflen);
1013d91be41SRobert Watson 		break;
1023d91be41SRobert Watson 
1033d91be41SRobert Watson 	case AF_INET:
1043d91be41SRobert Watson 		sin = (struct sockaddr_in *)ss;
1053d91be41SRobert Watson 		snprintf(buffer, buflen, "%s:%d", inet_ntoa(sin->sin_addr),
1063d91be41SRobert Watson 		    ntohs(sin->sin_port));
1073d91be41SRobert Watson 		break;
1083d91be41SRobert Watson 
1093d91be41SRobert Watson 	case AF_INET6:
1103d91be41SRobert Watson 		sin6 = (struct sockaddr_in6 *)ss;
1113d91be41SRobert Watson 		if (inet_ntop(AF_INET6, &sin6->sin6_addr, buffer2,
1123d91be41SRobert Watson 		    sizeof(buffer2)) != NULL)
1133d91be41SRobert Watson 			snprintf(buffer, buflen, "%s.%d", buffer2,
1143d91be41SRobert Watson 			    ntohs(sin6->sin6_port));
1153d91be41SRobert Watson 		else
1163d91be41SRobert Watson 			strlcpy(buffer, "-", sizeof(buffer));
1173d91be41SRobert Watson 		break;
1183d91be41SRobert Watson 
1193d91be41SRobert Watson 	default:
1203d91be41SRobert Watson 		strlcpy(buffer, "", buflen);
1213d91be41SRobert Watson 		break;
1223d91be41SRobert Watson 	}
1233d91be41SRobert Watson }
1243d91be41SRobert Watson 
1253d91be41SRobert Watson static void
1263d91be41SRobert Watson print_address(struct sockaddr_storage *ss)
1273d91be41SRobert Watson {
1283d91be41SRobert Watson 	char addr[PATH_MAX];
1293d91be41SRobert Watson 
1303d91be41SRobert Watson 	addr_to_string(ss, addr, sizeof(addr));
1315a246d29SRobert Watson 	printf("%s", addr);
1323d91be41SRobert Watson }
1333d91be41SRobert Watson 
1343d91be41SRobert Watson void
1353d91be41SRobert Watson procstat_files(pid_t pid, struct kinfo_proc *kipp)
1363d91be41SRobert Watson {
1373d91be41SRobert Watson 	struct kinfo_file *freep, *kif;
13843151ee6SPeter Wemm 	int i, cnt;
1393d91be41SRobert Watson 	const char *str;
1403d91be41SRobert Watson 
1413d91be41SRobert Watson 	if (!hflag)
142f2805949SJoe Marcus Clarke 		printf("%5s %-16s %4s %1s %1s %-8s %3s %7s %-3s %-12s\n",
1435a246d29SRobert Watson 		    "PID", "COMM", "FD", "T", "V", "FLAGS", "REF", "OFFSET",
1445a246d29SRobert Watson 		    "PRO", "NAME");
1453d91be41SRobert Watson 
14643151ee6SPeter Wemm 	freep = kinfo_getfile(pid, &cnt);
14708afefa8SJoe Marcus Clarke 	if (freep == NULL)
14808afefa8SJoe Marcus Clarke 		return;
14943151ee6SPeter Wemm 	for (i = 0; i < cnt; i++) {
15043151ee6SPeter Wemm 		kif = &freep[i];
1513d91be41SRobert Watson 
1523d91be41SRobert Watson 		printf("%5d ", pid);
1535a246d29SRobert Watson 		printf("%-16s ", kipp->ki_comm);
154f2805949SJoe Marcus Clarke 		switch (kif->kf_fd) {
155f2805949SJoe Marcus Clarke 		case KF_FD_TYPE_CWD:
156f2805949SJoe Marcus Clarke 			printf(" cwd ");
157f2805949SJoe Marcus Clarke 			break;
158f2805949SJoe Marcus Clarke 
159f2805949SJoe Marcus Clarke 		case KF_FD_TYPE_ROOT:
160f2805949SJoe Marcus Clarke 			printf("root ");
161f2805949SJoe Marcus Clarke 			break;
162f2805949SJoe Marcus Clarke 
163f2805949SJoe Marcus Clarke 		case KF_FD_TYPE_JAIL:
164f2805949SJoe Marcus Clarke 			printf("jail ");
165f2805949SJoe Marcus Clarke 			break;
166f2805949SJoe Marcus Clarke 
167f2805949SJoe Marcus Clarke 		default:
168f2805949SJoe Marcus Clarke 			printf("%4d ", kif->kf_fd);
169f2805949SJoe Marcus Clarke 			break;
170f2805949SJoe Marcus Clarke 		}
1713d91be41SRobert Watson 		switch (kif->kf_type) {
1723d91be41SRobert Watson 		case KF_TYPE_VNODE:
1733d91be41SRobert Watson 			str = "v";
1743d91be41SRobert Watson 			break;
1753d91be41SRobert Watson 
1763d91be41SRobert Watson 		case KF_TYPE_SOCKET:
1773d91be41SRobert Watson 			str = "s";
1783d91be41SRobert Watson 			break;
1793d91be41SRobert Watson 
1803d91be41SRobert Watson 		case KF_TYPE_PIPE:
1813d91be41SRobert Watson 			str = "p";
1823d91be41SRobert Watson 			break;
1833d91be41SRobert Watson 
1843d91be41SRobert Watson 		case KF_TYPE_FIFO:
1853d91be41SRobert Watson 			str = "f";
1863d91be41SRobert Watson 			break;
1873d91be41SRobert Watson 
1883d91be41SRobert Watson 		case KF_TYPE_KQUEUE:
1893d91be41SRobert Watson 			str = "k";
1903d91be41SRobert Watson 			break;
1913d91be41SRobert Watson 
1923d91be41SRobert Watson 		case KF_TYPE_CRYPTO:
1933d91be41SRobert Watson 			str = "c";
1943d91be41SRobert Watson 			break;
1953d91be41SRobert Watson 
1963d91be41SRobert Watson 		case KF_TYPE_MQUEUE:
1973d91be41SRobert Watson 			str = "m";
1983d91be41SRobert Watson 			break;
1993d91be41SRobert Watson 
20087cb56f6SRobert Watson 		case KF_TYPE_SHM:
20187cb56f6SRobert Watson 			str = "h";
20287cb56f6SRobert Watson 			break;
20387cb56f6SRobert Watson 
204bc093719SEd Schouten 		case KF_TYPE_PTS:
205bc093719SEd Schouten 			str = "t";
206bc093719SEd Schouten 			break;
207bc093719SEd Schouten 
2086bc1e9cdSJohn Baldwin 		case KF_TYPE_SEM:
2096bc1e9cdSJohn Baldwin 			str = "e";
2106bc1e9cdSJohn Baldwin 			break;
2116bc1e9cdSJohn Baldwin 
2123d91be41SRobert Watson 		case KF_TYPE_NONE:
2133d91be41SRobert Watson 		case KF_TYPE_UNKNOWN:
2143d91be41SRobert Watson 		default:
2153d91be41SRobert Watson 			str = "?";
2163d91be41SRobert Watson 			break;
2173d91be41SRobert Watson 		}
2183d91be41SRobert Watson 		printf("%1s ", str);
2193d91be41SRobert Watson 		str = "-";
2203d91be41SRobert Watson 		if (kif->kf_type == KF_TYPE_VNODE) {
2213d91be41SRobert Watson 			switch (kif->kf_vnode_type) {
2223d91be41SRobert Watson 			case KF_VTYPE_VREG:
2233d91be41SRobert Watson 				str = "r";
2243d91be41SRobert Watson 				break;
2253d91be41SRobert Watson 
2263d91be41SRobert Watson 			case KF_VTYPE_VDIR:
2273d91be41SRobert Watson 				str = "d";
2283d91be41SRobert Watson 				break;
2293d91be41SRobert Watson 
2303d91be41SRobert Watson 			case KF_VTYPE_VBLK:
2313d91be41SRobert Watson 				str = "b";
2323d91be41SRobert Watson 				break;
2333d91be41SRobert Watson 
2343d91be41SRobert Watson 			case KF_VTYPE_VCHR:
2353d91be41SRobert Watson 				str = "c";
2363d91be41SRobert Watson 				break;
2373d91be41SRobert Watson 
2383d91be41SRobert Watson 			case KF_VTYPE_VLNK:
2393d91be41SRobert Watson 				str = "l";
2403d91be41SRobert Watson 				break;
2413d91be41SRobert Watson 
2423d91be41SRobert Watson 			case KF_VTYPE_VSOCK:
2433d91be41SRobert Watson 				str = "s";
2443d91be41SRobert Watson 				break;
2453d91be41SRobert Watson 
2463d91be41SRobert Watson 			case KF_VTYPE_VFIFO:
2473d91be41SRobert Watson 				str = "f";
2483d91be41SRobert Watson 				break;
2493d91be41SRobert Watson 
2503d91be41SRobert Watson 			case KF_VTYPE_VBAD:
2513d91be41SRobert Watson 				str = "x";
2523d91be41SRobert Watson 				break;
2533d91be41SRobert Watson 
2543d91be41SRobert Watson 			case KF_VTYPE_VNON:
2553d91be41SRobert Watson 			case KF_VTYPE_UNKNOWN:
2563d91be41SRobert Watson 			default:
2573d91be41SRobert Watson 				str = "?";
2583d91be41SRobert Watson 				break;
2593d91be41SRobert Watson 			}
2603d91be41SRobert Watson 		}
2613d91be41SRobert Watson 		printf("%1s ", str);
2623d91be41SRobert Watson 		printf("%s", kif->kf_flags & KF_FLAG_READ ? "r" : "-");
2633d91be41SRobert Watson 		printf("%s", kif->kf_flags & KF_FLAG_WRITE ? "w" : "-");
2643d91be41SRobert Watson 		printf("%s", kif->kf_flags & KF_FLAG_APPEND ? "a" : "-");
2653d91be41SRobert Watson 		printf("%s", kif->kf_flags & KF_FLAG_ASYNC ? "s" : "-");
2663d91be41SRobert Watson 		printf("%s", kif->kf_flags & KF_FLAG_FSYNC ? "f" : "-");
2673d91be41SRobert Watson 		printf("%s", kif->kf_flags & KF_FLAG_NONBLOCK ? "n" : "-");
2683d91be41SRobert Watson 		printf("%s", kif->kf_flags & KF_FLAG_DIRECT ? "d" : "-");
2693d91be41SRobert Watson 		printf("%s ", kif->kf_flags & KF_FLAG_HASLOCK ? "l" : "-");
270f2805949SJoe Marcus Clarke 		if (kif->kf_ref_count > -1)
2713d91be41SRobert Watson 			printf("%3d ", kif->kf_ref_count);
272f2805949SJoe Marcus Clarke 		else
273f2805949SJoe Marcus Clarke 			printf("%3c ", '-');
274f2805949SJoe Marcus Clarke 		if (kif->kf_offset > -1)
2753d91be41SRobert Watson 			printf("%7jd ", (intmax_t)kif->kf_offset);
276f2805949SJoe Marcus Clarke 		else
277f2805949SJoe Marcus Clarke 			printf("%7c ", '-');
2783d91be41SRobert Watson 
2793d91be41SRobert Watson 		switch (kif->kf_type) {
2803d91be41SRobert Watson 		case KF_TYPE_VNODE:
2813d91be41SRobert Watson 		case KF_TYPE_FIFO:
282bc093719SEd Schouten 		case KF_TYPE_PTS:
2835a246d29SRobert Watson 			printf("%-3s ", "-");
2845a246d29SRobert Watson 			printf("%-18s", kif->kf_path);
2853d91be41SRobert Watson 			break;
2863d91be41SRobert Watson 
2873d91be41SRobert Watson 		case KF_TYPE_SOCKET:
2885a246d29SRobert Watson 			printf("%-3s ",
2893d91be41SRobert Watson 			    protocol_to_string(kif->kf_sock_domain,
2903d91be41SRobert Watson 			    kif->kf_sock_type, kif->kf_sock_protocol));
2913d91be41SRobert Watson 			/*
2923d91be41SRobert Watson 			 * While generally we like to print two addresses,
2933d91be41SRobert Watson 			 * local and peer, for sockets, it turns out to be
2943d91be41SRobert Watson 			 * more useful to print the first non-nul address for
2953d91be41SRobert Watson 			 * local sockets, as typically they aren't bound and
2963d91be41SRobert Watson 			 *  connected, and the path strings can get long.
2973d91be41SRobert Watson 			 */
2983d91be41SRobert Watson 			if (kif->kf_sock_domain == AF_LOCAL) {
2993d91be41SRobert Watson 				struct sockaddr_un *sun =
3003d91be41SRobert Watson 				    (struct sockaddr_un *)&kif->kf_sa_local;
3013d91be41SRobert Watson 
3023d91be41SRobert Watson 				if (sun->sun_path[0] != 0)
3033d91be41SRobert Watson 					print_address(&kif->kf_sa_local);
3043d91be41SRobert Watson 				else
3053d91be41SRobert Watson 					print_address(&kif->kf_sa_peer);
3063d91be41SRobert Watson 			} else {
3073d91be41SRobert Watson 				print_address(&kif->kf_sa_local);
3083d91be41SRobert Watson 				printf(" ");
3093d91be41SRobert Watson 				print_address(&kif->kf_sa_peer);
3103d91be41SRobert Watson 			}
3113d91be41SRobert Watson 			break;
3123d91be41SRobert Watson 
3133d91be41SRobert Watson 		default:
3145a246d29SRobert Watson 			printf("%-3s ", "-");
3155a246d29SRobert Watson 			printf("%-18s", "-");
3163d91be41SRobert Watson 		}
3173d91be41SRobert Watson 
3183d91be41SRobert Watson 		printf("\n");
3193d91be41SRobert Watson 	}
3203d91be41SRobert Watson 	free(freep);
3213d91be41SRobert Watson }
322