ktrstruct.c revision 1.14
1/* $OpenBSD: ktrstruct.c,v 1.14 2015/12/25 02:11:47 tedu 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=%d }\n", 374 msg->msg_name, msg->msg_namelen, msg->msg_iov, msg->msg_iovlen, 375 msg->msg_control, msg->msg_controllen, msg->msg_flags); 376} 377 378static void 379ktriovec(const char *data, int count) 380{ 381 struct iovec iov; 382 int i; 383 384 printf("struct iovec"); 385 if (count > 1) 386 printf(" [%d]", count); 387 for (i = 0; i < count; i++) { 388 memcpy(&iov, data, sizeof(iov)); 389 data += sizeof(iov); 390 printf(" { base=%p, len=%lu }", iov.iov_base, iov.iov_len); 391 } 392 printf("\n"); 393} 394 395static void 396ktrevent(const char *data, int count) 397{ 398 struct kevent kev; 399 int i; 400 401 printf("struct kevent"); 402 if (count > 1) 403 printf(" [%d]", count); 404 for (i = 0; i < count; i++) { 405 memcpy(&kev, data, sizeof(kev)); 406 data += sizeof(kev); 407 printf(" { ident=%lu }", kev.ident); 408 } 409 printf("\n"); 410} 411 412static void 413ktrcmsghdr(char *data, socklen_t len) 414{ 415 struct msghdr msg; 416 struct cmsghdr *cmsg; 417 int i, count, *fds; 418 419 msg.msg_control = data; 420 msg.msg_controllen = len; 421 422 /* count the control messages */ 423 count = 0; 424 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 425 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 426 count++; 427 } 428 429 printf("struct cmsghdr"); 430 if (count > 1) 431 printf(" [%d]", count); 432 433 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 434 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 435 printf(" { len=%u, level=", cmsg->cmsg_len); 436 if (cmsg->cmsg_level == SOL_SOCKET) { 437 printf("SOL_SOCKET, type="); 438 switch (cmsg->cmsg_type) { 439 case SCM_RIGHTS: 440 printf("SCM_RIGHTS, data="); 441 fds = (int *)CMSG_DATA(cmsg); 442 for (i = 0; 443 cmsg->cmsg_len > CMSG_LEN(sizeof(int) * i); 444 i++) { 445 printf("%s%d", i ? "," : "", fds[i]); 446 } 447 break; 448 case SCM_TIMESTAMP: 449 default: 450 printf("%d", cmsg->cmsg_type); 451 break; 452 } 453 } else { 454 struct protoent *p = getprotobynumber(cmsg->cmsg_level); 455 456 printf("%u<%s>, type=%d", cmsg->cmsg_level, 457 p != NULL ? p->p_name : "unknown", cmsg->cmsg_type); 458 } 459 printf(" }"); 460 } 461 printf("\n"); 462} 463 464void 465ktrstruct(char *buf, size_t buflen) 466{ 467 char *name, *data; 468 size_t namelen, datalen; 469 int i; 470 471 for (name = buf, namelen = 0; namelen < buflen && name[namelen] != '\0'; 472 ++namelen) 473 /* nothing */; 474 if (namelen == buflen) 475 goto invalid; 476 if (name[namelen] != '\0') 477 goto invalid; 478 data = buf + namelen + 1; 479 datalen = buflen - namelen - 1; 480 if (datalen == 0) 481 goto invalid; 482 /* sanity check */ 483 for (i = 0; i < namelen; ++i) 484 if (!isalpha((unsigned char)name[i])) 485 goto invalid; 486 if (strcmp(name, "stat") == 0) { 487 struct stat sb; 488 489 if (datalen != sizeof(struct stat)) 490 goto invalid; 491 memcpy(&sb, data, datalen); 492 ktrstat(&sb); 493 } else if (strcmp(name, "sockaddr") == 0) { 494 struct sockaddr_storage ss; 495 496 if (datalen > sizeof(ss)) 497 goto invalid; 498 memcpy(&ss, data, datalen); 499 if ((ss.ss_family != AF_UNIX && 500 datalen < sizeof(struct sockaddr)) || datalen != ss.ss_len) 501 goto invalid; 502 ktrsockaddr((struct sockaddr *)&ss); 503 } else if (strcmp(name, "abstimespec") == 0 || 504 strcmp(name, "reltimespec") == 0) { 505 struct timespec ts; 506 507 if (datalen != sizeof(ts)) 508 goto invalid; 509 memcpy(&ts, data, datalen); 510 ktrtimespec(&ts, name[0] == 'r'); 511 } else if (strcmp(name, "abstimeval") == 0 || 512 strcmp(name, "reltimeval") == 0) { 513 struct timeval tv; 514 515 if (datalen != sizeof(tv)) 516 goto invalid; 517 memcpy(&tv, data, datalen); 518 ktrtimeval(&tv, name[0] == 'r'); 519 } else if (strcmp(name, "sigaction") == 0) { 520 struct sigaction sa; 521 522 if (datalen != sizeof(sa)) 523 goto invalid; 524 memcpy(&sa, data, datalen); 525 ktrsigaction(&sa); 526 } else if (strcmp(name, "rlimit") == 0) { 527 struct rlimit lim; 528 529 if (datalen != sizeof(lim)) 530 goto invalid; 531 memcpy(&lim, data, datalen); 532 ktrrlimit(&lim); 533 } else if (strcmp(name, "rusage") == 0) { 534 struct rusage ru; 535 536 if (datalen != sizeof(ru)) 537 goto invalid; 538 memcpy(&ru, data, datalen); 539 ktrrusage(&ru); 540 } else if (strcmp(name, "tfork") == 0) { 541 struct __tfork tf; 542 543 if (datalen != sizeof(tf)) 544 goto invalid; 545 memcpy(&tf, data, datalen); 546 ktrtfork(&tf); 547 } else if (strcmp(name, "fdset") == 0) { 548 struct fd_set *fds; 549 550 if ((fds = malloc(datalen)) == NULL) 551 err(1, "malloc"); 552 memcpy(fds, data, datalen); 553 ktrfdset(fds, datalen); 554 free(fds); 555 } else if (strcmp(name, "quota") == 0) { 556 struct dqblk quota; 557 558 if (datalen != sizeof(quota)) 559 goto invalid; 560 memcpy("a, data, datalen); 561 ktrquota("a); 562 } else if (strcmp(name, "msghdr") == 0) { 563 struct msghdr msg; 564 565 if (datalen != sizeof(msg)) 566 goto invalid; 567 memcpy(&msg, data, datalen); 568 ktrmsghdr(&msg); 569 } else if (strcmp(name, "iovec") == 0) { 570 if (datalen % sizeof(struct iovec)) 571 goto invalid; 572 ktriovec(data, datalen / sizeof(struct iovec)); 573 } else if (strcmp(name, "kevent") == 0) { 574 if (datalen % sizeof(struct kevent)) 575 goto invalid; 576 ktrevent(data, datalen / sizeof(struct kevent)); 577 } else if (strcmp(name, "cmsghdr") == 0) { 578 char *cmsg; 579 580 if ((cmsg = malloc(datalen)) == NULL) 581 err(1, "malloc"); 582 memcpy(cmsg, data, datalen); 583 ktrcmsghdr(cmsg, datalen); 584 free(cmsg); 585 } else if (strcmp(name, "pledgereq") == 0) { 586 printf("pledge request="); 587 showbufc(basecol + sizeof("pledge request=") - 1, 588 (unsigned char *)data, datalen); 589 } else if (strcmp(name, "pledgepath") == 0) { 590 printf("pledge path="); 591 showbufc(basecol + sizeof("pledge path=") - 1, 592 (unsigned char *)data, datalen); 593 } else { 594 printf("unknown structure %s\n", name); 595 } 596 return; 597invalid: 598 printf("invalid record\n"); 599} 600