Annotation of src/usr.bin/kdump/ktrstruct.c, Revision 1.1
1.1 ! guenther 1: /* $OpenBSD: kdump.c,v 1.83 2013/07/03 23:04:33 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/un.h>
! 38: #include <netinet/in.h>
! 39: #include <arpa/inet.h>
! 40:
! 41: #include <ctype.h>
! 42: #include <err.h>
! 43: #include <limits.h>
! 44: #include <poll.h>
! 45: #include <signal.h>
! 46: #include <stdio.h>
! 47: #include <stdlib.h>
! 48: #include <stdint.h>
! 49: #include <string.h>
! 50: #include <grp.h>
! 51: #include <pwd.h>
! 52: #include <unistd.h>
! 53:
! 54: #include "kdump.h"
! 55: #include "kdump_subr.h"
! 56:
! 57: #define TIME_FORMAT "%b %e %T %Y"
! 58:
! 59: static void
! 60: ktrsockaddr(struct sockaddr *sa)
! 61: {
! 62: /*
! 63: TODO: Support additional address families
! 64: #include <netnatm/natm.h>
! 65: struct sockaddr_natm *natm;
! 66: #include <netsmb/netbios.h>
! 67: struct sockaddr_nb *nb;
! 68: */
! 69: char addr[64];
! 70:
! 71: /*
! 72: * note: ktrstruct() has already verified that sa points to a
! 73: * buffer at least sizeof(struct sockaddr) bytes long and exactly
! 74: * sa->sa_len bytes long.
! 75: */
! 76: printf("struct sockaddr { ");
! 77: sockfamilyname(sa->sa_family);
! 78: printf(", ");
! 79:
! 80: #define check_sockaddr_len(n) \
! 81: if (sa_##n->s##n##_len < sizeof(struct sockaddr_##n)) { \
! 82: printf("invalid"); \
! 83: break; \
! 84: }
! 85:
! 86: switch(sa->sa_family) {
! 87: case AF_INET: {
! 88: struct sockaddr_in *sa_in;
! 89:
! 90: sa_in = (struct sockaddr_in *)sa;
! 91: check_sockaddr_len(in);
! 92: inet_ntop(AF_INET, &sa_in->sin_addr, addr, sizeof addr);
! 93: printf("%s:%u", addr, ntohs(sa_in->sin_port));
! 94: break;
! 95: }
! 96: case AF_INET6: {
! 97: struct sockaddr_in6 *sa_in6;
! 98:
! 99: sa_in6 = (struct sockaddr_in6 *)sa;
! 100: check_sockaddr_len(in6);
! 101: inet_ntop(AF_INET6, &sa_in6->sin6_addr, addr, sizeof addr);
! 102: printf("[%s]:%u", addr, htons(sa_in6->sin6_port));
! 103: break;
! 104: }
! 105: #ifdef IPX
! 106: case AF_IPX: {
! 107: struct sockaddr_ipx *sa_ipx;
! 108:
! 109: sa_ipx = (struct sockaddr_ipx *)sa;
! 110: check_sockaddr_len(ipx);
! 111: /* XXX wish we had ipx_ntop */
! 112: printf("%s", ipx_ntoa(sa_ipx->sipx_addr));
! 113: break;
! 114: }
! 115: #endif
! 116: case AF_UNIX: {
! 117: struct sockaddr_un *sa_un;
! 118:
! 119: sa_un = (struct sockaddr_un *)sa;
! 120: if (sa_un->sun_len <= sizeof(sa_un->sun_len) +
! 121: sizeof(sa_un->sun_family)) {
! 122: printf("invalid");
! 123: break;
! 124: }
! 125: printf("\"%.*s\"", (int)(sa_un->sun_len -
! 126: sizeof(sa_un->sun_len) - sizeof(sa_un->sun_family)),
! 127: sa_un->sun_path);
! 128: break;
! 129: }
! 130: default:
! 131: printf("unknown address family");
! 132: }
! 133: printf(" }\n");
! 134: }
! 135:
! 136: static void
! 137: print_time(time_t t, int relative)
! 138: {
! 139: char timestr[PATH_MAX + 4];
! 140: struct tm *tm;
! 141:
! 142: if (resolv == 0 || relative)
! 143: printf("%jd", (intmax_t)t);
! 144: else {
! 145: tm = localtime(&t);
! 146: (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
! 147: printf("\"%s\"", timestr);
! 148: }
! 149: }
! 150:
! 151: static void
! 152: print_timespec(const struct timespec *tsp, int relative)
! 153: {
! 154: print_time(tsp->tv_sec, relative);
! 155: if (tsp->tv_nsec != 0)
! 156: printf(".%09ld", tsp->tv_nsec);
! 157: }
! 158:
! 159: static void
! 160: ktrstat(const struct stat *statp)
! 161: {
! 162: char mode[12];
! 163: struct passwd *pwd;
! 164: struct group *grp;
! 165:
! 166: /*
! 167: * note: ktrstruct() has already verified that statp points to a
! 168: * buffer exactly sizeof(struct stat) bytes long.
! 169: */
! 170: printf("struct stat { ");
! 171: strmode(statp->st_mode, mode);
! 172: printf("dev=%d, ino=%llu, mode=%s, nlink=%u, ",
! 173: statp->st_dev, (unsigned long long)statp->st_ino,
! 174: mode, statp->st_nlink);
! 175: if (resolv == 0 || (pwd = getpwuid(statp->st_uid)) == NULL)
! 176: printf("uid=%u, ", statp->st_uid);
! 177: else
! 178: printf("uid=\"%s\", ", pwd->pw_name);
! 179: if (resolv == 0 || (grp = getgrgid(statp->st_gid)) == NULL)
! 180: printf("gid=%u, ", statp->st_gid);
! 181: else
! 182: printf("gid=\"%s\", ", grp->gr_name);
! 183: printf("rdev=%d, ", statp->st_rdev);
! 184: printf("atime=");
! 185: print_timespec(&statp->st_atim, 0);
! 186: printf(", mtime=");
! 187: print_timespec(&statp->st_mtim, 0);
! 188: printf(", ctime=");
! 189: print_timespec(&statp->st_ctim, 0);
! 190: printf(", size=%lld, blocks=%lld, blksize=%u, flags=0x%x, gen=0x%x",
! 191: statp->st_size, statp->st_blocks, statp->st_blksize,
! 192: statp->st_flags, statp->st_gen);
! 193: printf(" }\n");
! 194: }
! 195:
! 196: static void
! 197: ktrtimespec(const struct timespec *tsp, int relative)
! 198: {
! 199: printf("struct timespec { ");
! 200: print_timespec(tsp, relative);
! 201: printf(" }\n");
! 202: }
! 203:
! 204: static void
! 205: ktrtimeval(const struct timeval *tvp, int relative)
! 206: {
! 207: printf("struct timeval { ");
! 208: print_time(tvp->tv_sec, relative);
! 209: if (tvp->tv_usec != 0)
! 210: printf(".%06ld", tvp->tv_usec);
! 211: printf(" }\n");
! 212: }
! 213:
! 214: static void
! 215: ktrsigaction(const struct sigaction *sa)
! 216: {
! 217: /*
! 218: * note: ktrstruct() has already verified that sa points to a
! 219: * buffer exactly sizeof(struct sigaction) bytes long.
! 220: */
! 221: printf("struct sigaction { ");
! 222: if (sa->sa_handler == SIG_DFL)
! 223: printf("handler=SIG_DFL");
! 224: else if (sa->sa_handler == SIG_IGN)
! 225: printf("handler=SIG_IGN");
! 226: else if (sa->sa_flags & SA_SIGINFO)
! 227: printf("sigaction=%p", (void *)sa->sa_sigaction);
! 228: else
! 229: printf("handler=%p", (void *)sa->sa_handler);
! 230: printf(", mask=");
! 231: sigset(sa->sa_mask);
! 232: printf(", flags=");
! 233: sigactionflagname(sa->sa_flags);
! 234: printf(" }\n");
! 235: }
! 236:
! 237: static void
! 238: print_rlim(rlim_t lim)
! 239: {
! 240: if (lim == RLIM_INFINITY)
! 241: printf("infinite");
! 242: else
! 243: printf("%llu", (unsigned long long)lim);
! 244: }
! 245:
! 246: static void
! 247: ktrrlimit(const struct rlimit *limp)
! 248: {
! 249: printf("struct rlimit { ");
! 250: printf("cur=");
! 251: print_rlim(limp->rlim_cur);
! 252: printf(", max=");
! 253: print_rlim(limp->rlim_max);
! 254: printf(" }\n");
! 255: }
! 256:
! 257: static void
! 258: ktrtfork(const struct __tfork *tf)
! 259: {
! 260: printf("struct __tfork { tcb=%p, tid=%p, stack=%p }\n",
! 261: tf->tf_tcb, (void *)tf->tf_tid, tf->tf_stack);
! 262: }
! 263:
! 264: static void
! 265: ktrfdset(const struct fd_set *fds, int len)
! 266: {
! 267: int nfds, i, start = -1;
! 268: char sep = ' ';
! 269:
! 270: nfds = len * NBBY;
! 271: printf("struct fd_set {");
! 272: for (i = 0; i <= nfds; i++)
! 273: if (i != nfds && FD_ISSET(i, fds)) {
! 274: if (start == -1)
! 275: start = i;
! 276: } else if (start != -1) {
! 277: putchar(sep);
! 278: if (start == i - 1)
! 279: printf("%d", start);
! 280: else if (start == i - 2)
! 281: printf("%d,%d", start, i - 1);
! 282: else
! 283: printf("%d-%d", start, i - 1);
! 284: sep = ',';
! 285: start = -1;
! 286: }
! 287:
! 288: printf(" }\n");
! 289: }
! 290:
! 291: void
! 292: ktrstruct(char *buf, size_t buflen)
! 293: {
! 294: char *name, *data;
! 295: size_t namelen, datalen;
! 296: int i;
! 297:
! 298: for (name = buf, namelen = 0; namelen < buflen && name[namelen] != '\0';
! 299: ++namelen)
! 300: /* nothing */;
! 301: if (namelen == buflen)
! 302: goto invalid;
! 303: if (name[namelen] != '\0')
! 304: goto invalid;
! 305: data = buf + namelen + 1;
! 306: datalen = buflen - namelen - 1;
! 307: if (datalen == 0)
! 308: goto invalid;
! 309: /* sanity check */
! 310: for (i = 0; i < namelen; ++i)
! 311: if (!isalpha((unsigned char)name[i]))
! 312: goto invalid;
! 313: if (strcmp(name, "stat") == 0) {
! 314: struct stat sb;
! 315:
! 316: if (datalen != sizeof(struct stat))
! 317: goto invalid;
! 318: memcpy(&sb, data, datalen);
! 319: ktrstat(&sb);
! 320: } else if (strcmp(name, "sockaddr") == 0) {
! 321: struct sockaddr_storage ss;
! 322:
! 323: if (datalen > sizeof(ss))
! 324: goto invalid;
! 325: memcpy(&ss, data, datalen);
! 326: if ((ss.ss_family != AF_UNIX &&
! 327: datalen < sizeof(struct sockaddr)) || datalen != ss.ss_len)
! 328: goto invalid;
! 329: ktrsockaddr((struct sockaddr *)&ss);
! 330: } else if (strcmp(name, "abstimespec") == 0 ||
! 331: strcmp(name, "reltimespec") == 0) {
! 332: struct timespec ts;
! 333:
! 334: if (datalen != sizeof(ts))
! 335: goto invalid;
! 336: memcpy(&ts, data, datalen);
! 337: ktrtimespec(&ts, name[0] == 'r');
! 338: } else if (strcmp(name, "abstimeval") == 0 ||
! 339: strcmp(name, "reltimeval") == 0) {
! 340: struct timeval tv;
! 341:
! 342: if (datalen != sizeof(tv))
! 343: goto invalid;
! 344: memcpy(&tv, data, datalen);
! 345: ktrtimeval(&tv, name[0] == 'r');
! 346: } else if (strcmp(name, "sigaction") == 0) {
! 347: struct sigaction sa;
! 348:
! 349: if (datalen != sizeof(sa))
! 350: goto invalid;
! 351: memcpy(&sa, data, datalen);
! 352: ktrsigaction(&sa);
! 353: } else if (strcmp(name, "rlimit") == 0) {
! 354: struct rlimit lim;
! 355:
! 356: if (datalen != sizeof(lim))
! 357: goto invalid;
! 358: memcpy(&lim, data, datalen);
! 359: ktrrlimit(&lim);
! 360: } else if (strcmp(name, "tfork") == 0) {
! 361: struct __tfork tf;
! 362:
! 363: if (datalen != sizeof(tf))
! 364: goto invalid;
! 365: memcpy(&tf, data, datalen);
! 366: ktrtfork(&tf);
! 367: } else if (strcmp(name, "fdset") == 0) {
! 368: struct fd_set *fds;
! 369: if ((fds = malloc(datalen)) == NULL)
! 370: err(1, "malloc");
! 371: memcpy(fds, data, datalen);
! 372: ktrfdset(fds, datalen);
! 373: free(fds);
! 374: } else {
! 375: printf("unknown structure %s\n", name);
! 376: }
! 377: return;
! 378: invalid:
! 379: printf("invalid record\n");
! 380: }