ktrstruct.c revision 1.16
1/* $OpenBSD: ktrstruct.c,v 1.16 2016/01/14 05:27:42 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/stat.h> 36#include <sys/time.h> 37#include <sys/event.h> 38#include <sys/un.h> 39#include <ufs/ufs/quota.h> 40#include <netinet/in.h> 41#include <arpa/inet.h> 42 43#include <ctype.h> 44#include <err.h> 45#include <limits.h> 46#include <netdb.h> 47#include <poll.h> 48#include <signal.h> 49#include <stddef.h> 50#include <stdio.h> 51#include <stdlib.h> 52#include <stdint.h> 53#include <string.h> 54#include <grp.h> 55#include <pwd.h> 56#include <unistd.h> 57 58#include "kdump.h" 59#include "kdump_subr.h" 60 61#define TIME_FORMAT "%b %e %T %Y" 62 63static void 64ktrsockaddr(struct sockaddr *sa) 65{ 66/* 67 TODO: Support additional address families 68 #include <netmpls/mpls.h> 69 struct sockaddr_mpls *mpls; 70*/ 71 char addr[64]; 72 73 /* 74 * note: ktrstruct() has already verified that sa points to a 75 * buffer at least sizeof(struct sockaddr) bytes long and exactly 76 * sa->sa_len bytes long. 77 */ 78 printf("struct sockaddr { "); 79 sockfamilyname(sa->sa_family); 80 printf(", "); 81 82#define check_sockaddr_len(n) \ 83 if (sa_##n->s##n##_len < sizeof(struct sockaddr_##n)) { \ 84 printf("invalid"); \ 85 break; \ 86 } 87 88 switch(sa->sa_family) { 89 case AF_INET: { 90 struct sockaddr_in *sa_in; 91 92 sa_in = (struct sockaddr_in *)sa; 93 check_sockaddr_len(in); 94 inet_ntop(AF_INET, &sa_in->sin_addr, addr, sizeof addr); 95 printf("%s:%u", addr, ntohs(sa_in->sin_port)); 96 break; 97 } 98 case AF_INET6: { 99 struct sockaddr_in6 *sa_in6; 100 101 sa_in6 = (struct sockaddr_in6 *)sa; 102 check_sockaddr_len(in6); 103 inet_ntop(AF_INET6, &sa_in6->sin6_addr, addr, sizeof addr); 104 printf("[%s]:%u", addr, htons(sa_in6->sin6_port)); 105 break; 106 } 107#ifdef IPX 108 case AF_IPX: { 109 struct sockaddr_ipx *sa_ipx; 110 111 sa_ipx = (struct sockaddr_ipx *)sa; 112 check_sockaddr_len(ipx); 113 /* XXX wish we had ipx_ntop */ 114 printf("%s", ipx_ntoa(sa_ipx->sipx_addr)); 115 break; 116 } 117#endif 118 case AF_UNIX: { 119 struct sockaddr_un *sa_un; 120 121 sa_un = (struct sockaddr_un *)sa; 122 if (sa_un->sun_len <= offsetof(struct sockaddr_un, sun_path)) { 123 printf("invalid"); 124 break; 125 } 126 printf("\"%.*s\"", (int)(sa_un->sun_len - 127 offsetof(struct sockaddr_un, sun_path)), 128 sa_un->sun_path); 129 break; 130 } 131 default: 132 printf("unknown address family"); 133 } 134 printf(" }\n"); 135} 136 137static void 138print_time(time_t t, int relative, int have_subsec) 139{ 140 char timestr[PATH_MAX + 4]; 141 struct tm *tm; 142 143 if (t < 0 && have_subsec) { 144 /* negative times with non-zero subsecs require care */ 145 printf("-%jd", -(intmax_t)(t + 1)); 146 } else 147 printf("%jd", (intmax_t)t); 148 149 if (!relative) { 150 tm = localtime(&t); 151 if (tm != NULL) { 152 (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, 153 tm); 154 printf("<\"%s\">", timestr); 155 } 156 } 157} 158 159static void 160print_timespec(const struct timespec *tsp, int relative) 161{ 162 if (tsp->tv_nsec == UTIME_NOW) 163 printf("UTIME_NOW"); 164 else if (tsp->tv_nsec == UTIME_OMIT) 165 printf("UTIME_OMIT"); 166 else { 167 print_time(tsp->tv_sec, relative, tsp->tv_nsec); 168 if (tsp->tv_nsec != 0) 169 printf(".%09ld", tsp->tv_sec >= 0 ? tsp->tv_nsec : 170 1000000000 - tsp->tv_nsec); 171 } 172} 173 174void 175uidname(int uid) 176{ 177 const char *name; 178 179 if (uid == -1) 180 printf("-1"); 181 else { 182 printf("%u<", (unsigned)uid); 183 if (uid > UID_MAX || (name = user_from_uid(uid, 1)) == NULL) 184 printf("unknown>"); 185 else 186 printf("\"%s\">", name); 187 } 188} 189 190void 191gidname(int gid) 192{ 193 const char *name; 194 195 if (gid == -1) 196 printf("-1"); 197 else { 198 printf("%u<", (unsigned)gid); 199 if (gid > GID_MAX || (name = group_from_gid(gid, 1)) == NULL) 200 printf("unknown>"); 201 else 202 printf("\"%s\">", name); 203 } 204} 205 206static void 207ktrstat(const struct stat *statp) 208{ 209 char mode[12]; 210 211 /* 212 * note: ktrstruct() has already verified that statp points to a 213 * buffer exactly sizeof(struct stat) bytes long. 214 */ 215 printf("struct stat { "); 216 strmode(statp->st_mode, mode); 217 printf("dev=%d, ino=%llu, mode=%s, nlink=%u, uid=", 218 statp->st_dev, (unsigned long long)statp->st_ino, 219 mode, statp->st_nlink); 220 uidname(statp->st_uid); 221 printf(", gid="); 222 gidname(statp->st_gid); 223 printf(", rdev=%d, ", statp->st_rdev); 224 printf("atime="); 225 print_timespec(&statp->st_atim, 0); 226 printf(", mtime="); 227 print_timespec(&statp->st_mtim, 0); 228 printf(", ctime="); 229 print_timespec(&statp->st_ctim, 0); 230 printf(", size=%lld, blocks=%lld, blksize=%d, flags=0x%x, gen=0x%x", 231 statp->st_size, statp->st_blocks, statp->st_blksize, 232 statp->st_flags, statp->st_gen); 233 printf(" }\n"); 234} 235 236static void 237ktrtimespec(const struct timespec *tsp, int relative) 238{ 239 printf("struct timespec { "); 240 print_timespec(tsp, relative); 241 printf(" }\n"); 242} 243 244static void 245print_timeval(const struct timeval *tvp, int relative) 246{ 247 print_time(tvp->tv_sec, relative, tvp->tv_usec); 248 if (tvp->tv_usec != 0) 249 printf(".%06ld", tvp->tv_sec >= 0 ? tvp->tv_usec : 250 1000000 - tvp->tv_usec); 251} 252 253static void 254ktrtimeval(const struct timeval *tvp, int relative) 255{ 256 printf("struct timeval { "); 257 print_timeval(tvp, relative); 258 printf(" }\n"); 259} 260 261static void 262ktrsigaction(const struct sigaction *sa) 263{ 264 /* 265 * note: ktrstruct() has already verified that sa points to a 266 * buffer exactly sizeof(struct sigaction) bytes long. 267 */ 268 printf("struct sigaction { "); 269 if (sa->sa_handler == SIG_DFL) 270 printf("handler=SIG_DFL"); 271 else if (sa->sa_handler == SIG_IGN) 272 printf("handler=SIG_IGN"); 273 else if (sa->sa_flags & SA_SIGINFO) 274 printf("sigaction=%p", (void *)sa->sa_sigaction); 275 else 276 printf("handler=%p", (void *)sa->sa_handler); 277 printf(", mask="); 278 sigset(sa->sa_mask); 279 printf(", flags="); 280 sigactionflagname(sa->sa_flags); 281 printf(" }\n"); 282} 283 284static void 285print_rlim(rlim_t lim) 286{ 287 if (lim == RLIM_INFINITY) 288 printf("infinite"); 289 else 290 printf("%llu", (unsigned long long)lim); 291} 292 293static void 294ktrrlimit(const struct rlimit *limp) 295{ 296 printf("struct rlimit { "); 297 printf("cur="); 298 print_rlim(limp->rlim_cur); 299 printf(", max="); 300 print_rlim(limp->rlim_max); 301 printf(" }\n"); 302} 303 304static void 305ktrtfork(const struct __tfork *tf) 306{ 307 printf("struct __tfork { tcb=%p, tid=%p, stack=%p }\n", 308 tf->tf_tcb, (void *)tf->tf_tid, tf->tf_stack); 309} 310 311static void 312ktrfdset(const struct fd_set *fds, int len) 313{ 314 int nfds, i, start = -1; 315 char sep = ' '; 316 317 nfds = len * NBBY; 318 printf("struct fd_set {"); 319 for (i = 0; i <= nfds; i++) 320 if (i != nfds && FD_ISSET(i, fds)) { 321 if (start == -1) 322 start = i; 323 } else if (start != -1) { 324 putchar(sep); 325 if (start == i - 1) 326 printf("%d", start); 327 else if (start == i - 2) 328 printf("%d,%d", start, i - 1); 329 else 330 printf("%d-%d", start, i - 1); 331 sep = ','; 332 start = -1; 333 } 334 335 printf(" }\n"); 336} 337 338static void 339ktrrusage(const struct rusage *rup) 340{ 341 printf("struct rusage { utime="); 342 print_timeval(&rup->ru_utime, 1); 343 printf(", stime="); 344 print_timeval(&rup->ru_stime, 1); 345 printf(", maxrss=%ld, ixrss=%ld, idrss=%ld, isrss=%ld," 346 " minflt=%ld, majflt=%ld, nswap=%ld, inblock=%ld," 347 " oublock=%ld, msgsnd=%ld, msgrcv=%ld, nsignals=%ld," 348 " nvcsw=%ld, nivcsw=%ld }\n", 349 rup->ru_maxrss, rup->ru_ixrss, rup->ru_idrss, rup->ru_isrss, 350 rup->ru_minflt, rup->ru_majflt, rup->ru_nswap, rup->ru_inblock, 351 rup->ru_oublock, rup->ru_msgsnd, rup->ru_msgrcv, rup->ru_nsignals, 352 rup->ru_nvcsw, rup->ru_nivcsw); 353} 354 355static void 356ktrquota(const struct dqblk *quota) 357{ 358 printf("struct dqblk { bhardlimit=%u, bsoftlimit=%u, curblocks=%u," 359 " ihardlimit=%u, isoftlimit=%u, curinodes=%u, btime=", 360 quota->dqb_bhardlimit, quota->dqb_bsoftlimit, 361 quota->dqb_curblocks, quota->dqb_ihardlimit, 362 quota->dqb_isoftlimit, quota->dqb_curinodes); 363 print_time(quota->dqb_btime, 0, 0); 364 printf(", itime="); 365 print_time(quota->dqb_itime, 0, 0); 366 printf(" }\n"); 367} 368 369static void 370ktrmsghdr(const struct msghdr *msg) 371{ 372 printf("struct msghdr { name=%p, namelen=%u, iov=%p, iovlen=%u," 373 " control=%p, controllen=%u, flags=", 374 msg->msg_name, msg->msg_namelen, msg->msg_iov, msg->msg_iovlen, 375 msg->msg_control, msg->msg_controllen); 376 sendrecvflagsname(msg->msg_flags); 377 printf(" }\n"); 378} 379 380static void 381ktriovec(const char *data, int count) 382{ 383 struct iovec iov; 384 int i; 385 386 printf("struct iovec"); 387 if (count > 1) 388 printf(" [%d]", count); 389 for (i = 0; i < count; i++) { 390 memcpy(&iov, data, sizeof(iov)); 391 data += sizeof(iov); 392 printf(" { base=%p, len=%lu }", iov.iov_base, iov.iov_len); 393 } 394 printf("\n"); 395} 396 397static void 398ktrevent(const char *data, int count) 399{ 400 struct kevent kev; 401 int i; 402 403 printf("struct kevent"); 404 if (count > 1) 405 printf(" [%d]", count); 406 for (i = 0; i < count; i++) { 407 memcpy(&kev, data, sizeof(kev)); 408 data += sizeof(kev); 409 printf(" { ident=%lu, filter=", kev.ident); 410 evfiltername(kev.filter); 411 printf(", flags="); 412 evflagsname(kev.flags); 413 printf(", fflags="); 414 evfflagsname(kev.filter, kev.fflags); 415 printf(", data=%llu", kev.data); 416 if ((kev.flags & EV_ERROR) && fancy) { 417 printf("<\"%s\">", strerror(kev.data)); 418 } 419 printf(", udata=%p }", kev.udata); 420 } 421 printf("\n"); 422} 423 424static void 425ktrcmsghdr(char *data, socklen_t len) 426{ 427 struct msghdr msg; 428 struct cmsghdr *cmsg; 429 int i, count, *fds; 430 431 msg.msg_control = data; 432 msg.msg_controllen = len; 433 434 /* count the control messages */ 435 count = 0; 436 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 437 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 438 count++; 439 } 440 441 printf("struct cmsghdr"); 442 if (count > 1) 443 printf(" [%d]", count); 444 445 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 446 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 447 printf(" { len=%u, level=", cmsg->cmsg_len); 448 if (cmsg->cmsg_level == SOL_SOCKET) { 449 printf("SOL_SOCKET, type="); 450 switch (cmsg->cmsg_type) { 451 case SCM_RIGHTS: 452 printf("SCM_RIGHTS, data="); 453 fds = (int *)CMSG_DATA(cmsg); 454 for (i = 0; 455 cmsg->cmsg_len > CMSG_LEN(sizeof(int) * i); 456 i++) { 457 printf("%s%d", i ? "," : "", fds[i]); 458 } 459 break; 460 case SCM_TIMESTAMP: 461 default: 462 printf("%d", cmsg->cmsg_type); 463 break; 464 } 465 } else { 466 struct protoent *p = getprotobynumber(cmsg->cmsg_level); 467 468 printf("%u<%s>, type=%d", cmsg->cmsg_level, 469 p != NULL ? p->p_name : "unknown", cmsg->cmsg_type); 470 } 471 printf(" }"); 472 } 473 printf("\n"); 474} 475 476void 477ktrstruct(char *buf, size_t buflen) 478{ 479 char *name, *data; 480 size_t namelen, datalen; 481 int i; 482 483 for (name = buf, namelen = 0; namelen < buflen && name[namelen] != '\0'; 484 ++namelen) 485 /* nothing */; 486 if (namelen == buflen) 487 goto invalid; 488 if (name[namelen] != '\0') 489 goto invalid; 490 data = buf + namelen + 1; 491 datalen = buflen - namelen - 1; 492 if (datalen == 0) 493 goto invalid; 494 /* sanity check */ 495 for (i = 0; i < namelen; ++i) 496 if (!isalpha((unsigned char)name[i])) 497 goto invalid; 498 if (strcmp(name, "stat") == 0) { 499 struct stat sb; 500 501 if (datalen != sizeof(struct stat)) 502 goto invalid; 503 memcpy(&sb, data, datalen); 504 ktrstat(&sb); 505 } else if (strcmp(name, "sockaddr") == 0) { 506 struct sockaddr_storage ss; 507 508 if (datalen > sizeof(ss)) 509 goto invalid; 510 memcpy(&ss, data, datalen); 511 if ((ss.ss_family != AF_UNIX && 512 datalen < sizeof(struct sockaddr)) || datalen != ss.ss_len) 513 goto invalid; 514 ktrsockaddr((struct sockaddr *)&ss); 515 } else if (strcmp(name, "abstimespec") == 0 || 516 strcmp(name, "reltimespec") == 0) { 517 struct timespec ts; 518 519 if (datalen != sizeof(ts)) 520 goto invalid; 521 memcpy(&ts, data, datalen); 522 ktrtimespec(&ts, name[0] == 'r'); 523 } else if (strcmp(name, "abstimeval") == 0 || 524 strcmp(name, "reltimeval") == 0) { 525 struct timeval tv; 526 527 if (datalen != sizeof(tv)) 528 goto invalid; 529 memcpy(&tv, data, datalen); 530 ktrtimeval(&tv, name[0] == 'r'); 531 } else if (strcmp(name, "sigaction") == 0) { 532 struct sigaction sa; 533 534 if (datalen != sizeof(sa)) 535 goto invalid; 536 memcpy(&sa, data, datalen); 537 ktrsigaction(&sa); 538 } else if (strcmp(name, "rlimit") == 0) { 539 struct rlimit lim; 540 541 if (datalen != sizeof(lim)) 542 goto invalid; 543 memcpy(&lim, data, datalen); 544 ktrrlimit(&lim); 545 } else if (strcmp(name, "rusage") == 0) { 546 struct rusage ru; 547 548 if (datalen != sizeof(ru)) 549 goto invalid; 550 memcpy(&ru, data, datalen); 551 ktrrusage(&ru); 552 } else if (strcmp(name, "tfork") == 0) { 553 struct __tfork tf; 554 555 if (datalen != sizeof(tf)) 556 goto invalid; 557 memcpy(&tf, data, datalen); 558 ktrtfork(&tf); 559 } else if (strcmp(name, "fdset") == 0) { 560 struct fd_set *fds; 561 562 if ((fds = malloc(datalen)) == NULL) 563 err(1, "malloc"); 564 memcpy(fds, data, datalen); 565 ktrfdset(fds, datalen); 566 free(fds); 567 } else if (strcmp(name, "quota") == 0) { 568 struct dqblk quota; 569 570 if (datalen != sizeof(quota)) 571 goto invalid; 572 memcpy("a, data, datalen); 573 ktrquota("a); 574 } else if (strcmp(name, "msghdr") == 0) { 575 struct msghdr msg; 576 577 if (datalen != sizeof(msg)) 578 goto invalid; 579 memcpy(&msg, data, datalen); 580 ktrmsghdr(&msg); 581 } else if (strcmp(name, "iovec") == 0) { 582 if (datalen % sizeof(struct iovec)) 583 goto invalid; 584 ktriovec(data, datalen / sizeof(struct iovec)); 585 } else if (strcmp(name, "kevent") == 0) { 586 if (datalen % sizeof(struct kevent)) 587 goto invalid; 588 ktrevent(data, datalen / sizeof(struct kevent)); 589 } else if (strcmp(name, "cmsghdr") == 0) { 590 char *cmsg; 591 592 if ((cmsg = malloc(datalen)) == NULL) 593 err(1, "malloc"); 594 memcpy(cmsg, data, datalen); 595 ktrcmsghdr(cmsg, datalen); 596 free(cmsg); 597 } else if (strcmp(name, "pledgereq") == 0) { 598 printf("pledge request="); 599 showbufc(basecol + sizeof("pledge request=") - 1, 600 (unsigned char *)data, datalen); 601 } else if (strcmp(name, "pledgepath") == 0) { 602 printf("pledge path="); 603 showbufc(basecol + sizeof("pledge path=") - 1, 604 (unsigned char *)data, datalen); 605 } else { 606 printf("unknown structure %s\n", name); 607 } 608 return; 609invalid: 610 printf("invalid record\n"); 611} 612