xref: /openbsd-src/usr.bin/kdump/ktrstruct.c (revision a984a0c3bbe9bd26145da0f9cdbbc52b679f5629)
1*a984a0c3Sguenther /*	$OpenBSD: ktrstruct.c,v 1.32 2024/07/26 19:16:31 guenther Exp $	*/
2dbedfdbcSguenther 
3dbedfdbcSguenther /*-
4dbedfdbcSguenther  * Copyright (c) 1988, 1993
5dbedfdbcSguenther  *	The Regents of the University of California.  All rights reserved.
6dbedfdbcSguenther  *
7dbedfdbcSguenther  * Redistribution and use in source and binary forms, with or without
8dbedfdbcSguenther  * modification, are permitted provided that the following conditions
9dbedfdbcSguenther  * are met:
10dbedfdbcSguenther  * 1. Redistributions of source code must retain the above copyright
11dbedfdbcSguenther  *    notice, this list of conditions and the following disclaimer.
12dbedfdbcSguenther  * 2. Redistributions in binary form must reproduce the above copyright
13dbedfdbcSguenther  *    notice, this list of conditions and the following disclaimer in the
14dbedfdbcSguenther  *    documentation and/or other materials provided with the distribution.
15dbedfdbcSguenther  * 3. Neither the name of the University nor the names of its contributors
16dbedfdbcSguenther  *    may be used to endorse or promote products derived from this software
17dbedfdbcSguenther  *    without specific prior written permission.
18dbedfdbcSguenther  *
19dbedfdbcSguenther  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20dbedfdbcSguenther  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21dbedfdbcSguenther  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22dbedfdbcSguenther  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23dbedfdbcSguenther  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24dbedfdbcSguenther  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25dbedfdbcSguenther  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26dbedfdbcSguenther  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27dbedfdbcSguenther  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28dbedfdbcSguenther  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29dbedfdbcSguenther  * SUCH DAMAGE.
30dbedfdbcSguenther  */
31dbedfdbcSguenther 
32dbedfdbcSguenther #include <sys/types.h>
33dbedfdbcSguenther #include <sys/resource.h>
34dbedfdbcSguenther #include <sys/socket.h>
3564a15077Sguenther #include <sys/select.h>
36dbedfdbcSguenther #include <sys/stat.h>
37dbedfdbcSguenther #include <sys/time.h>
381a72e1b0Stedu #include <sys/event.h>
39dbedfdbcSguenther #include <sys/un.h>
405c402730Santon #include <sys/fcntl.h>
411338505aSguenther #include <ufs/ufs/quota.h>
42dbedfdbcSguenther #include <netinet/in.h>
43dbedfdbcSguenther #include <arpa/inet.h>
44dbedfdbcSguenther 
45dbedfdbcSguenther #include <ctype.h>
46dbedfdbcSguenther #include <err.h>
47dbedfdbcSguenther #include <limits.h>
487003901fSguenther #include <netdb.h>
49dbedfdbcSguenther #include <poll.h>
50dbedfdbcSguenther #include <signal.h>
5154bca4b0Sguenther #include <stddef.h>
52dbedfdbcSguenther #include <stdio.h>
53dbedfdbcSguenther #include <stdlib.h>
54dbedfdbcSguenther #include <stdint.h>
55dbedfdbcSguenther #include <string.h>
56dbedfdbcSguenther #include <grp.h>
57dbedfdbcSguenther #include <pwd.h>
58dbedfdbcSguenther #include <unistd.h>
5980bc2255Sguenther #include <vis.h>
60dbedfdbcSguenther 
61dbedfdbcSguenther #include "kdump.h"
62dbedfdbcSguenther #include "kdump_subr.h"
63dbedfdbcSguenther 
64dbedfdbcSguenther #define TIME_FORMAT	"%b %e %T %Y"
65dbedfdbcSguenther 
66dbedfdbcSguenther static void
67dbedfdbcSguenther ktrsockaddr(struct sockaddr *sa)
68dbedfdbcSguenther {
69dbedfdbcSguenther 	/*
7080bc2255Sguenther 	 * TODO: Support additional address families
7180bc2255Sguenther 	 *	#include <netmpls/mpls.h>
7280bc2255Sguenther 	 *	struct sockaddr_mpls	*mpls;
73dbedfdbcSguenther 	 */
74dbedfdbcSguenther 
75dbedfdbcSguenther 	/*
76dbedfdbcSguenther 	 * note: ktrstruct() has already verified that sa points to a
77dbedfdbcSguenther 	 * buffer at least sizeof(struct sockaddr) bytes long and exactly
78dbedfdbcSguenther 	 * sa->sa_len bytes long.
79dbedfdbcSguenther 	 */
80dbedfdbcSguenther 	printf("struct sockaddr { ");
81dbedfdbcSguenther 	sockfamilyname(sa->sa_family);
82dbedfdbcSguenther 	printf(", ");
83dbedfdbcSguenther 
84dbedfdbcSguenther #define check_sockaddr_len(n)					\
85dbedfdbcSguenther 	if (sa_##n->s##n##_len < sizeof(struct sockaddr_##n)) {	\
86dbedfdbcSguenther 		printf("invalid");				\
87dbedfdbcSguenther 		break;						\
88dbedfdbcSguenther 	}
89dbedfdbcSguenther 
90dbedfdbcSguenther 	switch(sa->sa_family) {
91dbedfdbcSguenther 	case AF_INET: {
92dbedfdbcSguenther 		struct sockaddr_in	*sa_in;
939ec514d4Sotto 		char addr[INET_ADDRSTRLEN];
94dbedfdbcSguenther 
95dbedfdbcSguenther 		sa_in = (struct sockaddr_in *)sa;
96dbedfdbcSguenther 		check_sockaddr_len(in);
97dbedfdbcSguenther 		inet_ntop(AF_INET, &sa_in->sin_addr, addr, sizeof addr);
98dbedfdbcSguenther 		printf("%s:%u", addr, ntohs(sa_in->sin_port));
99dbedfdbcSguenther 		break;
100dbedfdbcSguenther 	}
101dbedfdbcSguenther 	case AF_INET6: {
102dbedfdbcSguenther 		struct sockaddr_in6	*sa_in6;
1039ec514d4Sotto 		char addr[INET6_ADDRSTRLEN], scope[12] = { 0 };
104dbedfdbcSguenther 
105dbedfdbcSguenther 		sa_in6 = (struct sockaddr_in6 *)sa;
106dbedfdbcSguenther 		check_sockaddr_len(in6);
107dbedfdbcSguenther 		inet_ntop(AF_INET6, &sa_in6->sin6_addr, addr, sizeof addr);
1089ec514d4Sotto 		if (sa_in6->sin6_scope_id)
1099ec514d4Sotto 			snprintf(scope, sizeof(scope), "%%%u",
1109ec514d4Sotto 			    sa_in6->sin6_scope_id);
1119ec514d4Sotto 		printf("[%s%s]:%u", addr, scope, htons(sa_in6->sin6_port));
112dbedfdbcSguenther 		break;
113dbedfdbcSguenther 	}
114dbedfdbcSguenther 	case AF_UNIX: {
115dbedfdbcSguenther 		struct sockaddr_un *sa_un;
11680bc2255Sguenther 		char path[4 * sizeof(sa_un->sun_path) + 1];
11780bc2255Sguenther 		size_t len;
118dbedfdbcSguenther 
119dbedfdbcSguenther 		sa_un = (struct sockaddr_un *)sa;
12080bc2255Sguenther 		len = sa_un->sun_len;
12180bc2255Sguenther 		if (len <= offsetof(struct sockaddr_un, sun_path)) {
122dbedfdbcSguenther 			printf("invalid");
123dbedfdbcSguenther 			break;
124dbedfdbcSguenther 		}
12580bc2255Sguenther 		len -= offsetof(struct sockaddr_un, sun_path);
12680bc2255Sguenther 		if (len > sizeof(sa_un->sun_path)) {
12780bc2255Sguenther 			printf("too long");
12880bc2255Sguenther 			break;
12980bc2255Sguenther 		}
13080bc2255Sguenther 		/* format, stopping at first NUL */
13180bc2255Sguenther 		len = strnlen(sa_un->sun_path, len);
13280bc2255Sguenther 		strvisx(path, sa_un->sun_path, len,
13380bc2255Sguenther 		    VIS_CSTYLE | VIS_DQ | VIS_TAB | VIS_NL);
13480bc2255Sguenther 		printf("\"%s\"", path);
135dbedfdbcSguenther 		break;
136dbedfdbcSguenther 	}
137dbedfdbcSguenther 	default:
138dbedfdbcSguenther 		printf("unknown address family");
139dbedfdbcSguenther 	}
140dbedfdbcSguenther 	printf(" }\n");
141dbedfdbcSguenther }
142dbedfdbcSguenther 
143dbedfdbcSguenther static void
144154ec7daSguenther print_time(time_t t, int relative, int have_subsec)
145dbedfdbcSguenther {
146dbedfdbcSguenther 	char timestr[PATH_MAX + 4];
147dbedfdbcSguenther 	struct tm *tm;
148dbedfdbcSguenther 
149154ec7daSguenther 	if (t < 0 && have_subsec) {
150154ec7daSguenther 		/* negative times with non-zero subsecs require care */
151154ec7daSguenther 		printf("-%jd", -(intmax_t)(t + 1));
152154ec7daSguenther 	} else
153dbedfdbcSguenther 		printf("%jd", (intmax_t)t);
154154ec7daSguenther 
1552f33c23dStedu 	/* 1970s times are probably relative */
1562f33c23dStedu 	if (!relative && t > (10 * 365 * 24 * 3600)) {
157dbedfdbcSguenther 		tm = localtime(&t);
15840f07bdcSjsg 		if (tm != NULL) {
15940f07bdcSjsg 			(void)strftime(timestr, sizeof(timestr), TIME_FORMAT,
16040f07bdcSjsg 			    tm);
161154ec7daSguenther 			printf("<\"%s\">", timestr);
162dbedfdbcSguenther 		}
163dbedfdbcSguenther 	}
16440f07bdcSjsg }
165dbedfdbcSguenther 
166dbedfdbcSguenther static void
167dbedfdbcSguenther print_timespec(const struct timespec *tsp, int relative)
168dbedfdbcSguenther {
169911117f3Sguenther 	if (tsp->tv_nsec == UTIME_NOW)
170911117f3Sguenther 		printf("UTIME_NOW");
171911117f3Sguenther 	else if (tsp->tv_nsec == UTIME_OMIT)
172911117f3Sguenther 		printf("UTIME_OMIT");
173154ec7daSguenther 	else {
174154ec7daSguenther 		print_time(tsp->tv_sec, relative, tsp->tv_nsec);
175dbedfdbcSguenther 		if (tsp->tv_nsec != 0)
176154ec7daSguenther 			printf(".%09ld", tsp->tv_sec >= 0 ? tsp->tv_nsec :
177154ec7daSguenther 			    1000000000 - tsp->tv_nsec);
178154ec7daSguenther 	}
179154ec7daSguenther }
180154ec7daSguenther 
181154ec7daSguenther void
182154ec7daSguenther uidname(int uid)
183154ec7daSguenther {
184154ec7daSguenther 	const char *name;
185154ec7daSguenther 
186154ec7daSguenther 	if (uid == -1)
187154ec7daSguenther 		printf("-1");
188154ec7daSguenther 	else {
189154ec7daSguenther 		printf("%u<", (unsigned)uid);
190154ec7daSguenther 		if (uid > UID_MAX || (name = user_from_uid(uid, 1)) == NULL)
191154ec7daSguenther 			printf("unknown>");
192154ec7daSguenther 		else
193154ec7daSguenther 			printf("\"%s\">", name);
194154ec7daSguenther 	}
195154ec7daSguenther }
196154ec7daSguenther 
197154ec7daSguenther void
198154ec7daSguenther gidname(int gid)
199154ec7daSguenther {
200154ec7daSguenther 	const char *name;
201154ec7daSguenther 
202154ec7daSguenther 	if (gid == -1)
203154ec7daSguenther 		printf("-1");
204154ec7daSguenther 	else {
205154ec7daSguenther 		printf("%u<", (unsigned)gid);
206154ec7daSguenther 		if (gid > GID_MAX || (name = group_from_gid(gid, 1)) == NULL)
207154ec7daSguenther 			printf("unknown>");
208154ec7daSguenther 		else
209154ec7daSguenther 			printf("\"%s\">", name);
210dbedfdbcSguenther 	}
211911117f3Sguenther }
212dbedfdbcSguenther 
213dbedfdbcSguenther static void
214dbedfdbcSguenther ktrstat(const struct stat *statp)
215dbedfdbcSguenther {
216dbedfdbcSguenther 	char mode[12];
217dbedfdbcSguenther 
218dbedfdbcSguenther 	/*
219dbedfdbcSguenther 	 * note: ktrstruct() has already verified that statp points to a
220dbedfdbcSguenther 	 * buffer exactly sizeof(struct stat) bytes long.
221dbedfdbcSguenther 	 */
222dbedfdbcSguenther 	printf("struct stat { ");
223dbedfdbcSguenther 	strmode(statp->st_mode, mode);
224154ec7daSguenther 	printf("dev=%d, ino=%llu, mode=%s, nlink=%u, uid=",
225dbedfdbcSguenther 	    statp->st_dev, (unsigned long long)statp->st_ino,
226dbedfdbcSguenther 	    mode, statp->st_nlink);
227154ec7daSguenther 	uidname(statp->st_uid);
228154ec7daSguenther 	printf(", gid=");
229154ec7daSguenther 	gidname(statp->st_gid);
230154ec7daSguenther 	printf(", rdev=%d, ", statp->st_rdev);
231dbedfdbcSguenther 	printf("atime=");
232dbedfdbcSguenther 	print_timespec(&statp->st_atim, 0);
233dbedfdbcSguenther 	printf(", mtime=");
234dbedfdbcSguenther 	print_timespec(&statp->st_mtim, 0);
235dbedfdbcSguenther 	printf(", ctime=");
236dbedfdbcSguenther 	print_timespec(&statp->st_ctim, 0);
2374b9a7a17Skrw 	printf(", size=%lld, blocks=%lld, blksize=%d, flags=0x%x, gen=0x%x",
238dbedfdbcSguenther 	    statp->st_size, statp->st_blocks, statp->st_blksize,
239dbedfdbcSguenther 	    statp->st_flags, statp->st_gen);
240dbedfdbcSguenther 	printf(" }\n");
241dbedfdbcSguenther }
242dbedfdbcSguenther 
243dbedfdbcSguenther static void
244dbedfdbcSguenther ktrtimespec(const struct timespec *tsp, int relative)
245dbedfdbcSguenther {
246dbedfdbcSguenther 	printf("struct timespec { ");
247dbedfdbcSguenther 	print_timespec(tsp, relative);
248dbedfdbcSguenther 	printf(" }\n");
249dbedfdbcSguenther }
250dbedfdbcSguenther 
251dbedfdbcSguenther static void
2527f86807eSguenther print_timeval(const struct timeval *tvp, int relative)
253dbedfdbcSguenther {
254154ec7daSguenther 	print_time(tvp->tv_sec, relative, tvp->tv_usec);
255dbedfdbcSguenther 	if (tvp->tv_usec != 0)
256154ec7daSguenther 		printf(".%06ld", tvp->tv_sec >= 0 ? tvp->tv_usec :
257154ec7daSguenther 		    1000000 - tvp->tv_usec);
2580bcd1a52Sguenther }
2597f86807eSguenther 
2607f86807eSguenther static void
2617f86807eSguenther ktrtimeval(const struct timeval *tvp, int relative)
2627f86807eSguenther {
2637f86807eSguenther 	printf("struct timeval { ");
2647f86807eSguenther 	print_timeval(tvp, relative);
265dbedfdbcSguenther 	printf(" }\n");
266dbedfdbcSguenther }
267dbedfdbcSguenther 
268dbedfdbcSguenther static void
269*a984a0c3Sguenther ktritimerval(const struct itimerval *itvp)
270*a984a0c3Sguenther {
271*a984a0c3Sguenther 	printf("struct itimerval { value=");
272*a984a0c3Sguenther 	print_timeval(&itvp->it_value, 0);
273*a984a0c3Sguenther 	if (timerisset(&itvp->it_interval)) {
274*a984a0c3Sguenther 		printf(", interval=");
275*a984a0c3Sguenther 		print_timeval(&itvp->it_interval, 1);
276*a984a0c3Sguenther 	}
277*a984a0c3Sguenther 	printf(" }\n");
278*a984a0c3Sguenther }
279*a984a0c3Sguenther 
280*a984a0c3Sguenther static void
281dbedfdbcSguenther ktrsigaction(const struct sigaction *sa)
282dbedfdbcSguenther {
283dbedfdbcSguenther 	/*
284dbedfdbcSguenther 	 * note: ktrstruct() has already verified that sa points to a
285dbedfdbcSguenther 	 * buffer exactly sizeof(struct sigaction) bytes long.
286dbedfdbcSguenther 	 */
2871357eed1Sguenther 	/*
2881357eed1Sguenther 	 * Fuck!  Comparison of function pointers on hppa assumes you can
2891357eed1Sguenther 	 * dereference them if they're plabels!  Cast everything to void *
2901357eed1Sguenther 	 * to suppress that extra logic; sorry folks, the address we report
2911357eed1Sguenther 	 * here might not match what you see in your executable...
2921357eed1Sguenther 	 */
293dbedfdbcSguenther 	printf("struct sigaction { ");
2941357eed1Sguenther 	if ((void *)sa->sa_handler == (void *)SIG_DFL)
295dbedfdbcSguenther 		printf("handler=SIG_DFL");
2961357eed1Sguenther 	else if ((void *)sa->sa_handler == (void *)SIG_IGN)
297dbedfdbcSguenther 		printf("handler=SIG_IGN");
298dbedfdbcSguenther 	else if (sa->sa_flags & SA_SIGINFO)
299dbedfdbcSguenther 		printf("sigaction=%p", (void *)sa->sa_sigaction);
300dbedfdbcSguenther 	else
301dbedfdbcSguenther 		printf("handler=%p", (void *)sa->sa_handler);
302dbedfdbcSguenther 	printf(", mask=");
303dbedfdbcSguenther 	sigset(sa->sa_mask);
304dbedfdbcSguenther 	printf(", flags=");
305dbedfdbcSguenther 	sigactionflagname(sa->sa_flags);
306dbedfdbcSguenther 	printf(" }\n");
307dbedfdbcSguenther }
308dbedfdbcSguenther 
309dbedfdbcSguenther static void
310dbedfdbcSguenther print_rlim(rlim_t lim)
311dbedfdbcSguenther {
312dbedfdbcSguenther 	if (lim == RLIM_INFINITY)
313dbedfdbcSguenther 		printf("infinite");
314dbedfdbcSguenther 	else
315dbedfdbcSguenther 		printf("%llu", (unsigned long long)lim);
316dbedfdbcSguenther }
317dbedfdbcSguenther 
318dbedfdbcSguenther static void
319dbedfdbcSguenther ktrrlimit(const struct rlimit *limp)
320dbedfdbcSguenther {
321dbedfdbcSguenther 	printf("struct rlimit { ");
322dbedfdbcSguenther 	printf("cur=");
323dbedfdbcSguenther 	print_rlim(limp->rlim_cur);
324dbedfdbcSguenther 	printf(", max=");
325dbedfdbcSguenther 	print_rlim(limp->rlim_max);
326dbedfdbcSguenther 	printf(" }\n");
327dbedfdbcSguenther }
328dbedfdbcSguenther 
329dbedfdbcSguenther static void
330dbedfdbcSguenther ktrtfork(const struct __tfork *tf)
331dbedfdbcSguenther {
332dbedfdbcSguenther 	printf("struct __tfork { tcb=%p, tid=%p, stack=%p }\n",
333dbedfdbcSguenther 	    tf->tf_tcb, (void *)tf->tf_tid, tf->tf_stack);
334dbedfdbcSguenther }
335dbedfdbcSguenther 
336dbedfdbcSguenther static void
337ee71c3a5Sguenther ktrfds(const char *data, size_t count)
338ee71c3a5Sguenther {
339ee71c3a5Sguenther 	size_t i;
340ee71c3a5Sguenther 	int fd;
341ee71c3a5Sguenther 
3425f257f27Sotto 	printf("int");
3435f257f27Sotto 	if (count > 1)
3445f257f27Sotto 		printf(" [%zu] { ", count);
3455f257f27Sotto 	for (i = 0; i < count; i++) {
346ee71c3a5Sguenther 		memcpy(&fd, &data[i * sizeof(fd)], sizeof(fd));
3475f257f27Sotto 		printf("%d%s", fd, i < count - 1 ? ", " : "");
348ee71c3a5Sguenther 	}
3495f257f27Sotto 	if (count > 1)
3505f257f27Sotto 		printf(" }");
3515f257f27Sotto 	printf("\n");
352ee71c3a5Sguenther }
353ee71c3a5Sguenther 
354ee71c3a5Sguenther static void
355aaf6c75dSguenther ktrfdset(struct fd_set *fds, int len)
356dbedfdbcSguenther {
357dbedfdbcSguenther 	int nfds, i, start = -1;
358dbedfdbcSguenther 	char sep = ' ';
359dbedfdbcSguenther 
360dbedfdbcSguenther 	nfds = len * NBBY;
361dbedfdbcSguenther 	printf("struct fd_set {");
362dbedfdbcSguenther 	for (i = 0; i <= nfds; i++)
363dbedfdbcSguenther 		if (i != nfds && FD_ISSET(i, fds)) {
364dbedfdbcSguenther 			if (start == -1)
365dbedfdbcSguenther 				start = i;
366dbedfdbcSguenther 		} else if (start != -1) {
367dbedfdbcSguenther 			putchar(sep);
368dbedfdbcSguenther 			if (start == i - 1)
369dbedfdbcSguenther 				printf("%d", start);
370dbedfdbcSguenther 			else if (start == i - 2)
371dbedfdbcSguenther 				printf("%d,%d", start, i - 1);
372dbedfdbcSguenther 			else
373dbedfdbcSguenther 				printf("%d-%d", start, i - 1);
374dbedfdbcSguenther 			sep = ',';
375dbedfdbcSguenther 			start = -1;
376dbedfdbcSguenther 		}
377dbedfdbcSguenther 
378dbedfdbcSguenther 	printf(" }\n");
379dbedfdbcSguenther }
380dbedfdbcSguenther 
3817f86807eSguenther static void
3827f86807eSguenther ktrrusage(const struct rusage *rup)
3837f86807eSguenther {
3847f86807eSguenther 	printf("struct rusage { utime=");
3857f86807eSguenther 	print_timeval(&rup->ru_utime, 1);
3867f86807eSguenther 	printf(", stime=");
3877f86807eSguenther 	print_timeval(&rup->ru_stime, 1);
3887f86807eSguenther 	printf(", maxrss=%ld, ixrss=%ld, idrss=%ld, isrss=%ld,"
3897f86807eSguenther 	    " minflt=%ld, majflt=%ld, nswap=%ld, inblock=%ld,"
3907f86807eSguenther 	    " oublock=%ld, msgsnd=%ld, msgrcv=%ld, nsignals=%ld,"
3917f86807eSguenther 	    " nvcsw=%ld, nivcsw=%ld }\n",
3927f86807eSguenther 	    rup->ru_maxrss, rup->ru_ixrss, rup->ru_idrss, rup->ru_isrss,
3937f86807eSguenther 	    rup->ru_minflt, rup->ru_majflt, rup->ru_nswap, rup->ru_inblock,
3947f86807eSguenther 	    rup->ru_oublock, rup->ru_msgsnd, rup->ru_msgrcv, rup->ru_nsignals,
3957f86807eSguenther 	    rup->ru_nvcsw, rup->ru_nivcsw);
3967f86807eSguenther }
3977f86807eSguenther 
3981338505aSguenther static void
3991338505aSguenther ktrquota(const struct dqblk *quota)
4001338505aSguenther {
4011338505aSguenther 	printf("struct dqblk { bhardlimit=%u, bsoftlimit=%u, curblocks=%u,"
4021338505aSguenther 	    " ihardlimit=%u, isoftlimit=%u, curinodes=%u, btime=",
4031338505aSguenther 	    quota->dqb_bhardlimit, quota->dqb_bsoftlimit,
4041338505aSguenther 	    quota->dqb_curblocks, quota->dqb_ihardlimit,
4051338505aSguenther 	    quota->dqb_isoftlimit, quota->dqb_curinodes);
406154ec7daSguenther 	print_time(quota->dqb_btime, 0, 0);
4071338505aSguenther 	printf(", itime=");
408154ec7daSguenther 	print_time(quota->dqb_itime, 0, 0);
4091338505aSguenther 	printf(" }\n");
4101338505aSguenther }
4111338505aSguenther 
4127003901fSguenther static void
4137b0c308aSmbuhl ktrmmsghdr(const struct mmsghdr *mmsg)
4147b0c308aSmbuhl {
4157b0c308aSmbuhl 	printf("struct mmsghdr { msg_hdr = { name=%p, namelen=%u, "
4167b0c308aSmbuhl 	    "iov=%p, iovlen=%u, control=%p, controllen=%u, flags=",
4177b0c308aSmbuhl 	    mmsg->msg_hdr.msg_name, mmsg->msg_hdr.msg_namelen,
4187b0c308aSmbuhl 	    mmsg->msg_hdr.msg_iov, mmsg->msg_hdr.msg_iovlen,
4197b0c308aSmbuhl 	    mmsg->msg_hdr.msg_control, mmsg->msg_hdr.msg_controllen);
4207b0c308aSmbuhl 	sendrecvflagsname(mmsg->msg_hdr.msg_flags);
4217b0c308aSmbuhl 	printf(" }, msg_len = %u }\n", mmsg->msg_len);
4227b0c308aSmbuhl }
4237b0c308aSmbuhl 
4247b0c308aSmbuhl static void
4257003901fSguenther ktrmsghdr(const struct msghdr *msg)
4267003901fSguenther {
4277003901fSguenther 	printf("struct msghdr { name=%p, namelen=%u, iov=%p, iovlen=%u,"
4288449a441Sguenther 	    " control=%p, controllen=%u, flags=",
4297003901fSguenther 	    msg->msg_name, msg->msg_namelen, msg->msg_iov, msg->msg_iovlen,
4308449a441Sguenther 	    msg->msg_control, msg->msg_controllen);
4318449a441Sguenther 	sendrecvflagsname(msg->msg_flags);
4328449a441Sguenther 	printf(" }\n");
4337003901fSguenther }
4347003901fSguenther 
4357003901fSguenther static void
4367003901fSguenther ktriovec(const char *data, int count)
4377003901fSguenther {
4387003901fSguenther 	struct iovec iov;
4397003901fSguenther 	int i;
4407003901fSguenther 
4417003901fSguenther 	printf("struct iovec");
4427003901fSguenther 	if (count > 1)
4437003901fSguenther 		printf(" [%d]", count);
4447003901fSguenther 	for (i = 0; i < count; i++) {
4457003901fSguenther 		memcpy(&iov, data, sizeof(iov));
4467003901fSguenther 		data += sizeof(iov);
4477003901fSguenther 		printf(" { base=%p, len=%lu }", iov.iov_base, iov.iov_len);
4487003901fSguenther 	}
4497003901fSguenther 	printf("\n");
4507003901fSguenther }
4517003901fSguenther 
4527003901fSguenther static void
4531a72e1b0Stedu ktrevent(const char *data, int count)
4541a72e1b0Stedu {
4551a72e1b0Stedu 	struct kevent kev;
4561a72e1b0Stedu 	int i;
4571a72e1b0Stedu 
4581a72e1b0Stedu 	printf("struct kevent");
4591a72e1b0Stedu 	if (count > 1)
4601a72e1b0Stedu 		printf(" [%d]", count);
4611a72e1b0Stedu 	for (i = 0; i < count; i++) {
4621a72e1b0Stedu 		memcpy(&kev, data, sizeof(kev));
4631a72e1b0Stedu 		data += sizeof(kev);
4648449a441Sguenther 		printf(" { ident=%lu, filter=", kev.ident);
4658449a441Sguenther 		evfiltername(kev.filter);
4668449a441Sguenther 		printf(", flags=");
4678449a441Sguenther 		evflagsname(kev.flags);
4688449a441Sguenther 		printf(", fflags=");
4698449a441Sguenther 		evfflagsname(kev.filter, kev.fflags);
4708449a441Sguenther 		printf(", data=%llu", kev.data);
4718449a441Sguenther 		if ((kev.flags & EV_ERROR) && fancy) {
4728449a441Sguenther 			printf("<\"%s\">", strerror(kev.data));
47329174d74Stedu 		}
4748449a441Sguenther 		printf(", udata=%p }", kev.udata);
4751a72e1b0Stedu 	}
4761a72e1b0Stedu 	printf("\n");
4771a72e1b0Stedu }
4781a72e1b0Stedu 
4791a72e1b0Stedu static void
480cd632112Sderaadt ktrpollfd(const char *data, int count)
481cd632112Sderaadt {
482cd632112Sderaadt 	struct pollfd pfd;
483cd632112Sderaadt 	int i;
484cd632112Sderaadt 
485cd632112Sderaadt 	printf("struct pollfd");
486cd632112Sderaadt 	if (count > 1)
487cd632112Sderaadt 		printf(" [%d]", count);
488cd632112Sderaadt 	for (i = 0; i < count; i++) {
489cd632112Sderaadt 		memcpy(&pfd, data, sizeof(pfd));
490cd632112Sderaadt 		data += sizeof(pfd);
491cd632112Sderaadt 		printf(" { fd=%d, events=", pfd.fd);
492cd632112Sderaadt 		pollfdeventname(pfd.events);
493cd632112Sderaadt 		printf(", revents=");
494cd632112Sderaadt 		pollfdeventname(pfd.revents);
495cd632112Sderaadt 		printf(" }");
496cd632112Sderaadt 	}
497cd632112Sderaadt 	printf("\n");
498cd632112Sderaadt }
499cd632112Sderaadt 
500cd632112Sderaadt static void
5017003901fSguenther ktrcmsghdr(char *data, socklen_t len)
5027003901fSguenther {
5037003901fSguenther 	struct msghdr msg;
5047003901fSguenther 	struct cmsghdr *cmsg;
5057003901fSguenther 	int i, count, *fds;
5067003901fSguenther 
5077003901fSguenther 	msg.msg_control = data;
5087003901fSguenther 	msg.msg_controllen = len;
5097003901fSguenther 
5107003901fSguenther 	/* count the control messages */
5117003901fSguenther 	count = 0;
5127003901fSguenther 	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
5137003901fSguenther 	     cmsg = CMSG_NXTHDR(&msg, cmsg)) {
5147003901fSguenther 		count++;
5157003901fSguenther 	}
5167003901fSguenther 
5177003901fSguenther 	printf("struct cmsghdr");
5187003901fSguenther 	if (count > 1)
5197003901fSguenther 		printf(" [%d]", count);
5207003901fSguenther 
5217003901fSguenther 	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
5227003901fSguenther 	     cmsg = CMSG_NXTHDR(&msg, cmsg)) {
5237003901fSguenther 		printf(" { len=%u, level=", cmsg->cmsg_len);
5247003901fSguenther 		if (cmsg->cmsg_level == SOL_SOCKET) {
5257003901fSguenther 			printf("SOL_SOCKET, type=");
5267003901fSguenther 			switch (cmsg->cmsg_type) {
5277003901fSguenther 			case SCM_RIGHTS:
5287003901fSguenther 				printf("SCM_RIGHTS, data=");
5297003901fSguenther 				fds = (int *)CMSG_DATA(cmsg);
5307003901fSguenther 				for (i = 0;
5312ff740a6Sclaudio 				    cmsg->cmsg_len > CMSG_LEN(sizeof(int) * i)
5322ff740a6Sclaudio 				    && (char *)fds + (i + 1) * sizeof(int) <=
5332ff740a6Sclaudio 				    data + len;
5347003901fSguenther 				    i++) {
5357003901fSguenther 					printf("%s%d", i ? "," : "", fds[i]);
5367003901fSguenther 				}
5377003901fSguenther 				break;
5387003901fSguenther 			case SCM_TIMESTAMP:
5397003901fSguenther 			default:
5407003901fSguenther 				printf("%d", cmsg->cmsg_type);
5417003901fSguenther 				break;
5427003901fSguenther 			}
5437003901fSguenther 		} else {
5447003901fSguenther 			struct protoent *p = getprotobynumber(cmsg->cmsg_level);
5457003901fSguenther 
5467003901fSguenther 			printf("%u<%s>, type=%d", cmsg->cmsg_level,
5477003901fSguenther 			    p != NULL ? p->p_name : "unknown", cmsg->cmsg_type);
5487003901fSguenther 		}
5497003901fSguenther 		printf(" }");
5507003901fSguenther 	}
5517003901fSguenther 	printf("\n");
5527003901fSguenther }
5537003901fSguenther 
5545c402730Santon static void
5555c402730Santon ktrflock(const struct flock *fl)
5565c402730Santon {
5575c402730Santon 	printf("struct flock { start=%lld, len=%lld, pid=%d, type=",
5585c402730Santon 	    fl->l_start, fl->l_len, fl->l_pid);
5595c402730Santon 	flocktypename(fl->l_type);
5605c402730Santon 	printf(", whence=");
5615c402730Santon 	whencename(fl->l_whence);
5625c402730Santon 	printf(" }\n");
5635c402730Santon }
5645c402730Santon 
56579b24ea9Sguenther static void
56679b24ea9Sguenther ktrsiginfo(const siginfo_t *si)
56779b24ea9Sguenther {
56879b24ea9Sguenther 	printf("siginfo_t { ");
56979b24ea9Sguenther 	siginfo(si, 1);
57079b24ea9Sguenther 	printf(" }\n");
57179b24ea9Sguenther }
57279b24ea9Sguenther 
573dbedfdbcSguenther void
574dbedfdbcSguenther ktrstruct(char *buf, size_t buflen)
575dbedfdbcSguenther {
576dbedfdbcSguenther 	char *name, *data;
577dbedfdbcSguenther 	size_t namelen, datalen;
578dbedfdbcSguenther 	int i;
579dbedfdbcSguenther 
580dbedfdbcSguenther 	for (name = buf, namelen = 0; namelen < buflen && name[namelen] != '\0';
581dbedfdbcSguenther 	     ++namelen)
582dbedfdbcSguenther 		/* nothing */;
583dbedfdbcSguenther 	if (namelen == buflen)
584dbedfdbcSguenther 		goto invalid;
585dbedfdbcSguenther 	if (name[namelen] != '\0')
586dbedfdbcSguenther 		goto invalid;
587dbedfdbcSguenther 	data = buf + namelen + 1;
588dbedfdbcSguenther 	datalen = buflen - namelen - 1;
5895f257f27Sotto 
590dbedfdbcSguenther 	/* sanity check */
591dbedfdbcSguenther 	for (i = 0; i < namelen; ++i)
592dbedfdbcSguenther 		if (!isalpha((unsigned char)name[i]))
593dbedfdbcSguenther 			goto invalid;
594dbedfdbcSguenther 	if (strcmp(name, "stat") == 0) {
595dbedfdbcSguenther 		struct stat sb;
596dbedfdbcSguenther 
597dbedfdbcSguenther 		if (datalen != sizeof(struct stat))
598dbedfdbcSguenther 			goto invalid;
599dbedfdbcSguenther 		memcpy(&sb, data, datalen);
600dbedfdbcSguenther 		ktrstat(&sb);
601dbedfdbcSguenther 	} else if (strcmp(name, "sockaddr") == 0) {
602dbedfdbcSguenther 		struct sockaddr_storage ss;
603dbedfdbcSguenther 
604dbedfdbcSguenther 		if (datalen > sizeof(ss))
605dbedfdbcSguenther 			goto invalid;
6065f257f27Sotto 		if (datalen < offsetof(struct sockaddr_storage, ss_len) +
6075f257f27Sotto 		    sizeof(ss.ss_len))
6085f257f27Sotto 			goto invalid;
609dbedfdbcSguenther 		memcpy(&ss, data, datalen);
610dbedfdbcSguenther 		if ((ss.ss_family != AF_UNIX &&
611dbedfdbcSguenther 		    datalen < sizeof(struct sockaddr)) || datalen != ss.ss_len)
612dbedfdbcSguenther 			goto invalid;
613dbedfdbcSguenther 		ktrsockaddr((struct sockaddr *)&ss);
614dbedfdbcSguenther 	} else if (strcmp(name, "abstimespec") == 0 ||
615dbedfdbcSguenther 	    strcmp(name, "reltimespec") == 0) {
616dbedfdbcSguenther 		struct timespec ts;
617dbedfdbcSguenther 
618dbedfdbcSguenther 		if (datalen != sizeof(ts))
619dbedfdbcSguenther 			goto invalid;
620dbedfdbcSguenther 		memcpy(&ts, data, datalen);
621dbedfdbcSguenther 		ktrtimespec(&ts, name[0] == 'r');
622dbedfdbcSguenther 	} else if (strcmp(name, "abstimeval") == 0 ||
623dbedfdbcSguenther 	    strcmp(name, "reltimeval") == 0) {
624dbedfdbcSguenther 		struct timeval tv;
625dbedfdbcSguenther 
626dbedfdbcSguenther 		if (datalen != sizeof(tv))
627dbedfdbcSguenther 			goto invalid;
628dbedfdbcSguenther 		memcpy(&tv, data, datalen);
629dbedfdbcSguenther 		ktrtimeval(&tv, name[0] == 'r');
630*a984a0c3Sguenther 	} else if (strcmp(name, "itimerval") == 0) {
631*a984a0c3Sguenther 		struct itimerval itv;
632*a984a0c3Sguenther 
633*a984a0c3Sguenther 		if (datalen != sizeof(itv))
634*a984a0c3Sguenther 			goto invalid;
635*a984a0c3Sguenther 		memcpy(&itv, data, datalen);
636*a984a0c3Sguenther 		ktritimerval(&itv);
637dbedfdbcSguenther 	} else if (strcmp(name, "sigaction") == 0) {
638dbedfdbcSguenther 		struct sigaction sa;
639dbedfdbcSguenther 
640dbedfdbcSguenther 		if (datalen != sizeof(sa))
641dbedfdbcSguenther 			goto invalid;
642dbedfdbcSguenther 		memcpy(&sa, data, datalen);
643dbedfdbcSguenther 		ktrsigaction(&sa);
644dbedfdbcSguenther 	} else if (strcmp(name, "rlimit") == 0) {
645dbedfdbcSguenther 		struct rlimit lim;
646dbedfdbcSguenther 
647dbedfdbcSguenther 		if (datalen != sizeof(lim))
648dbedfdbcSguenther 			goto invalid;
649dbedfdbcSguenther 		memcpy(&lim, data, datalen);
650dbedfdbcSguenther 		ktrrlimit(&lim);
6517f86807eSguenther 	} else if (strcmp(name, "rusage") == 0) {
6527f86807eSguenther 		struct rusage ru;
6537f86807eSguenther 
6547f86807eSguenther 		if (datalen != sizeof(ru))
6557f86807eSguenther 			goto invalid;
6567f86807eSguenther 		memcpy(&ru, data, datalen);
6577f86807eSguenther 		ktrrusage(&ru);
658dbedfdbcSguenther 	} else if (strcmp(name, "tfork") == 0) {
659dbedfdbcSguenther 		struct __tfork tf;
660dbedfdbcSguenther 
661dbedfdbcSguenther 		if (datalen != sizeof(tf))
662dbedfdbcSguenther 			goto invalid;
663dbedfdbcSguenther 		memcpy(&tf, data, datalen);
664dbedfdbcSguenther 		ktrtfork(&tf);
665ee71c3a5Sguenther 	} else if (strcmp(name, "fds") == 0) {
666ee71c3a5Sguenther 		if (datalen % sizeof(int))
667ee71c3a5Sguenther 			goto invalid;
668ee71c3a5Sguenther 		ktrfds(data, datalen / sizeof(int));
669dbedfdbcSguenther 	} else if (strcmp(name, "fdset") == 0) {
670dbedfdbcSguenther 		struct fd_set *fds;
6717003901fSguenther 
672dbedfdbcSguenther 		if ((fds = malloc(datalen)) == NULL)
673dbedfdbcSguenther 			err(1, "malloc");
674dbedfdbcSguenther 		memcpy(fds, data, datalen);
675dbedfdbcSguenther 		ktrfdset(fds, datalen);
676dbedfdbcSguenther 		free(fds);
6771338505aSguenther 	} else if (strcmp(name, "quota") == 0) {
6781338505aSguenther 		struct dqblk quota;
6791338505aSguenther 
6801338505aSguenther 		if (datalen != sizeof(quota))
6811338505aSguenther 			goto invalid;
6821338505aSguenther 		memcpy(&quota, data, datalen);
6831338505aSguenther 		ktrquota(&quota);
6847003901fSguenther 	} else if (strcmp(name, "msghdr") == 0) {
6857003901fSguenther 		struct msghdr msg;
6867003901fSguenther 
6877003901fSguenther 		if (datalen != sizeof(msg))
6887003901fSguenther 			goto invalid;
6897003901fSguenther 		memcpy(&msg, data, datalen);
6907003901fSguenther 		ktrmsghdr(&msg);
6917b0c308aSmbuhl 	} else if (strcmp(name, "mmsghdr") == 0) {
6927b0c308aSmbuhl 		struct mmsghdr mmsg;
6937b0c308aSmbuhl 
6947b0c308aSmbuhl 		if (datalen != sizeof(mmsg))
6957b0c308aSmbuhl 			goto invalid;
6967b0c308aSmbuhl 		memcpy(&mmsg, data, datalen);
6977b0c308aSmbuhl 		ktrmmsghdr(&mmsg);
6987003901fSguenther 	} else if (strcmp(name, "iovec") == 0) {
6997003901fSguenther 		if (datalen % sizeof(struct iovec))
7007003901fSguenther 			goto invalid;
7017003901fSguenther 		ktriovec(data, datalen / sizeof(struct iovec));
7021a72e1b0Stedu 	} else if (strcmp(name, "kevent") == 0) {
7031a72e1b0Stedu 		if (datalen % sizeof(struct kevent))
7041a72e1b0Stedu 			goto invalid;
7051a72e1b0Stedu 		ktrevent(data, datalen / sizeof(struct kevent));
706cd632112Sderaadt 	} else if (strcmp(name, "pollfd") == 0) {
707cd632112Sderaadt 		if (datalen % sizeof(struct pollfd))
708cd632112Sderaadt 			goto invalid;
709cd632112Sderaadt 		ktrpollfd(data, datalen / sizeof(struct pollfd));
7107003901fSguenther 	} else if (strcmp(name, "cmsghdr") == 0) {
7117003901fSguenther 		char *cmsg;
7127003901fSguenther 
7135f257f27Sotto 		if (datalen == 0)
7145f257f27Sotto 			goto invalid;
7155f257f27Sotto 
7167003901fSguenther 		if ((cmsg = malloc(datalen)) == NULL)
7177003901fSguenther 			err(1, "malloc");
7187003901fSguenther 		memcpy(cmsg, data, datalen);
7197003901fSguenther 		ktrcmsghdr(cmsg, datalen);
7207003901fSguenther 		free(cmsg);
7210bd1216cSderaadt 	} else if (strcmp(name, "pledgereq") == 0) {
7224ea7ed56Sderaadt 		printf("promise=");
7234ea7ed56Sderaadt 		showbufc(basecol + sizeof("promise=") - 1,
72480bc2255Sguenther 		    (unsigned char *)data, datalen, VIS_DQ | VIS_TAB | VIS_NL);
7254ea7ed56Sderaadt 	} else if (strcmp(name, "pledgeexecreq") == 0) {
7264ea7ed56Sderaadt 		printf("execpromise=");
7274ea7ed56Sderaadt 		showbufc(basecol + sizeof("execpromise=") - 1,
72880bc2255Sguenther 		    (unsigned char *)data, datalen, VIS_DQ | VIS_TAB | VIS_NL);
7298b23add8Sbeck 	} else if (strcmp(name, "unveil") == 0) {
7308b23add8Sbeck 		printf("flags=");
7318b23add8Sbeck 		showbufc(basecol + sizeof("flags=") - 1,
7328b23add8Sbeck 		    (unsigned char *)data, datalen, VIS_DQ | VIS_TAB | VIS_NL);
7335c402730Santon 	} else if (strcmp(name, "flock") == 0) {
7345c402730Santon 		struct flock fl;
7355c402730Santon 
7365c402730Santon 		if (datalen != sizeof(fl))
7375c402730Santon 			goto invalid;
7385c402730Santon 		memcpy(&fl, data, datalen);
7395c402730Santon 		ktrflock(&fl);
74079b24ea9Sguenther 	} else if (strcmp(name, "siginfo") == 0) {
74179b24ea9Sguenther 		siginfo_t si;
74279b24ea9Sguenther 
74379b24ea9Sguenther 		if (datalen != sizeof(si))
74479b24ea9Sguenther 			goto invalid;
74579b24ea9Sguenther 		memcpy(&si, data, datalen);
74679b24ea9Sguenther 		ktrsiginfo(&si);
747dbedfdbcSguenther 	} else {
748dbedfdbcSguenther 		printf("unknown structure %s\n", name);
749dbedfdbcSguenther 	}
750dbedfdbcSguenther 	return;
751dbedfdbcSguenther invalid:
752dbedfdbcSguenther 	printf("invalid record\n");
753dbedfdbcSguenther }
754