1 /* $OpenBSD: ktrstruct.c,v 1.6 2014/10/13 03:46: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 <ufs/ufs/quota.h> 39 #include <netinet/in.h> 40 #include <arpa/inet.h> 41 42 #include <ctype.h> 43 #include <err.h> 44 #include <limits.h> 45 #include <poll.h> 46 #include <signal.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <stdint.h> 50 #include <string.h> 51 #include <grp.h> 52 #include <pwd.h> 53 #include <unistd.h> 54 55 #include "kdump.h" 56 #include "kdump_subr.h" 57 58 #define TIME_FORMAT "%b %e %T %Y" 59 60 static void 61 ktrsockaddr(struct sockaddr *sa) 62 { 63 /* 64 TODO: Support additional address families 65 #include <netmpls/mpls.h> 66 struct sockaddr_mpls *mpls; 67 */ 68 char addr[64]; 69 70 /* 71 * note: ktrstruct() has already verified that sa points to a 72 * buffer at least sizeof(struct sockaddr) bytes long and exactly 73 * sa->sa_len bytes long. 74 */ 75 printf("struct sockaddr { "); 76 sockfamilyname(sa->sa_family); 77 printf(", "); 78 79 #define check_sockaddr_len(n) \ 80 if (sa_##n->s##n##_len < sizeof(struct sockaddr_##n)) { \ 81 printf("invalid"); \ 82 break; \ 83 } 84 85 switch(sa->sa_family) { 86 case AF_INET: { 87 struct sockaddr_in *sa_in; 88 89 sa_in = (struct sockaddr_in *)sa; 90 check_sockaddr_len(in); 91 inet_ntop(AF_INET, &sa_in->sin_addr, addr, sizeof addr); 92 printf("%s:%u", addr, ntohs(sa_in->sin_port)); 93 break; 94 } 95 case AF_INET6: { 96 struct sockaddr_in6 *sa_in6; 97 98 sa_in6 = (struct sockaddr_in6 *)sa; 99 check_sockaddr_len(in6); 100 inet_ntop(AF_INET6, &sa_in6->sin6_addr, addr, sizeof addr); 101 printf("[%s]:%u", addr, htons(sa_in6->sin6_port)); 102 break; 103 } 104 #ifdef IPX 105 case AF_IPX: { 106 struct sockaddr_ipx *sa_ipx; 107 108 sa_ipx = (struct sockaddr_ipx *)sa; 109 check_sockaddr_len(ipx); 110 /* XXX wish we had ipx_ntop */ 111 printf("%s", ipx_ntoa(sa_ipx->sipx_addr)); 112 break; 113 } 114 #endif 115 case AF_UNIX: { 116 struct sockaddr_un *sa_un; 117 118 sa_un = (struct sockaddr_un *)sa; 119 if (sa_un->sun_len <= sizeof(sa_un->sun_len) + 120 sizeof(sa_un->sun_family)) { 121 printf("invalid"); 122 break; 123 } 124 printf("\"%.*s\"", (int)(sa_un->sun_len - 125 sizeof(sa_un->sun_len) - sizeof(sa_un->sun_family)), 126 sa_un->sun_path); 127 break; 128 } 129 default: 130 printf("unknown address family"); 131 } 132 printf(" }\n"); 133 } 134 135 static void 136 print_time(time_t t, int relative) 137 { 138 char timestr[PATH_MAX + 4]; 139 struct tm *tm; 140 141 if (resolv == 0 || relative) 142 printf("%jd", (intmax_t)t); 143 else { 144 tm = localtime(&t); 145 (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm); 146 printf("\"%s\"", timestr); 147 } 148 } 149 150 static void 151 print_timespec(const struct timespec *tsp, int relative) 152 { 153 if (tsp->tv_nsec == UTIME_NOW) 154 printf("UTIME_NOW"); 155 else if (tsp->tv_nsec == UTIME_OMIT) 156 printf("UTIME_OMIT"); 157 else if ((resolv == 0 || relative) && tsp->tv_sec < 0 && 158 tsp->tv_nsec > 0) { 159 /* negative relative times with non-zero nsecs require care */ 160 printf("-%jd.%09ld", -(intmax_t)(tsp->tv_sec+1), 161 1000000000 - tsp->tv_nsec); 162 } else { 163 print_time(tsp->tv_sec, relative); 164 if (tsp->tv_nsec != 0) 165 printf(".%09ld", tsp->tv_nsec); 166 } 167 } 168 169 static void 170 ktrstat(const struct stat *statp) 171 { 172 char mode[12]; 173 struct passwd *pwd; 174 struct group *grp; 175 176 /* 177 * note: ktrstruct() has already verified that statp points to a 178 * buffer exactly sizeof(struct stat) bytes long. 179 */ 180 printf("struct stat { "); 181 strmode(statp->st_mode, mode); 182 printf("dev=%d, ino=%llu, mode=%s, nlink=%u, ", 183 statp->st_dev, (unsigned long long)statp->st_ino, 184 mode, statp->st_nlink); 185 if (resolv == 0 || (pwd = getpwuid(statp->st_uid)) == NULL) 186 printf("uid=%u, ", statp->st_uid); 187 else 188 printf("uid=\"%s\", ", pwd->pw_name); 189 if (resolv == 0 || (grp = getgrgid(statp->st_gid)) == NULL) 190 printf("gid=%u, ", statp->st_gid); 191 else 192 printf("gid=\"%s\", ", grp->gr_name); 193 printf("rdev=%d, ", statp->st_rdev); 194 printf("atime="); 195 print_timespec(&statp->st_atim, 0); 196 printf(", mtime="); 197 print_timespec(&statp->st_mtim, 0); 198 printf(", ctime="); 199 print_timespec(&statp->st_ctim, 0); 200 printf(", size=%lld, blocks=%lld, blksize=%u, flags=0x%x, gen=0x%x", 201 statp->st_size, statp->st_blocks, statp->st_blksize, 202 statp->st_flags, statp->st_gen); 203 printf(" }\n"); 204 } 205 206 static void 207 ktrtimespec(const struct timespec *tsp, int relative) 208 { 209 printf("struct timespec { "); 210 print_timespec(tsp, relative); 211 printf(" }\n"); 212 } 213 214 static void 215 print_timeval(const struct timeval *tvp, int relative) 216 { 217 if ((resolv == 0 || relative) && tvp->tv_sec < 0 && 218 tvp->tv_usec > 0) { 219 /* negative relative times with non-zero usecs require care */ 220 printf("-%jd.%06ld", -(intmax_t)(tvp->tv_sec+1), 221 1000000 - tvp->tv_usec); 222 } else { 223 print_time(tvp->tv_sec, relative); 224 if (tvp->tv_usec != 0) 225 printf(".%06ld", tvp->tv_usec); 226 } 227 } 228 229 static void 230 ktrtimeval(const struct timeval *tvp, int relative) 231 { 232 printf("struct timeval { "); 233 print_timeval(tvp, relative); 234 printf(" }\n"); 235 } 236 237 static void 238 ktrsigaction(const struct sigaction *sa) 239 { 240 /* 241 * note: ktrstruct() has already verified that sa points to a 242 * buffer exactly sizeof(struct sigaction) bytes long. 243 */ 244 printf("struct sigaction { "); 245 if (sa->sa_handler == SIG_DFL) 246 printf("handler=SIG_DFL"); 247 else if (sa->sa_handler == SIG_IGN) 248 printf("handler=SIG_IGN"); 249 else if (sa->sa_flags & SA_SIGINFO) 250 printf("sigaction=%p", (void *)sa->sa_sigaction); 251 else 252 printf("handler=%p", (void *)sa->sa_handler); 253 printf(", mask="); 254 sigset(sa->sa_mask); 255 printf(", flags="); 256 sigactionflagname(sa->sa_flags); 257 printf(" }\n"); 258 } 259 260 static void 261 print_rlim(rlim_t lim) 262 { 263 if (lim == RLIM_INFINITY) 264 printf("infinite"); 265 else 266 printf("%llu", (unsigned long long)lim); 267 } 268 269 static void 270 ktrrlimit(const struct rlimit *limp) 271 { 272 printf("struct rlimit { "); 273 printf("cur="); 274 print_rlim(limp->rlim_cur); 275 printf(", max="); 276 print_rlim(limp->rlim_max); 277 printf(" }\n"); 278 } 279 280 static void 281 ktrtfork(const struct __tfork *tf) 282 { 283 printf("struct __tfork { tcb=%p, tid=%p, stack=%p }\n", 284 tf->tf_tcb, (void *)tf->tf_tid, tf->tf_stack); 285 } 286 287 static void 288 ktrfdset(const struct fd_set *fds, int len) 289 { 290 int nfds, i, start = -1; 291 char sep = ' '; 292 293 nfds = len * NBBY; 294 printf("struct fd_set {"); 295 for (i = 0; i <= nfds; i++) 296 if (i != nfds && FD_ISSET(i, fds)) { 297 if (start == -1) 298 start = i; 299 } else if (start != -1) { 300 putchar(sep); 301 if (start == i - 1) 302 printf("%d", start); 303 else if (start == i - 2) 304 printf("%d,%d", start, i - 1); 305 else 306 printf("%d-%d", start, i - 1); 307 sep = ','; 308 start = -1; 309 } 310 311 printf(" }\n"); 312 } 313 314 static void 315 ktrrusage(const struct rusage *rup) 316 { 317 printf("struct rusage { utime="); 318 print_timeval(&rup->ru_utime, 1); 319 printf(", stime="); 320 print_timeval(&rup->ru_stime, 1); 321 printf(", maxrss=%ld, ixrss=%ld, idrss=%ld, isrss=%ld," 322 " minflt=%ld, majflt=%ld, nswap=%ld, inblock=%ld," 323 " oublock=%ld, msgsnd=%ld, msgrcv=%ld, nsignals=%ld," 324 " nvcsw=%ld, nivcsw=%ld }\n", 325 rup->ru_maxrss, rup->ru_ixrss, rup->ru_idrss, rup->ru_isrss, 326 rup->ru_minflt, rup->ru_majflt, rup->ru_nswap, rup->ru_inblock, 327 rup->ru_oublock, rup->ru_msgsnd, rup->ru_msgrcv, rup->ru_nsignals, 328 rup->ru_nvcsw, rup->ru_nivcsw); 329 } 330 331 static void 332 ktrquota(const struct dqblk *quota) 333 { 334 printf("struct dqblk { bhardlimit=%u, bsoftlimit=%u, curblocks=%u," 335 " ihardlimit=%u, isoftlimit=%u, curinodes=%u, btime=", 336 quota->dqb_bhardlimit, quota->dqb_bsoftlimit, 337 quota->dqb_curblocks, quota->dqb_ihardlimit, 338 quota->dqb_isoftlimit, quota->dqb_curinodes); 339 print_time(quota->dqb_btime, 0); 340 printf(", itime="); 341 print_time(quota->dqb_itime, 0); 342 printf(" }\n"); 343 } 344 345 void 346 ktrstruct(char *buf, size_t buflen) 347 { 348 char *name, *data; 349 size_t namelen, datalen; 350 int i; 351 352 for (name = buf, namelen = 0; namelen < buflen && name[namelen] != '\0'; 353 ++namelen) 354 /* nothing */; 355 if (namelen == buflen) 356 goto invalid; 357 if (name[namelen] != '\0') 358 goto invalid; 359 data = buf + namelen + 1; 360 datalen = buflen - namelen - 1; 361 if (datalen == 0) 362 goto invalid; 363 /* sanity check */ 364 for (i = 0; i < namelen; ++i) 365 if (!isalpha((unsigned char)name[i])) 366 goto invalid; 367 if (strcmp(name, "stat") == 0) { 368 struct stat sb; 369 370 if (datalen != sizeof(struct stat)) 371 goto invalid; 372 memcpy(&sb, data, datalen); 373 ktrstat(&sb); 374 } else if (strcmp(name, "sockaddr") == 0) { 375 struct sockaddr_storage ss; 376 377 if (datalen > sizeof(ss)) 378 goto invalid; 379 memcpy(&ss, data, datalen); 380 if ((ss.ss_family != AF_UNIX && 381 datalen < sizeof(struct sockaddr)) || datalen != ss.ss_len) 382 goto invalid; 383 ktrsockaddr((struct sockaddr *)&ss); 384 } else if (strcmp(name, "abstimespec") == 0 || 385 strcmp(name, "reltimespec") == 0) { 386 struct timespec ts; 387 388 if (datalen != sizeof(ts)) 389 goto invalid; 390 memcpy(&ts, data, datalen); 391 ktrtimespec(&ts, name[0] == 'r'); 392 } else if (strcmp(name, "abstimeval") == 0 || 393 strcmp(name, "reltimeval") == 0) { 394 struct timeval tv; 395 396 if (datalen != sizeof(tv)) 397 goto invalid; 398 memcpy(&tv, data, datalen); 399 ktrtimeval(&tv, name[0] == 'r'); 400 } else if (strcmp(name, "sigaction") == 0) { 401 struct sigaction sa; 402 403 if (datalen != sizeof(sa)) 404 goto invalid; 405 memcpy(&sa, data, datalen); 406 ktrsigaction(&sa); 407 } else if (strcmp(name, "rlimit") == 0) { 408 struct rlimit lim; 409 410 if (datalen != sizeof(lim)) 411 goto invalid; 412 memcpy(&lim, data, datalen); 413 ktrrlimit(&lim); 414 } else if (strcmp(name, "rusage") == 0) { 415 struct rusage ru; 416 417 if (datalen != sizeof(ru)) 418 goto invalid; 419 memcpy(&ru, data, datalen); 420 ktrrusage(&ru); 421 } else if (strcmp(name, "tfork") == 0) { 422 struct __tfork tf; 423 424 if (datalen != sizeof(tf)) 425 goto invalid; 426 memcpy(&tf, data, datalen); 427 ktrtfork(&tf); 428 } else if (strcmp(name, "fdset") == 0) { 429 struct fd_set *fds; 430 if ((fds = malloc(datalen)) == NULL) 431 err(1, "malloc"); 432 memcpy(fds, data, datalen); 433 ktrfdset(fds, datalen); 434 free(fds); 435 } else if (strcmp(name, "quota") == 0) { 436 struct dqblk quota; 437 438 if (datalen != sizeof(quota)) 439 goto invalid; 440 memcpy("a, data, datalen); 441 ktrquota("a); 442 } else { 443 printf("unknown structure %s\n", name); 444 } 445 return; 446 invalid: 447 printf("invalid record\n"); 448 } 449