xref: /openbsd/usr.bin/kdump/ktrstruct.c (revision a984a0c3)
1 /*	$OpenBSD: ktrstruct.c,v 1.32 2024/07/26 19:16:31 guenther Exp $	*/
2 
3 /*-
4  * Copyright (c) 1988, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/types.h>
33 #include <sys/resource.h>
34 #include <sys/socket.h>
35 #include <sys/select.h>
36 #include <sys/stat.h>
37 #include <sys/time.h>
38 #include <sys/event.h>
39 #include <sys/un.h>
40 #include <sys/fcntl.h>
41 #include <ufs/ufs/quota.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
44 
45 #include <ctype.h>
46 #include <err.h>
47 #include <limits.h>
48 #include <netdb.h>
49 #include <poll.h>
50 #include <signal.h>
51 #include <stddef.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <stdint.h>
55 #include <string.h>
56 #include <grp.h>
57 #include <pwd.h>
58 #include <unistd.h>
59 #include <vis.h>
60 
61 #include "kdump.h"
62 #include "kdump_subr.h"
63 
64 #define TIME_FORMAT	"%b %e %T %Y"
65 
66 static void
ktrsockaddr(struct sockaddr * sa)67 ktrsockaddr(struct sockaddr *sa)
68 {
69 	/*
70 	 * TODO: Support additional address families
71 	 *	#include <netmpls/mpls.h>
72 	 *	struct sockaddr_mpls	*mpls;
73 	 */
74 
75 	/*
76 	 * note: ktrstruct() has already verified that sa points to a
77 	 * buffer at least sizeof(struct sockaddr) bytes long and exactly
78 	 * sa->sa_len bytes long.
79 	 */
80 	printf("struct sockaddr { ");
81 	sockfamilyname(sa->sa_family);
82 	printf(", ");
83 
84 #define check_sockaddr_len(n)					\
85 	if (sa_##n->s##n##_len < sizeof(struct sockaddr_##n)) {	\
86 		printf("invalid");				\
87 		break;						\
88 	}
89 
90 	switch(sa->sa_family) {
91 	case AF_INET: {
92 		struct sockaddr_in	*sa_in;
93 		char addr[INET_ADDRSTRLEN];
94 
95 		sa_in = (struct sockaddr_in *)sa;
96 		check_sockaddr_len(in);
97 		inet_ntop(AF_INET, &sa_in->sin_addr, addr, sizeof addr);
98 		printf("%s:%u", addr, ntohs(sa_in->sin_port));
99 		break;
100 	}
101 	case AF_INET6: {
102 		struct sockaddr_in6	*sa_in6;
103 		char addr[INET6_ADDRSTRLEN], scope[12] = { 0 };
104 
105 		sa_in6 = (struct sockaddr_in6 *)sa;
106 		check_sockaddr_len(in6);
107 		inet_ntop(AF_INET6, &sa_in6->sin6_addr, addr, sizeof addr);
108 		if (sa_in6->sin6_scope_id)
109 			snprintf(scope, sizeof(scope), "%%%u",
110 			    sa_in6->sin6_scope_id);
111 		printf("[%s%s]:%u", addr, scope, htons(sa_in6->sin6_port));
112 		break;
113 	}
114 	case AF_UNIX: {
115 		struct sockaddr_un *sa_un;
116 		char path[4 * sizeof(sa_un->sun_path) + 1];
117 		size_t len;
118 
119 		sa_un = (struct sockaddr_un *)sa;
120 		len = sa_un->sun_len;
121 		if (len <= offsetof(struct sockaddr_un, sun_path)) {
122 			printf("invalid");
123 			break;
124 		}
125 		len -= offsetof(struct sockaddr_un, sun_path);
126 		if (len > sizeof(sa_un->sun_path)) {
127 			printf("too long");
128 			break;
129 		}
130 		/* format, stopping at first NUL */
131 		len = strnlen(sa_un->sun_path, len);
132 		strvisx(path, sa_un->sun_path, len,
133 		    VIS_CSTYLE | VIS_DQ | VIS_TAB | VIS_NL);
134 		printf("\"%s\"", path);
135 		break;
136 	}
137 	default:
138 		printf("unknown address family");
139 	}
140 	printf(" }\n");
141 }
142 
143 static void
print_time(time_t t,int relative,int have_subsec)144 print_time(time_t t, int relative, int have_subsec)
145 {
146 	char timestr[PATH_MAX + 4];
147 	struct tm *tm;
148 
149 	if (t < 0 && have_subsec) {
150 		/* negative times with non-zero subsecs require care */
151 		printf("-%jd", -(intmax_t)(t + 1));
152 	} else
153 		printf("%jd", (intmax_t)t);
154 
155 	/* 1970s times are probably relative */
156 	if (!relative && t > (10 * 365 * 24 * 3600)) {
157 		tm = localtime(&t);
158 		if (tm != NULL) {
159 			(void)strftime(timestr, sizeof(timestr), TIME_FORMAT,
160 			    tm);
161 			printf("<\"%s\">", timestr);
162 		}
163 	}
164 }
165 
166 static void
print_timespec(const struct timespec * tsp,int relative)167 print_timespec(const struct timespec *tsp, int relative)
168 {
169 	if (tsp->tv_nsec == UTIME_NOW)
170 		printf("UTIME_NOW");
171 	else if (tsp->tv_nsec == UTIME_OMIT)
172 		printf("UTIME_OMIT");
173 	else {
174 		print_time(tsp->tv_sec, relative, tsp->tv_nsec);
175 		if (tsp->tv_nsec != 0)
176 			printf(".%09ld", tsp->tv_sec >= 0 ? tsp->tv_nsec :
177 			    1000000000 - tsp->tv_nsec);
178 	}
179 }
180 
181 void
uidname(int uid)182 uidname(int uid)
183 {
184 	const char *name;
185 
186 	if (uid == -1)
187 		printf("-1");
188 	else {
189 		printf("%u<", (unsigned)uid);
190 		if (uid > UID_MAX || (name = user_from_uid(uid, 1)) == NULL)
191 			printf("unknown>");
192 		else
193 			printf("\"%s\">", name);
194 	}
195 }
196 
197 void
gidname(int gid)198 gidname(int gid)
199 {
200 	const char *name;
201 
202 	if (gid == -1)
203 		printf("-1");
204 	else {
205 		printf("%u<", (unsigned)gid);
206 		if (gid > GID_MAX || (name = group_from_gid(gid, 1)) == NULL)
207 			printf("unknown>");
208 		else
209 			printf("\"%s\">", name);
210 	}
211 }
212 
213 static void
ktrstat(const struct stat * statp)214 ktrstat(const struct stat *statp)
215 {
216 	char mode[12];
217 
218 	/*
219 	 * note: ktrstruct() has already verified that statp points to a
220 	 * buffer exactly sizeof(struct stat) bytes long.
221 	 */
222 	printf("struct stat { ");
223 	strmode(statp->st_mode, mode);
224 	printf("dev=%d, ino=%llu, mode=%s, nlink=%u, uid=",
225 	    statp->st_dev, (unsigned long long)statp->st_ino,
226 	    mode, statp->st_nlink);
227 	uidname(statp->st_uid);
228 	printf(", gid=");
229 	gidname(statp->st_gid);
230 	printf(", rdev=%d, ", statp->st_rdev);
231 	printf("atime=");
232 	print_timespec(&statp->st_atim, 0);
233 	printf(", mtime=");
234 	print_timespec(&statp->st_mtim, 0);
235 	printf(", ctime=");
236 	print_timespec(&statp->st_ctim, 0);
237 	printf(", size=%lld, blocks=%lld, blksize=%d, flags=0x%x, gen=0x%x",
238 	    statp->st_size, statp->st_blocks, statp->st_blksize,
239 	    statp->st_flags, statp->st_gen);
240 	printf(" }\n");
241 }
242 
243 static void
ktrtimespec(const struct timespec * tsp,int relative)244 ktrtimespec(const struct timespec *tsp, int relative)
245 {
246 	printf("struct timespec { ");
247 	print_timespec(tsp, relative);
248 	printf(" }\n");
249 }
250 
251 static void
print_timeval(const struct timeval * tvp,int relative)252 print_timeval(const struct timeval *tvp, int relative)
253 {
254 	print_time(tvp->tv_sec, relative, tvp->tv_usec);
255 	if (tvp->tv_usec != 0)
256 		printf(".%06ld", tvp->tv_sec >= 0 ? tvp->tv_usec :
257 		    1000000 - tvp->tv_usec);
258 }
259 
260 static void
ktrtimeval(const struct timeval * tvp,int relative)261 ktrtimeval(const struct timeval *tvp, int relative)
262 {
263 	printf("struct timeval { ");
264 	print_timeval(tvp, relative);
265 	printf(" }\n");
266 }
267 
268 static void
ktritimerval(const struct itimerval * itvp)269 ktritimerval(const struct itimerval *itvp)
270 {
271 	printf("struct itimerval { value=");
272 	print_timeval(&itvp->it_value, 0);
273 	if (timerisset(&itvp->it_interval)) {
274 		printf(", interval=");
275 		print_timeval(&itvp->it_interval, 1);
276 	}
277 	printf(" }\n");
278 }
279 
280 static void
ktrsigaction(const struct sigaction * sa)281 ktrsigaction(const struct sigaction *sa)
282 {
283 	/*
284 	 * note: ktrstruct() has already verified that sa points to a
285 	 * buffer exactly sizeof(struct sigaction) bytes long.
286 	 */
287 	/*
288 	 * Fuck!  Comparison of function pointers on hppa assumes you can
289 	 * dereference them if they're plabels!  Cast everything to void *
290 	 * to suppress that extra logic; sorry folks, the address we report
291 	 * here might not match what you see in your executable...
292 	 */
293 	printf("struct sigaction { ");
294 	if ((void *)sa->sa_handler == (void *)SIG_DFL)
295 		printf("handler=SIG_DFL");
296 	else if ((void *)sa->sa_handler == (void *)SIG_IGN)
297 		printf("handler=SIG_IGN");
298 	else if (sa->sa_flags & SA_SIGINFO)
299 		printf("sigaction=%p", (void *)sa->sa_sigaction);
300 	else
301 		printf("handler=%p", (void *)sa->sa_handler);
302 	printf(", mask=");
303 	sigset(sa->sa_mask);
304 	printf(", flags=");
305 	sigactionflagname(sa->sa_flags);
306 	printf(" }\n");
307 }
308 
309 static void
print_rlim(rlim_t lim)310 print_rlim(rlim_t lim)
311 {
312 	if (lim == RLIM_INFINITY)
313 		printf("infinite");
314 	else
315 		printf("%llu", (unsigned long long)lim);
316 }
317 
318 static void
ktrrlimit(const struct rlimit * limp)319 ktrrlimit(const struct rlimit *limp)
320 {
321 	printf("struct rlimit { ");
322 	printf("cur=");
323 	print_rlim(limp->rlim_cur);
324 	printf(", max=");
325 	print_rlim(limp->rlim_max);
326 	printf(" }\n");
327 }
328 
329 static void
ktrtfork(const struct __tfork * tf)330 ktrtfork(const struct __tfork *tf)
331 {
332 	printf("struct __tfork { tcb=%p, tid=%p, stack=%p }\n",
333 	    tf->tf_tcb, (void *)tf->tf_tid, tf->tf_stack);
334 }
335 
336 static void
ktrfds(const char * data,size_t count)337 ktrfds(const char *data, size_t count)
338 {
339 	size_t i;
340 	int fd;
341 
342 	printf("int");
343 	if (count > 1)
344 		printf(" [%zu] { ", count);
345 	for (i = 0; i < count; i++) {
346 		memcpy(&fd, &data[i * sizeof(fd)], sizeof(fd));
347 		printf("%d%s", fd, i < count - 1 ? ", " : "");
348 	}
349 	if (count > 1)
350 		printf(" }");
351 	printf("\n");
352 }
353 
354 static void
ktrfdset(struct fd_set * fds,int len)355 ktrfdset(struct fd_set *fds, int len)
356 {
357 	int nfds, i, start = -1;
358 	char sep = ' ';
359 
360 	nfds = len * NBBY;
361 	printf("struct fd_set {");
362 	for (i = 0; i <= nfds; i++)
363 		if (i != nfds && FD_ISSET(i, fds)) {
364 			if (start == -1)
365 				start = i;
366 		} else if (start != -1) {
367 			putchar(sep);
368 			if (start == i - 1)
369 				printf("%d", start);
370 			else if (start == i - 2)
371 				printf("%d,%d", start, i - 1);
372 			else
373 				printf("%d-%d", start, i - 1);
374 			sep = ',';
375 			start = -1;
376 		}
377 
378 	printf(" }\n");
379 }
380 
381 static void
ktrrusage(const struct rusage * rup)382 ktrrusage(const struct rusage *rup)
383 {
384 	printf("struct rusage { utime=");
385 	print_timeval(&rup->ru_utime, 1);
386 	printf(", stime=");
387 	print_timeval(&rup->ru_stime, 1);
388 	printf(", maxrss=%ld, ixrss=%ld, idrss=%ld, isrss=%ld,"
389 	    " minflt=%ld, majflt=%ld, nswap=%ld, inblock=%ld,"
390 	    " oublock=%ld, msgsnd=%ld, msgrcv=%ld, nsignals=%ld,"
391 	    " nvcsw=%ld, nivcsw=%ld }\n",
392 	    rup->ru_maxrss, rup->ru_ixrss, rup->ru_idrss, rup->ru_isrss,
393 	    rup->ru_minflt, rup->ru_majflt, rup->ru_nswap, rup->ru_inblock,
394 	    rup->ru_oublock, rup->ru_msgsnd, rup->ru_msgrcv, rup->ru_nsignals,
395 	    rup->ru_nvcsw, rup->ru_nivcsw);
396 }
397 
398 static void
ktrquota(const struct dqblk * quota)399 ktrquota(const struct dqblk *quota)
400 {
401 	printf("struct dqblk { bhardlimit=%u, bsoftlimit=%u, curblocks=%u,"
402 	    " ihardlimit=%u, isoftlimit=%u, curinodes=%u, btime=",
403 	    quota->dqb_bhardlimit, quota->dqb_bsoftlimit,
404 	    quota->dqb_curblocks, quota->dqb_ihardlimit,
405 	    quota->dqb_isoftlimit, quota->dqb_curinodes);
406 	print_time(quota->dqb_btime, 0, 0);
407 	printf(", itime=");
408 	print_time(quota->dqb_itime, 0, 0);
409 	printf(" }\n");
410 }
411 
412 static void
ktrmmsghdr(const struct mmsghdr * mmsg)413 ktrmmsghdr(const struct mmsghdr *mmsg)
414 {
415 	printf("struct mmsghdr { msg_hdr = { name=%p, namelen=%u, "
416 	    "iov=%p, iovlen=%u, control=%p, controllen=%u, flags=",
417 	    mmsg->msg_hdr.msg_name, mmsg->msg_hdr.msg_namelen,
418 	    mmsg->msg_hdr.msg_iov, mmsg->msg_hdr.msg_iovlen,
419 	    mmsg->msg_hdr.msg_control, mmsg->msg_hdr.msg_controllen);
420 	sendrecvflagsname(mmsg->msg_hdr.msg_flags);
421 	printf(" }, msg_len = %u }\n", mmsg->msg_len);
422 }
423 
424 static void
ktrmsghdr(const struct msghdr * msg)425 ktrmsghdr(const struct msghdr *msg)
426 {
427 	printf("struct msghdr { name=%p, namelen=%u, iov=%p, iovlen=%u,"
428 	    " control=%p, controllen=%u, flags=",
429 	    msg->msg_name, msg->msg_namelen, msg->msg_iov, msg->msg_iovlen,
430 	    msg->msg_control, msg->msg_controllen);
431 	sendrecvflagsname(msg->msg_flags);
432 	printf(" }\n");
433 }
434 
435 static void
ktriovec(const char * data,int count)436 ktriovec(const char *data, int count)
437 {
438 	struct iovec iov;
439 	int i;
440 
441 	printf("struct iovec");
442 	if (count > 1)
443 		printf(" [%d]", count);
444 	for (i = 0; i < count; i++) {
445 		memcpy(&iov, data, sizeof(iov));
446 		data += sizeof(iov);
447 		printf(" { base=%p, len=%lu }", iov.iov_base, iov.iov_len);
448 	}
449 	printf("\n");
450 }
451 
452 static void
ktrevent(const char * data,int count)453 ktrevent(const char *data, int count)
454 {
455 	struct kevent kev;
456 	int i;
457 
458 	printf("struct kevent");
459 	if (count > 1)
460 		printf(" [%d]", count);
461 	for (i = 0; i < count; i++) {
462 		memcpy(&kev, data, sizeof(kev));
463 		data += sizeof(kev);
464 		printf(" { ident=%lu, filter=", kev.ident);
465 		evfiltername(kev.filter);
466 		printf(", flags=");
467 		evflagsname(kev.flags);
468 		printf(", fflags=");
469 		evfflagsname(kev.filter, kev.fflags);
470 		printf(", data=%llu", kev.data);
471 		if ((kev.flags & EV_ERROR) && fancy) {
472 			printf("<\"%s\">", strerror(kev.data));
473 		}
474 		printf(", udata=%p }", kev.udata);
475 	}
476 	printf("\n");
477 }
478 
479 static void
ktrpollfd(const char * data,int count)480 ktrpollfd(const char *data, int count)
481 {
482 	struct pollfd pfd;
483 	int i;
484 
485 	printf("struct pollfd");
486 	if (count > 1)
487 		printf(" [%d]", count);
488 	for (i = 0; i < count; i++) {
489 		memcpy(&pfd, data, sizeof(pfd));
490 		data += sizeof(pfd);
491 		printf(" { fd=%d, events=", pfd.fd);
492 		pollfdeventname(pfd.events);
493 		printf(", revents=");
494 		pollfdeventname(pfd.revents);
495 		printf(" }");
496 	}
497 	printf("\n");
498 }
499 
500 static void
ktrcmsghdr(char * data,socklen_t len)501 ktrcmsghdr(char *data, socklen_t len)
502 {
503 	struct msghdr msg;
504 	struct cmsghdr *cmsg;
505 	int i, count, *fds;
506 
507 	msg.msg_control = data;
508 	msg.msg_controllen = len;
509 
510 	/* count the control messages */
511 	count = 0;
512 	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
513 	     cmsg = CMSG_NXTHDR(&msg, cmsg)) {
514 		count++;
515 	}
516 
517 	printf("struct cmsghdr");
518 	if (count > 1)
519 		printf(" [%d]", count);
520 
521 	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
522 	     cmsg = CMSG_NXTHDR(&msg, cmsg)) {
523 		printf(" { len=%u, level=", cmsg->cmsg_len);
524 		if (cmsg->cmsg_level == SOL_SOCKET) {
525 			printf("SOL_SOCKET, type=");
526 			switch (cmsg->cmsg_type) {
527 			case SCM_RIGHTS:
528 				printf("SCM_RIGHTS, data=");
529 				fds = (int *)CMSG_DATA(cmsg);
530 				for (i = 0;
531 				    cmsg->cmsg_len > CMSG_LEN(sizeof(int) * i)
532 				    && (char *)fds + (i + 1) * sizeof(int) <=
533 				    data + len;
534 				    i++) {
535 					printf("%s%d", i ? "," : "", fds[i]);
536 				}
537 				break;
538 			case SCM_TIMESTAMP:
539 			default:
540 				printf("%d", cmsg->cmsg_type);
541 				break;
542 			}
543 		} else {
544 			struct protoent *p = getprotobynumber(cmsg->cmsg_level);
545 
546 			printf("%u<%s>, type=%d", cmsg->cmsg_level,
547 			    p != NULL ? p->p_name : "unknown", cmsg->cmsg_type);
548 		}
549 		printf(" }");
550 	}
551 	printf("\n");
552 }
553 
554 static void
ktrflock(const struct flock * fl)555 ktrflock(const struct flock *fl)
556 {
557 	printf("struct flock { start=%lld, len=%lld, pid=%d, type=",
558 	    fl->l_start, fl->l_len, fl->l_pid);
559 	flocktypename(fl->l_type);
560 	printf(", whence=");
561 	whencename(fl->l_whence);
562 	printf(" }\n");
563 }
564 
565 static void
ktrsiginfo(const siginfo_t * si)566 ktrsiginfo(const siginfo_t *si)
567 {
568 	printf("siginfo_t { ");
569 	siginfo(si, 1);
570 	printf(" }\n");
571 }
572 
573 void
ktrstruct(char * buf,size_t buflen)574 ktrstruct(char *buf, size_t buflen)
575 {
576 	char *name, *data;
577 	size_t namelen, datalen;
578 	int i;
579 
580 	for (name = buf, namelen = 0; namelen < buflen && name[namelen] != '\0';
581 	     ++namelen)
582 		/* nothing */;
583 	if (namelen == buflen)
584 		goto invalid;
585 	if (name[namelen] != '\0')
586 		goto invalid;
587 	data = buf + namelen + 1;
588 	datalen = buflen - namelen - 1;
589 
590 	/* sanity check */
591 	for (i = 0; i < namelen; ++i)
592 		if (!isalpha((unsigned char)name[i]))
593 			goto invalid;
594 	if (strcmp(name, "stat") == 0) {
595 		struct stat sb;
596 
597 		if (datalen != sizeof(struct stat))
598 			goto invalid;
599 		memcpy(&sb, data, datalen);
600 		ktrstat(&sb);
601 	} else if (strcmp(name, "sockaddr") == 0) {
602 		struct sockaddr_storage ss;
603 
604 		if (datalen > sizeof(ss))
605 			goto invalid;
606 		if (datalen < offsetof(struct sockaddr_storage, ss_len) +
607 		    sizeof(ss.ss_len))
608 			goto invalid;
609 		memcpy(&ss, data, datalen);
610 		if ((ss.ss_family != AF_UNIX &&
611 		    datalen < sizeof(struct sockaddr)) || datalen != ss.ss_len)
612 			goto invalid;
613 		ktrsockaddr((struct sockaddr *)&ss);
614 	} else if (strcmp(name, "abstimespec") == 0 ||
615 	    strcmp(name, "reltimespec") == 0) {
616 		struct timespec ts;
617 
618 		if (datalen != sizeof(ts))
619 			goto invalid;
620 		memcpy(&ts, data, datalen);
621 		ktrtimespec(&ts, name[0] == 'r');
622 	} else if (strcmp(name, "abstimeval") == 0 ||
623 	    strcmp(name, "reltimeval") == 0) {
624 		struct timeval tv;
625 
626 		if (datalen != sizeof(tv))
627 			goto invalid;
628 		memcpy(&tv, data, datalen);
629 		ktrtimeval(&tv, name[0] == 'r');
630 	} else if (strcmp(name, "itimerval") == 0) {
631 		struct itimerval itv;
632 
633 		if (datalen != sizeof(itv))
634 			goto invalid;
635 		memcpy(&itv, data, datalen);
636 		ktritimerval(&itv);
637 	} else if (strcmp(name, "sigaction") == 0) {
638 		struct sigaction sa;
639 
640 		if (datalen != sizeof(sa))
641 			goto invalid;
642 		memcpy(&sa, data, datalen);
643 		ktrsigaction(&sa);
644 	} else if (strcmp(name, "rlimit") == 0) {
645 		struct rlimit lim;
646 
647 		if (datalen != sizeof(lim))
648 			goto invalid;
649 		memcpy(&lim, data, datalen);
650 		ktrrlimit(&lim);
651 	} else if (strcmp(name, "rusage") == 0) {
652 		struct rusage ru;
653 
654 		if (datalen != sizeof(ru))
655 			goto invalid;
656 		memcpy(&ru, data, datalen);
657 		ktrrusage(&ru);
658 	} else if (strcmp(name, "tfork") == 0) {
659 		struct __tfork tf;
660 
661 		if (datalen != sizeof(tf))
662 			goto invalid;
663 		memcpy(&tf, data, datalen);
664 		ktrtfork(&tf);
665 	} else if (strcmp(name, "fds") == 0) {
666 		if (datalen % sizeof(int))
667 			goto invalid;
668 		ktrfds(data, datalen / sizeof(int));
669 	} else if (strcmp(name, "fdset") == 0) {
670 		struct fd_set *fds;
671 
672 		if ((fds = malloc(datalen)) == NULL)
673 			err(1, "malloc");
674 		memcpy(fds, data, datalen);
675 		ktrfdset(fds, datalen);
676 		free(fds);
677 	} else if (strcmp(name, "quota") == 0) {
678 		struct dqblk quota;
679 
680 		if (datalen != sizeof(quota))
681 			goto invalid;
682 		memcpy(&quota, data, datalen);
683 		ktrquota(&quota);
684 	} else if (strcmp(name, "msghdr") == 0) {
685 		struct msghdr msg;
686 
687 		if (datalen != sizeof(msg))
688 			goto invalid;
689 		memcpy(&msg, data, datalen);
690 		ktrmsghdr(&msg);
691 	} else if (strcmp(name, "mmsghdr") == 0) {
692 		struct mmsghdr mmsg;
693 
694 		if (datalen != sizeof(mmsg))
695 			goto invalid;
696 		memcpy(&mmsg, data, datalen);
697 		ktrmmsghdr(&mmsg);
698 	} else if (strcmp(name, "iovec") == 0) {
699 		if (datalen % sizeof(struct iovec))
700 			goto invalid;
701 		ktriovec(data, datalen / sizeof(struct iovec));
702 	} else if (strcmp(name, "kevent") == 0) {
703 		if (datalen % sizeof(struct kevent))
704 			goto invalid;
705 		ktrevent(data, datalen / sizeof(struct kevent));
706 	} else if (strcmp(name, "pollfd") == 0) {
707 		if (datalen % sizeof(struct pollfd))
708 			goto invalid;
709 		ktrpollfd(data, datalen / sizeof(struct pollfd));
710 	} else if (strcmp(name, "cmsghdr") == 0) {
711 		char *cmsg;
712 
713 		if (datalen == 0)
714 			goto invalid;
715 
716 		if ((cmsg = malloc(datalen)) == NULL)
717 			err(1, "malloc");
718 		memcpy(cmsg, data, datalen);
719 		ktrcmsghdr(cmsg, datalen);
720 		free(cmsg);
721 	} else if (strcmp(name, "pledgereq") == 0) {
722 		printf("promise=");
723 		showbufc(basecol + sizeof("promise=") - 1,
724 		    (unsigned char *)data, datalen, VIS_DQ | VIS_TAB | VIS_NL);
725 	} else if (strcmp(name, "pledgeexecreq") == 0) {
726 		printf("execpromise=");
727 		showbufc(basecol + sizeof("execpromise=") - 1,
728 		    (unsigned char *)data, datalen, VIS_DQ | VIS_TAB | VIS_NL);
729 	} else if (strcmp(name, "unveil") == 0) {
730 		printf("flags=");
731 		showbufc(basecol + sizeof("flags=") - 1,
732 		    (unsigned char *)data, datalen, VIS_DQ | VIS_TAB | VIS_NL);
733 	} else if (strcmp(name, "flock") == 0) {
734 		struct flock fl;
735 
736 		if (datalen != sizeof(fl))
737 			goto invalid;
738 		memcpy(&fl, data, datalen);
739 		ktrflock(&fl);
740 	} else if (strcmp(name, "siginfo") == 0) {
741 		siginfo_t si;
742 
743 		if (datalen != sizeof(si))
744 			goto invalid;
745 		memcpy(&si, data, datalen);
746 		ktrsiginfo(&si);
747 	} else {
748 		printf("unknown structure %s\n", name);
749 	}
750 	return;
751 invalid:
752 	printf("invalid record\n");
753 }
754