1 /* $NetBSD: savefile.c,v 1.8 2024/09/02 15:33:38 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1993, 1994, 1995, 1996, 1997 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: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 * 23 * savefile.c - supports offline use of tcpdump 24 * Extraction/creation by Jeffrey Mogul, DECWRL 25 * Modified by Steve McCanne, LBL. 26 * 27 * Used to save the received packet headers, after filtering, to 28 * a file, and then read them later. 29 * The first record in the file contains saved values for the machine 30 * dependent values so we can print the dump file on any architecture. 31 */ 32 33 #include <sys/cdefs.h> 34 __RCSID("$NetBSD: savefile.c,v 1.8 2024/09/02 15:33:38 christos Exp $"); 35 36 #include <config.h> 37 38 #include <pcap-types.h> 39 #ifdef _WIN32 40 #include <io.h> 41 #include <fcntl.h> 42 #endif /* _WIN32 */ 43 44 #include <errno.h> 45 #include <memory.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <limits.h> /* for INT_MAX */ 50 51 #include "pcap-int.h" 52 53 #ifdef HAVE_OS_PROTO_H 54 #include "os-proto.h" 55 #endif 56 57 #include "sf-pcap.h" 58 #include "sf-pcapng.h" 59 #include "pcap-common.h" 60 #include "charconv.h" 61 62 #ifdef _WIN32 63 /* 64 * This isn't exported on Windows, because it would only work if both 65 * WinPcap/Npcap and the code using it were to use the Universal CRT; otherwise, 66 * a FILE structure in WinPcap/Npcap and a FILE structure in the code using it 67 * could be different if they're using different versions of the C runtime. 68 * 69 * Instead, pcap/pcap.h defines it as a macro that wraps the hopen version, 70 * with the wrapper calling _fileno() and _get_osfhandle() themselves, 71 * so that it convert the appropriate CRT version's FILE structure to 72 * a HANDLE (which is OS-defined, not CRT-defined, and is part of the Win32 73 * and Win64 ABIs). 74 */ 75 static pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *); 76 #endif 77 78 /* 79 * Setting O_BINARY on DOS/Windows is a bit tricky 80 */ 81 #if defined(_WIN32) 82 #define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY) 83 #elif defined(MSDOS) 84 #if defined(__HIGHC__) 85 #define SET_BINMODE(f) setmode(f, O_BINARY) 86 #else 87 #define SET_BINMODE(f) setmode(fileno(f), O_BINARY) 88 #endif 89 #endif 90 91 static int 92 sf_getnonblock(pcap_t *p _U_) 93 { 94 /* 95 * This is a savefile, not a live capture file, so never say 96 * it's in non-blocking mode. 97 */ 98 return (0); 99 } 100 101 static int 102 sf_setnonblock(pcap_t *p, int nonblock _U_) 103 { 104 /* 105 * This is a savefile, not a live capture file, so reject 106 * requests to put it in non-blocking mode. (If it's a 107 * pipe, it could be put in non-blocking mode, but that 108 * would significantly complicate the code to read packets, 109 * as it would have to handle reading partial packets and 110 * keeping the state of the read.) 111 */ 112 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 113 "Savefiles cannot be put into non-blocking mode"); 114 return (-1); 115 } 116 117 static int 118 sf_cant_set_rfmon(pcap_t *p _U_) 119 { 120 /* 121 * This is a savefile, not a device on which you can capture, 122 * so never say it supports being put into monitor mode. 123 */ 124 return (0); 125 } 126 127 static int 128 sf_stats(pcap_t *p, struct pcap_stat *ps _U_) 129 { 130 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 131 "Statistics aren't available from savefiles"); 132 return (-1); 133 } 134 135 #ifdef _WIN32 136 static struct pcap_stat * 137 sf_stats_ex(pcap_t *p, int *size _U_) 138 { 139 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 140 "Statistics aren't available from savefiles"); 141 return (NULL); 142 } 143 144 static int 145 sf_setbuff(pcap_t *p, int dim _U_) 146 { 147 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 148 "The kernel buffer size cannot be set while reading from a file"); 149 return (-1); 150 } 151 152 static int 153 sf_setmode(pcap_t *p, int mode _U_) 154 { 155 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 156 "impossible to set mode while reading from a file"); 157 return (-1); 158 } 159 160 static int 161 sf_setmintocopy(pcap_t *p, int size _U_) 162 { 163 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 164 "The mintocopy parameter cannot be set while reading from a file"); 165 return (-1); 166 } 167 168 static HANDLE 169 sf_getevent(pcap_t *pcap) 170 { 171 (void)snprintf(pcap->errbuf, sizeof(pcap->errbuf), 172 "The read event cannot be retrieved while reading from a file"); 173 return (INVALID_HANDLE_VALUE); 174 } 175 176 static int 177 sf_oid_get_request(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_, 178 size_t *lenp _U_) 179 { 180 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 181 "An OID get request cannot be performed on a file"); 182 return (PCAP_ERROR); 183 } 184 185 static int 186 sf_oid_set_request(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_, 187 size_t *lenp _U_) 188 { 189 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 190 "An OID set request cannot be performed on a file"); 191 return (PCAP_ERROR); 192 } 193 194 static u_int 195 sf_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue _U_, int sync _U_) 196 { 197 pcapint_strlcpy(p->errbuf, "Sending packets isn't supported on savefiles", 198 PCAP_ERRBUF_SIZE); 199 return (0); 200 } 201 202 static int 203 sf_setuserbuffer(pcap_t *p, int size _U_) 204 { 205 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 206 "The user buffer cannot be set when reading from a file"); 207 return (-1); 208 } 209 210 static int 211 sf_live_dump(pcap_t *p, char *filename _U_, int maxsize _U_, int maxpacks _U_) 212 { 213 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 214 "Live packet dumping cannot be performed when reading from a file"); 215 return (-1); 216 } 217 218 static int 219 sf_live_dump_ended(pcap_t *p, int sync _U_) 220 { 221 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 222 "Live packet dumping cannot be performed on a pcap_open_dead pcap_t"); 223 return (-1); 224 } 225 226 static PAirpcapHandle 227 sf_get_airpcap_handle(pcap_t *pcap _U_) 228 { 229 return (NULL); 230 } 231 #endif 232 233 static int 234 sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_) 235 { 236 pcapint_strlcpy(p->errbuf, "Sending packets isn't supported on savefiles", 237 PCAP_ERRBUF_SIZE); 238 return (-1); 239 } 240 241 /* 242 * Set direction flag: Which packets do we accept on a forwarding 243 * single device? IN, OUT or both? 244 */ 245 static int 246 sf_setdirection(pcap_t *p, pcap_direction_t d _U_) 247 { 248 snprintf(p->errbuf, sizeof(p->errbuf), 249 "Setting direction is not supported on savefiles"); 250 return (-1); 251 } 252 253 void 254 pcapint_sf_cleanup(pcap_t *p) 255 { 256 if (p->rfile != stdin) 257 (void)fclose(p->rfile); 258 if (p->buffer != NULL) 259 free(p->buffer); 260 pcap_freecode(&p->fcode); 261 } 262 263 #ifdef _WIN32 264 /* 265 * Wrapper for fopen() and _wfopen(). 266 * 267 * If we're in UTF-8 mode, map the pathname from UTF-8 to UTF-16LE and 268 * call _wfopen(). 269 * 270 * If we're not, just use fopen(); that'll treat it as being in the 271 * local code page. 272 */ 273 FILE * 274 pcapint_charset_fopen(const char *path, const char *mode) 275 { 276 wchar_t *utf16_path; 277 #define MAX_MODE_LEN 16 278 wchar_t utf16_mode[MAX_MODE_LEN+1]; 279 int i; 280 char c; 281 FILE *fp; 282 int save_errno; 283 284 if (pcapint_utf_8_mode) { 285 /* 286 * Map from UTF-8 to UTF-16LE. 287 * Fail if there are invalid characters in the input 288 * string, rather than converting them to REPLACEMENT 289 * CHARACTER; the latter is appropriate for strings 290 * to be displayed to the user, but for file names 291 * you just want the attempt to open the file to fail. 292 */ 293 utf16_path = cp_to_utf_16le(CP_UTF8, path, 294 MB_ERR_INVALID_CHARS); 295 if (utf16_path == NULL) { 296 /* 297 * Error. Assume errno has been set. 298 * 299 * XXX - what about Windows errors? 300 */ 301 return (NULL); 302 } 303 304 /* 305 * Now convert the mode to UTF-16LE as well. 306 * We assume the mode is ASCII, and that 307 * it's short, so that's easy. 308 */ 309 for (i = 0; (c = *mode) != '\0'; i++, mode++) { 310 if (c > 0x7F) { 311 /* Not an ASCII character; fail with EINVAL. */ 312 free(utf16_path); 313 errno = EINVAL; 314 return (NULL); 315 } 316 if (i >= MAX_MODE_LEN) { 317 /* The mode string is longer than we allow. */ 318 free(utf16_path); 319 errno = EINVAL; 320 return (NULL); 321 } 322 utf16_mode[i] = c; 323 } 324 utf16_mode[i] = '\0'; 325 326 /* 327 * OK, we have UTF-16LE strings; hand them to 328 * _wfopen(). 329 */ 330 fp = _wfopen(utf16_path, utf16_mode); 331 332 /* 333 * Make sure freeing the UTF-16LE string doesn't 334 * overwrite the error code we got from _wfopen(). 335 */ 336 save_errno = errno; 337 free(utf16_path); 338 errno = save_errno; 339 340 return (fp); 341 } else { 342 /* 343 * This takes strings in the local code page as an 344 * argument. 345 */ 346 return (fopen(path, mode)); 347 } 348 } 349 #endif 350 351 pcap_t * 352 pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision, 353 char *errbuf) 354 { 355 FILE *fp; 356 pcap_t *p; 357 358 if (fname == NULL) { 359 snprintf(errbuf, PCAP_ERRBUF_SIZE, 360 "A null pointer was supplied as the file name"); 361 return (NULL); 362 } 363 if (fname[0] == '-' && fname[1] == '\0') 364 { 365 fp = stdin; 366 if (fp == NULL) { 367 snprintf(errbuf, PCAP_ERRBUF_SIZE, 368 "The standard input is not open"); 369 return (NULL); 370 } 371 #if defined(_WIN32) || defined(MSDOS) 372 /* 373 * We're reading from the standard input, so put it in binary 374 * mode, as savefiles are binary files. 375 */ 376 SET_BINMODE(fp); 377 #endif 378 } 379 else { 380 /* 381 * Use pcapint_charset_fopen(); on Windows, it tests whether we're 382 * in "local code page" or "UTF-8" mode, and treats the 383 * pathname appropriately, and on other platforms, it just 384 * wraps fopen(). 385 * 386 * "b" is supported as of C90, so *all* UN*Xes should 387 * support it, even though it does nothing. For MS-DOS, 388 * we again need it. 389 */ 390 fp = pcapint_charset_fopen(fname, "rb"); 391 if (fp == NULL) { 392 pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 393 errno, "%s", fname); 394 return (NULL); 395 } 396 } 397 p = pcap_fopen_offline_with_tstamp_precision(fp, precision, errbuf); 398 if (p == NULL) { 399 if (fp != stdin) 400 fclose(fp); 401 } 402 return (p); 403 } 404 405 pcap_t * 406 pcap_open_offline(const char *fname, char *errbuf) 407 { 408 return (pcap_open_offline_with_tstamp_precision(fname, 409 PCAP_TSTAMP_PRECISION_MICRO, errbuf)); 410 } 411 412 #ifdef _WIN32 413 pcap_t* pcap_hopen_offline_with_tstamp_precision(intptr_t osfd, u_int precision, 414 char *errbuf) 415 { 416 int fd; 417 FILE *file; 418 419 fd = _open_osfhandle(osfd, _O_RDONLY); 420 if ( fd < 0 ) 421 { 422 pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 423 errno, "_open_osfhandle"); 424 return NULL; 425 } 426 427 file = _fdopen(fd, "rb"); 428 if ( file == NULL ) 429 { 430 pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 431 errno, "_fdopen"); 432 _close(fd); 433 return NULL; 434 } 435 436 return pcap_fopen_offline_with_tstamp_precision(file, precision, 437 errbuf); 438 } 439 440 pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf) 441 { 442 return pcap_hopen_offline_with_tstamp_precision(osfd, 443 PCAP_TSTAMP_PRECISION_MICRO, errbuf); 444 } 445 #endif 446 447 /* 448 * Given a link-layer header type and snapshot length, return a 449 * snapshot length to use when reading the file; it's guaranteed 450 * to be > 0 and <= INT_MAX. 451 * 452 * XXX - the only reason why we limit it to <= INT_MAX is so that 453 * it fits in p->snapshot, and the only reason that p->snapshot is 454 * signed is that pcap_snapshot() returns an int, not an unsigned int. 455 */ 456 bpf_u_int32 457 pcapint_adjust_snapshot(bpf_u_int32 linktype, bpf_u_int32 snaplen) 458 { 459 if (snaplen == 0 || snaplen > INT_MAX) { 460 /* 461 * Bogus snapshot length; use the maximum for this 462 * link-layer type as a fallback. 463 * 464 * XXX - we don't clamp snapshot lengths that are 465 * <= INT_MAX but > max_snaplen_for_dlt(linktype), 466 * so a capture file could cause us to allocate 467 * a Really Big Buffer. 468 */ 469 snaplen = max_snaplen_for_dlt(linktype); 470 } 471 return snaplen; 472 } 473 474 static pcap_t *(*check_headers[])(const uint8_t *, FILE *, u_int, char *, int *) = { 475 pcap_check_header, 476 pcap_ng_check_header 477 }; 478 479 #define N_FILE_TYPES (sizeof check_headers / sizeof check_headers[0]) 480 481 #ifdef _WIN32 482 static 483 #endif 484 pcap_t * 485 pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision, 486 char *errbuf) 487 { 488 register pcap_t *p; 489 uint8_t magic[4]; 490 size_t amt_read; 491 u_int i; 492 int err; 493 494 /* 495 * Fail if we were passed a NULL fp. 496 * 497 * That shouldn't happen if we're opening with a path name, but 498 * it could happen if buggy code is opening with a FILE * and 499 * didn't bother to make sure the FILE * isn't null. 500 */ 501 if (fp == NULL) { 502 snprintf(errbuf, PCAP_ERRBUF_SIZE, 503 "Null FILE * pointer provided to savefile open routine"); 504 return (NULL); 505 } 506 507 /* 508 * Read the first 4 bytes of the file; the network analyzer dump 509 * file formats we support (pcap and pcapng), and several other 510 * formats we might support in the future (such as snoop, DOS and 511 * Windows Sniffer, and Microsoft Network Monitor) all have magic 512 * numbers that are unique in their first 4 bytes. 513 */ 514 amt_read = fread(&magic, 1, sizeof(magic), fp); 515 if (amt_read != sizeof(magic)) { 516 if (ferror(fp)) { 517 pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 518 errno, "error reading dump file"); 519 } else { 520 snprintf(errbuf, PCAP_ERRBUF_SIZE, 521 "truncated dump file; tried to read %zu file header bytes, only got %zu", 522 sizeof(magic), amt_read); 523 } 524 return (NULL); 525 } 526 527 /* 528 * Try all file types. 529 */ 530 for (i = 0; i < N_FILE_TYPES; i++) { 531 p = (*check_headers[i])(magic, fp, precision, errbuf, &err); 532 if (p != NULL) { 533 /* Yup, that's it. */ 534 goto found; 535 } 536 if (err) { 537 /* 538 * Error trying to read the header. 539 */ 540 return (NULL); 541 } 542 } 543 544 /* 545 * Well, who knows what this mess is.... 546 */ 547 snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format"); 548 return (NULL); 549 550 found: 551 p->rfile = fp; 552 553 /* Padding only needed for live capture fcode */ 554 p->fddipad = 0; 555 556 #if !defined(_WIN32) && !defined(MSDOS) 557 /* 558 * You can do "select()" and "poll()" on plain files on most 559 * platforms, and should be able to do so on pipes. 560 * 561 * You can't do "select()" on anything other than sockets in 562 * Windows, so, on Win32 systems, we don't have "selectable_fd". 563 */ 564 p->selectable_fd = fileno(fp); 565 #endif 566 567 p->can_set_rfmon_op = sf_cant_set_rfmon; 568 p->read_op = pcapint_offline_read; 569 p->inject_op = sf_inject; 570 p->setfilter_op = pcapint_install_bpf_program; 571 p->setdirection_op = sf_setdirection; 572 p->set_datalink_op = NULL; /* we don't support munging link-layer headers */ 573 p->getnonblock_op = sf_getnonblock; 574 p->setnonblock_op = sf_setnonblock; 575 p->stats_op = sf_stats; 576 #ifdef _WIN32 577 p->stats_ex_op = sf_stats_ex; 578 p->setbuff_op = sf_setbuff; 579 p->setmode_op = sf_setmode; 580 p->setmintocopy_op = sf_setmintocopy; 581 p->getevent_op = sf_getevent; 582 p->oid_get_request_op = sf_oid_get_request; 583 p->oid_set_request_op = sf_oid_set_request; 584 p->sendqueue_transmit_op = sf_sendqueue_transmit; 585 p->setuserbuffer_op = sf_setuserbuffer; 586 p->live_dump_op = sf_live_dump; 587 p->live_dump_ended_op = sf_live_dump_ended; 588 p->get_airpcap_handle_op = sf_get_airpcap_handle; 589 #endif 590 591 /* 592 * For offline captures, the standard one-shot callback can 593 * be used for pcap_next()/pcap_next_ex(). 594 */ 595 p->oneshot_callback = pcapint_oneshot; 596 597 /* 598 * Default breakloop operation. 599 */ 600 p->breakloop_op = pcapint_breakloop_common; 601 602 /* 603 * Savefiles never require special BPF code generation. 604 */ 605 p->bpf_codegen_flags = 0; 606 607 p->activated = 1; 608 609 return (p); 610 } 611 612 /* 613 * This isn't needed on Windows; we #define pcap_fopen_offline() as 614 * a wrapper around pcap_hopen_offline(), and we don't call it from 615 * inside this file, so it's unused. 616 */ 617 #ifndef _WIN32 618 pcap_t * 619 pcap_fopen_offline(FILE *fp, char *errbuf) 620 { 621 return (pcap_fopen_offline_with_tstamp_precision(fp, 622 PCAP_TSTAMP_PRECISION_MICRO, errbuf)); 623 } 624 #endif 625 626 /* 627 * Read packets from a capture file, and call the callback for each 628 * packet. 629 * If cnt > 0, return after 'cnt' packets, otherwise continue until eof. 630 */ 631 int 632 pcapint_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 633 { 634 struct bpf_insn *fcode; 635 int n = 0; 636 u_char *data; 637 638 /* 639 * This can conceivably process more than INT_MAX packets, 640 * which would overflow the packet count, causing it either 641 * to look like a negative number, and thus cause us to 642 * return a value that looks like an error, or overflow 643 * back into positive territory, and thus cause us to 644 * return a too-low count. 645 * 646 * Therefore, if the packet count is unlimited, we clip 647 * it at INT_MAX; this routine is not expected to 648 * process packets indefinitely, so that's not an issue. 649 */ 650 if (PACKET_COUNT_IS_UNLIMITED(cnt)) 651 cnt = INT_MAX; 652 653 for (;;) { 654 struct pcap_pkthdr h; 655 int status; 656 657 /* 658 * Has "pcap_breakloop()" been called? 659 * If so, return immediately - if we haven't read any 660 * packets, clear the flag and return -2 to indicate 661 * that we were told to break out of the loop, otherwise 662 * leave the flag set, so that the *next* call will break 663 * out of the loop without having read any packets, and 664 * return the number of packets we've processed so far. 665 */ 666 if (p->break_loop) { 667 if (n == 0) { 668 p->break_loop = 0; 669 return (-2); 670 } else 671 return (n); 672 } 673 674 status = p->next_packet_op(p, &h, &data); 675 if (status < 0) { 676 /* 677 * Error. Pass it back to the caller. 678 */ 679 return (status); 680 } 681 if (status == 0) { 682 /* 683 * EOF. Nothing more to process; 684 */ 685 break; 686 } 687 688 /* 689 * OK, we've read a packet; run it through the filter 690 * and, if it passes, process it. 691 */ 692 if ((fcode = p->fcode.bf_insns) == NULL || 693 pcapint_filter(fcode, data, h.len, h.caplen)) { 694 (*callback)(user, &h, data); 695 n++; /* count the packet */ 696 if (n >= cnt) 697 break; 698 } 699 } 700 /*XXX this breaks semantics tcpslice expects */ 701 return (n); 702 } 703