1 /* 2 * Copyright (c) 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 * 21 * sf-pcap.c - libpcap-file-format-specific code from savefile.c 22 * Extraction/creation by Jeffrey Mogul, DECWRL 23 * Modified by Steve McCanne, LBL. 24 * 25 * Used to save the received packet headers, after filtering, to 26 * a file, and then read them later. 27 * The first record in the file contains saved values for the machine 28 * dependent values so we can print the dump file on any architecture. 29 */ 30 31 #ifndef lint 32 static const char rcsid[] _U_ = 33 "@(#) $Header$ (LBL)"; 34 #endif 35 36 #ifdef HAVE_CONFIG_H 37 #include "config.h" 38 #endif 39 40 #ifdef _WIN32 41 #include <pcap-stdinc.h> 42 #else /* _WIN32 */ 43 #if HAVE_INTTYPES_H 44 #include <inttypes.h> 45 #elif HAVE_STDINT_H 46 #include <stdint.h> 47 #endif 48 #ifdef HAVE_SYS_BITYPES_H 49 #include <sys/bitypes.h> 50 #endif 51 #include <sys/types.h> 52 #endif /* _WIN32 */ 53 54 #include <errno.h> 55 #include <memory.h> 56 #include <stdio.h> 57 #include <stdlib.h> 58 #include <string.h> 59 60 #include "pcap-int.h" 61 62 #include "pcap-common.h" 63 64 #ifdef HAVE_OS_PROTO_H 65 #include "os-proto.h" 66 #endif 67 68 #include "sf-pcap.h" 69 70 /* 71 * Setting O_BINARY on DOS/Windows is a bit tricky 72 */ 73 #if defined(_WIN32) 74 #define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY) 75 #elif defined(MSDOS) 76 #if defined(__HIGHC__) 77 #define SET_BINMODE(f) setmode(f, O_BINARY) 78 #else 79 #define SET_BINMODE(f) setmode(fileno(f), O_BINARY) 80 #endif 81 #endif 82 83 /* 84 * Standard libpcap format. 85 */ 86 #define TCPDUMP_MAGIC 0xa1b2c3d4 87 88 /* 89 * Alexey Kuznetzov's modified libpcap format. 90 */ 91 #define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34 92 93 /* 94 * Reserved for Francisco Mesquita <francisco.mesquita@radiomovel.pt> 95 * for another modified format. 96 */ 97 #define FMESQUITA_TCPDUMP_MAGIC 0xa1b234cd 98 99 /* 100 * Navtel Communcations' format, with nanosecond timestamps, 101 * as per a request from Dumas Hwang <dumas.hwang@navtelcom.com>. 102 */ 103 #define NAVTEL_TCPDUMP_MAGIC 0xa12b3c4d 104 105 /* 106 * Normal libpcap format, except for seconds/nanoseconds timestamps, 107 * as per a request by Ulf Lamping <ulf.lamping@web.de> 108 */ 109 #define NSEC_TCPDUMP_MAGIC 0xa1b23c4d 110 111 /* 112 * Mechanism for storing information about a capture in the upper 113 * 6 bits of a linktype value in a capture file. 114 * 115 * LT_LINKTYPE_EXT(x) extracts the additional information. 116 * 117 * The rest of the bits are for a value describing the link-layer 118 * value. LT_LINKTYPE(x) extracts that value. 119 */ 120 #define LT_LINKTYPE(x) ((x) & 0x03FFFFFF) 121 #define LT_LINKTYPE_EXT(x) ((x) & 0xFC000000) 122 123 static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap); 124 125 /* 126 * Private data for reading pcap savefiles. 127 */ 128 typedef enum { 129 NOT_SWAPPED, 130 SWAPPED, 131 MAYBE_SWAPPED 132 } swapped_type_t; 133 134 typedef enum { 135 PASS_THROUGH, 136 SCALE_UP, 137 SCALE_DOWN 138 } tstamp_scale_type_t; 139 140 struct pcap_sf { 141 size_t hdrsize; 142 swapped_type_t lengths_swapped; 143 tstamp_scale_type_t scale_type; 144 }; 145 146 /* 147 * Check whether this is a pcap savefile and, if it is, extract the 148 * relevant information from the header. 149 */ 150 pcap_t * 151 pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf, 152 int *err) 153 { 154 struct pcap_file_header hdr; 155 size_t amt_read; 156 pcap_t *p; 157 int swapped = 0; 158 struct pcap_sf *ps; 159 160 /* 161 * Assume no read errors. 162 */ 163 *err = 0; 164 165 /* 166 * Check whether the first 4 bytes of the file are the magic 167 * number for a pcap savefile, or for a byte-swapped pcap 168 * savefile. 169 */ 170 if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC && 171 magic != NSEC_TCPDUMP_MAGIC) { 172 magic = SWAPLONG(magic); 173 if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC && 174 magic != NSEC_TCPDUMP_MAGIC) 175 return (NULL); /* nope */ 176 swapped = 1; 177 } 178 179 /* 180 * They are. Put the magic number in the header, and read 181 * the rest of the header. 182 */ 183 hdr.magic = magic; 184 amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1, 185 sizeof(hdr) - sizeof(hdr.magic), fp); 186 if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) { 187 if (ferror(fp)) { 188 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 189 "error reading dump file: %s", 190 pcap_strerror(errno)); 191 } else { 192 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 193 "truncated dump file; tried to read %lu file header bytes, only got %lu", 194 (unsigned long)sizeof(hdr), 195 (unsigned long)amt_read); 196 } 197 *err = 1; 198 return (NULL); 199 } 200 201 /* 202 * If it's a byte-swapped capture file, byte-swap the header. 203 */ 204 if (swapped) { 205 hdr.version_major = SWAPSHORT(hdr.version_major); 206 hdr.version_minor = SWAPSHORT(hdr.version_minor); 207 hdr.thiszone = SWAPLONG(hdr.thiszone); 208 hdr.sigfigs = SWAPLONG(hdr.sigfigs); 209 hdr.snaplen = SWAPLONG(hdr.snaplen); 210 hdr.linktype = SWAPLONG(hdr.linktype); 211 } 212 213 if (hdr.version_major < PCAP_VERSION_MAJOR) { 214 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 215 "archaic pcap savefile format"); 216 *err = 1; 217 return (NULL); 218 } 219 220 /* 221 * currently only versions 2.[0-4] are supported with 222 * the exception of 543.0 for DG/UX tcpdump. 223 */ 224 if (! ((hdr.version_major == PCAP_VERSION_MAJOR && 225 hdr.version_minor <= PCAP_VERSION_MINOR) || 226 (hdr.version_major == 543 && 227 hdr.version_minor == 0))) { 228 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 229 "unsupported pcap savefile version %u.%u", 230 hdr.version_major, hdr.version_minor); 231 *err = 1; 232 return NULL; 233 } 234 235 if (hdr.snaplen > MAXIMUM_SNAPLEN) { 236 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 237 "invalid file capture length %u, bigger than " 238 "maximum of %u", hdr.snaplen, MAXIMUM_SNAPLEN); 239 *err = 1; 240 return NULL; 241 } 242 243 /* 244 * OK, this is a good pcap file. 245 * Allocate a pcap_t for it. 246 */ 247 p = pcap_open_offline_common(errbuf, sizeof (struct pcap_sf)); 248 if (p == NULL) { 249 /* Allocation failed. */ 250 *err = 1; 251 return (NULL); 252 } 253 p->swapped = swapped; 254 p->version_major = hdr.version_major; 255 p->version_minor = hdr.version_minor; 256 p->tzoff = hdr.thiszone; 257 p->snapshot = hdr.snaplen; 258 p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype)); 259 p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype); 260 261 p->next_packet_op = pcap_next_packet; 262 263 ps = p->priv; 264 265 p->opt.tstamp_precision = precision; 266 267 /* 268 * Will we need to scale the timestamps to match what the 269 * user wants? 270 */ 271 switch (precision) { 272 273 case PCAP_TSTAMP_PRECISION_MICRO: 274 if (magic == NSEC_TCPDUMP_MAGIC) { 275 /* 276 * The file has nanoseconds, the user 277 * wants microseconds; scale the 278 * precision down. 279 */ 280 ps->scale_type = SCALE_DOWN; 281 } else { 282 /* 283 * The file has microseconds, the 284 * user wants microseconds; nothing to do. 285 */ 286 ps->scale_type = PASS_THROUGH; 287 } 288 break; 289 290 case PCAP_TSTAMP_PRECISION_NANO: 291 if (magic == NSEC_TCPDUMP_MAGIC) { 292 /* 293 * The file has nanoseconds, the 294 * user wants nanoseconds; nothing to do. 295 */ 296 ps->scale_type = PASS_THROUGH; 297 } else { 298 /* 299 * The file has microoseconds, the user 300 * wants nanoseconds; scale the 301 * precision up. 302 */ 303 ps->scale_type = SCALE_UP; 304 } 305 break; 306 307 default: 308 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 309 "unknown time stamp resolution %u", precision); 310 free(p); 311 *err = 1; 312 return (NULL); 313 } 314 315 /* 316 * We interchanged the caplen and len fields at version 2.3, 317 * in order to match the bpf header layout. But unfortunately 318 * some files were written with version 2.3 in their headers 319 * but without the interchanged fields. 320 * 321 * In addition, DG/UX tcpdump writes out files with a version 322 * number of 543.0, and with the caplen and len fields in the 323 * pre-2.3 order. 324 */ 325 switch (hdr.version_major) { 326 327 case 2: 328 if (hdr.version_minor < 3) 329 ps->lengths_swapped = SWAPPED; 330 else if (hdr.version_minor == 3) 331 ps->lengths_swapped = MAYBE_SWAPPED; 332 else 333 ps->lengths_swapped = NOT_SWAPPED; 334 break; 335 336 case 543: 337 ps->lengths_swapped = SWAPPED; 338 break; 339 340 default: 341 ps->lengths_swapped = NOT_SWAPPED; 342 break; 343 } 344 345 if (magic == KUZNETZOV_TCPDUMP_MAGIC) { 346 /* 347 * XXX - the patch that's in some versions of libpcap 348 * changes the packet header but not the magic number, 349 * and some other versions with this magic number have 350 * some extra debugging information in the packet header; 351 * we'd have to use some hacks^H^H^H^H^Hheuristics to 352 * detect those variants. 353 * 354 * Ethereal does that, but it does so by trying to read 355 * the first two packets of the file with each of the 356 * record header formats. That currently means it seeks 357 * backwards and retries the reads, which doesn't work 358 * on pipes. We want to be able to read from a pipe, so 359 * that strategy won't work; we'd have to buffer some 360 * data ourselves and read from that buffer in order to 361 * make that work. 362 */ 363 ps->hdrsize = sizeof(struct pcap_sf_patched_pkthdr); 364 365 if (p->linktype == DLT_EN10MB) { 366 /* 367 * This capture might have been done in raw mode 368 * or cooked mode. 369 * 370 * If it was done in cooked mode, p->snapshot was 371 * passed to recvfrom() as the buffer size, meaning 372 * that the most packet data that would be copied 373 * would be p->snapshot. However, a faked Ethernet 374 * header would then have been added to it, so the 375 * most data that would be in a packet in the file 376 * would be p->snapshot + 14. 377 * 378 * We can't easily tell whether the capture was done 379 * in raw mode or cooked mode, so we'll assume it was 380 * cooked mode, and add 14 to the snapshot length. 381 * That means that, for a raw capture, the snapshot 382 * length will be misleading if you use it to figure 383 * out why a capture doesn't have all the packet data, 384 * but there's not much we can do to avoid that. 385 */ 386 p->snapshot += 14; 387 } 388 } else 389 ps->hdrsize = sizeof(struct pcap_sf_pkthdr); 390 391 /* 392 * Allocate a buffer for the packet data. 393 */ 394 p->bufsize = p->snapshot; 395 if (p->bufsize <= 0) { 396 /* 397 * Bogus snapshot length; use the maximum as a fallback. 398 */ 399 p->bufsize = MAXIMUM_SNAPLEN; 400 } 401 p->buffer = malloc(p->bufsize); 402 if (p->buffer == NULL) { 403 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory"); 404 free(p); 405 *err = 1; 406 return (NULL); 407 } 408 409 p->cleanup_op = sf_cleanup; 410 411 return (p); 412 } 413 414 /* 415 * Read and return the next packet from the savefile. Return the header 416 * in hdr and a pointer to the contents in data. Return 0 on success, 1 417 * if there were no more packets, and -1 on an error. 418 */ 419 static int 420 pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) 421 { 422 struct pcap_sf *ps = p->priv; 423 struct pcap_sf_patched_pkthdr sf_hdr; 424 FILE *fp = p->rfile; 425 size_t amt_read; 426 bpf_u_int32 t; 427 428 /* 429 * Read the packet header; the structure we use as a buffer 430 * is the longer structure for files generated by the patched 431 * libpcap, but if the file has the magic number for an 432 * unpatched libpcap we only read as many bytes as the regular 433 * header has. 434 */ 435 amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp); 436 if (amt_read != ps->hdrsize) { 437 if (ferror(fp)) { 438 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 439 "error reading dump file: %s", 440 pcap_strerror(errno)); 441 return (-1); 442 } else { 443 if (amt_read != 0) { 444 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 445 "truncated dump file; tried to read %lu header bytes, only got %lu", 446 (unsigned long)ps->hdrsize, 447 (unsigned long)amt_read); 448 return (-1); 449 } 450 /* EOF */ 451 return (1); 452 } 453 } 454 455 if (p->swapped) { 456 /* these were written in opposite byte order */ 457 hdr->caplen = SWAPLONG(sf_hdr.caplen); 458 hdr->len = SWAPLONG(sf_hdr.len); 459 hdr->ts.tv_sec = SWAPLONG(sf_hdr.ts.tv_sec); 460 hdr->ts.tv_usec = SWAPLONG(sf_hdr.ts.tv_usec); 461 } else { 462 hdr->caplen = sf_hdr.caplen; 463 hdr->len = sf_hdr.len; 464 hdr->ts.tv_sec = sf_hdr.ts.tv_sec; 465 hdr->ts.tv_usec = sf_hdr.ts.tv_usec; 466 } 467 468 switch (ps->scale_type) { 469 470 case PASS_THROUGH: 471 /* 472 * Just pass the time stamp through. 473 */ 474 break; 475 476 case SCALE_UP: 477 /* 478 * File has microseconds, user wants nanoseconds; convert 479 * it. 480 */ 481 hdr->ts.tv_usec = hdr->ts.tv_usec * 1000; 482 break; 483 484 case SCALE_DOWN: 485 /* 486 * File has nanoseconds, user wants microseconds; convert 487 * it. 488 */ 489 hdr->ts.tv_usec = hdr->ts.tv_usec / 1000; 490 break; 491 } 492 493 /* Swap the caplen and len fields, if necessary. */ 494 switch (ps->lengths_swapped) { 495 496 case NOT_SWAPPED: 497 break; 498 499 case MAYBE_SWAPPED: 500 if (hdr->caplen <= hdr->len) { 501 /* 502 * The captured length is <= the actual length, 503 * so presumably they weren't swapped. 504 */ 505 break; 506 } 507 /* FALLTHROUGH */ 508 509 case SWAPPED: 510 t = hdr->caplen; 511 hdr->caplen = hdr->len; 512 hdr->len = t; 513 break; 514 } 515 516 if (hdr->caplen > p->bufsize) { 517 /* 518 * This can happen due to Solaris 2.3 systems tripping 519 * over the BUFMOD problem and not setting the snapshot 520 * correctly in the savefile header. 521 * This can also happen with a corrupted savefile or a 522 * savefile built/modified by a fuzz tester. 523 * If the caplen isn't grossly wrong, try to salvage. 524 */ 525 size_t bytes_to_discard; 526 size_t bytes_to_read, bytes_read; 527 char discard_buf[4096]; 528 529 if (hdr->caplen > MAXIMUM_SNAPLEN) { 530 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 531 "invalid packet capture length %u, bigger than " 532 "maximum of %u", hdr->caplen, MAXIMUM_SNAPLEN); 533 return (-1); 534 } 535 536 /* 537 * XXX - we don't grow the buffer here because some 538 * program might assume that it will never get packets 539 * bigger than the snapshot length; for example, it might 540 * copy data from our buffer to a buffer of its own, 541 * allocated based on the return value of pcap_snapshot(). 542 * 543 * Read the first p->bufsize bytes into the buffer. 544 */ 545 amt_read = fread(p->buffer, 1, p->bufsize, fp); 546 if (amt_read != p->bufsize) { 547 if (ferror(fp)) { 548 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 549 "error reading dump file: %s", 550 pcap_strerror(errno)); 551 } else { 552 /* 553 * Yes, this uses hdr->caplen; technically, 554 * it's true, because we would try to read 555 * and discard the rest of those bytes, and 556 * that would fail because we got EOF before 557 * the read finished. 558 */ 559 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 560 "truncated dump file; tried to read %u captured bytes, only got %lu", 561 hdr->caplen, (unsigned long)amt_read); 562 } 563 return (-1); 564 } 565 566 /* 567 * Now read and discard what's left. 568 */ 569 bytes_to_discard = hdr->caplen - p->bufsize; 570 bytes_read = amt_read; 571 while (bytes_to_discard != 0) { 572 bytes_to_read = bytes_to_discard; 573 if (bytes_to_read > sizeof (discard_buf)) 574 bytes_to_read = sizeof (discard_buf); 575 amt_read = fread(discard_buf, 1, bytes_to_read, fp); 576 bytes_read += amt_read; 577 if (amt_read != bytes_to_read) { 578 if (ferror(fp)) { 579 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 580 "error reading dump file: %s", 581 pcap_strerror(errno)); 582 } else { 583 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 584 "truncated dump file; tried to read %u captured bytes, only got %lu", 585 hdr->caplen, (unsigned long)bytes_read); 586 } 587 return (-1); 588 } 589 bytes_to_discard -= amt_read; 590 } 591 592 /* 593 * Adjust caplen accordingly, so we don't get confused later 594 * as to how many bytes we have to play with. 595 */ 596 hdr->caplen = p->bufsize; 597 } else { 598 /* read the packet itself */ 599 amt_read = fread(p->buffer, 1, hdr->caplen, fp); 600 if (amt_read != hdr->caplen) { 601 if (ferror(fp)) { 602 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 603 "error reading dump file: %s", 604 pcap_strerror(errno)); 605 } else { 606 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 607 "truncated dump file; tried to read %u captured bytes, only got %lu", 608 hdr->caplen, (unsigned long)amt_read); 609 } 610 return (-1); 611 } 612 } 613 *data = p->buffer; 614 615 if (p->swapped) 616 swap_pseudo_headers(p->linktype, hdr, *data); 617 618 return (0); 619 } 620 621 static int 622 sf_write_header(pcap_t *p, FILE *fp, int linktype, int thiszone, int snaplen) 623 { 624 struct pcap_file_header hdr; 625 626 hdr.magic = p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? NSEC_TCPDUMP_MAGIC : TCPDUMP_MAGIC; 627 hdr.version_major = PCAP_VERSION_MAJOR; 628 hdr.version_minor = PCAP_VERSION_MINOR; 629 630 hdr.thiszone = thiszone; 631 hdr.snaplen = snaplen; 632 hdr.sigfigs = 0; 633 hdr.linktype = linktype; 634 635 if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) 636 return (-1); 637 638 return (0); 639 } 640 641 /* 642 * Output a packet to the initialized dump file. 643 */ 644 void 645 pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 646 { 647 register FILE *f; 648 struct pcap_sf_pkthdr sf_hdr; 649 650 f = (FILE *)user; 651 sf_hdr.ts.tv_sec = h->ts.tv_sec; 652 sf_hdr.ts.tv_usec = h->ts.tv_usec; 653 sf_hdr.caplen = h->caplen; 654 sf_hdr.len = h->len; 655 /* XXX we should check the return status */ 656 (void)fwrite(&sf_hdr, sizeof(sf_hdr), 1, f); 657 (void)fwrite(sp, h->caplen, 1, f); 658 } 659 660 static pcap_dumper_t * 661 pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname) 662 { 663 664 #if defined(_WIN32) || defined(MSDOS) 665 /* 666 * If we're writing to the standard output, put it in binary 667 * mode, as savefiles are binary files. 668 * 669 * Otherwise, we turn off buffering. 670 * XXX - why? And why not on the standard output? 671 */ 672 if (f == stdout) 673 SET_BINMODE(f); 674 else 675 setbuf(f, NULL); 676 #endif 677 if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) { 678 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s", 679 fname, pcap_strerror(errno)); 680 if (f != stdout) 681 (void)fclose(f); 682 return (NULL); 683 } 684 return ((pcap_dumper_t *)f); 685 } 686 687 /* 688 * Initialize so that sf_write() will output to the file named 'fname'. 689 */ 690 pcap_dumper_t * 691 pcap_dump_open(pcap_t *p, const char *fname) 692 { 693 FILE *f; 694 int linktype; 695 696 /* 697 * If this pcap_t hasn't been activated, it doesn't have a 698 * link-layer type, so we can't use it. 699 */ 700 if (!p->activated) { 701 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 702 "%s: not-yet-activated pcap_t passed to pcap_dump_open", 703 fname); 704 return (NULL); 705 } 706 linktype = dlt_to_linktype(p->linktype); 707 if (linktype == -1) { 708 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 709 "%s: link-layer type %d isn't supported in savefiles", 710 fname, p->linktype); 711 return (NULL); 712 } 713 linktype |= p->linktype_ext; 714 715 if (fname == NULL) { 716 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 717 "A null pointer was supplied as the file name"); 718 return NULL; 719 } 720 if (fname[0] == '-' && fname[1] == '\0') { 721 f = stdout; 722 fname = "standard output"; 723 } else { 724 #if !defined(_WIN32) && !defined(MSDOS) 725 f = fopen(fname, "w"); 726 #else 727 f = fopen(fname, "wb"); 728 #endif 729 if (f == NULL) { 730 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", 731 fname, pcap_strerror(errno)); 732 return (NULL); 733 } 734 } 735 return (pcap_setup_dump(p, linktype, f, fname)); 736 } 737 738 /* 739 * Initialize so that sf_write() will output to the given stream. 740 */ 741 pcap_dumper_t * 742 pcap_dump_fopen(pcap_t *p, FILE *f) 743 { 744 int linktype; 745 746 linktype = dlt_to_linktype(p->linktype); 747 if (linktype == -1) { 748 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 749 "stream: link-layer type %d isn't supported in savefiles", 750 p->linktype); 751 return (NULL); 752 } 753 linktype |= p->linktype_ext; 754 755 return (pcap_setup_dump(p, linktype, f, "stream")); 756 } 757 758 pcap_dumper_t * 759 pcap_dump_open_append(pcap_t *p, const char *fname) 760 { 761 FILE *f; 762 int linktype; 763 size_t amt_read; 764 struct pcap_file_header ph; 765 766 linktype = dlt_to_linktype(p->linktype); 767 if (linktype == -1) { 768 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 769 "%s: link-layer type %d isn't supported in savefiles", 770 fname, linktype); 771 return (NULL); 772 } 773 774 if (fname == NULL) { 775 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 776 "A null pointer was supplied as the file name"); 777 return NULL; 778 } 779 if (fname[0] == '-' && fname[1] == '\0') 780 return (pcap_setup_dump(p, linktype, stdout, "standard output")); 781 782 #if !defined(_WIN32) && !defined(MSDOS) 783 f = fopen(fname, "r+"); 784 #else 785 f = fopen(fname, "rb+"); 786 #endif 787 if (f == NULL) { 788 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", 789 fname, pcap_strerror(errno)); 790 return (NULL); 791 } 792 793 /* 794 * Try to read a pcap header. 795 */ 796 amt_read = fread(&ph, 1, sizeof (ph), f); 797 if (amt_read != sizeof (ph)) { 798 if (ferror(f)) { 799 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", 800 fname, pcap_strerror(errno)); 801 fclose(f); 802 return (NULL); 803 } else if (feof(f) && amt_read > 0) { 804 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 805 "%s: truncated pcap file header", fname); 806 fclose(f); 807 return (NULL); 808 } 809 } 810 811 #if defined(_WIN32) || defined(MSDOS) 812 /* 813 * We turn off buffering. 814 * XXX - why? And why not on the standard output? 815 */ 816 setbuf(f, NULL); 817 #endif 818 819 /* 820 * If a header is already present and: 821 * 822 * it's not for a pcap file of the appropriate resolution 823 * and the right byte order for this machine; 824 * 825 * the link-layer header types don't match; 826 * 827 * the snapshot lengths don't match; 828 * 829 * return an error. 830 */ 831 if (amt_read > 0) { 832 /* 833 * A header is already present. 834 * Do the checks. 835 */ 836 switch (ph.magic) { 837 838 case TCPDUMP_MAGIC: 839 if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_MICRO) { 840 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 841 "%s: different time stamp precision, cannot append to file", fname); 842 fclose(f); 843 return (NULL); 844 } 845 break; 846 847 case NSEC_TCPDUMP_MAGIC: 848 if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_NANO) { 849 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 850 "%s: different time stamp precision, cannot append to file", fname); 851 fclose(f); 852 return (NULL); 853 } 854 break; 855 856 case SWAPLONG(TCPDUMP_MAGIC): 857 case SWAPLONG(NSEC_TCPDUMP_MAGIC): 858 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 859 "%s: different byte order, cannot append to file", fname); 860 fclose(f); 861 return (NULL); 862 863 case KUZNETZOV_TCPDUMP_MAGIC: 864 case SWAPLONG(KUZNETZOV_TCPDUMP_MAGIC): 865 case NAVTEL_TCPDUMP_MAGIC: 866 case SWAPLONG(NAVTEL_TCPDUMP_MAGIC): 867 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 868 "%s: not a pcap file to which we can append", fname); 869 fclose(f); 870 return (NULL); 871 872 default: 873 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 874 "%s: not a pcap file", fname); 875 fclose(f); 876 return (NULL); 877 } 878 879 /* 880 * Good version? 881 */ 882 if (ph.version_major != PCAP_VERSION_MAJOR || 883 ph.version_minor != PCAP_VERSION_MINOR) { 884 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 885 "%s: version is %u.%u, cannot append to file", fname, 886 ph.version_major, ph.version_minor); 887 fclose(f); 888 return (NULL); 889 } 890 if ((bpf_u_int32)linktype != ph.linktype) { 891 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 892 "%s: different linktype, cannot append to file", fname); 893 fclose(f); 894 return (NULL); 895 } 896 if ((bpf_u_int32)p->snapshot != ph.snaplen) { 897 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 898 "%s: different snaplen, cannot append to file", fname); 899 fclose(f); 900 return (NULL); 901 } 902 } else { 903 /* 904 * A header isn't present; attempt to write it. 905 */ 906 if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) { 907 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s", 908 fname, pcap_strerror(errno)); 909 (void)fclose(f); 910 return (NULL); 911 } 912 } 913 914 /* 915 * Start writing at the end of the file. 916 */ 917 if (fseek(f, 0, SEEK_END) == -1) { 918 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't seek to end of %s: %s", 919 fname, pcap_strerror(errno)); 920 (void)fclose(f); 921 return (NULL); 922 } 923 return ((pcap_dumper_t *)f); 924 } 925 926 FILE * 927 pcap_dump_file(pcap_dumper_t *p) 928 { 929 return ((FILE *)p); 930 } 931 932 long 933 pcap_dump_ftell(pcap_dumper_t *p) 934 { 935 return (ftell((FILE *)p)); 936 } 937 938 int 939 pcap_dump_flush(pcap_dumper_t *p) 940 { 941 942 if (fflush((FILE *)p) == EOF) 943 return (-1); 944 else 945 return (0); 946 } 947 948 void 949 pcap_dump_close(pcap_dumper_t *p) 950 { 951 952 #ifdef notyet 953 if (ferror((FILE *)p)) 954 return-an-error; 955 /* XXX should check return from fclose() too */ 956 #endif 957 (void)fclose((FILE *)p); 958 } 959