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 * Check whether this is a pcap savefile and, if it is, extract the 127 * relevant information from the header. 128 */ 129 int 130 pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) 131 { 132 struct pcap_file_header hdr; 133 size_t amt_read; 134 135 /* 136 * Check whether the first 4 bytes of the file are the magic 137 * number for a pcap savefile, or for a byte-swapped pcap 138 * savefile. 139 */ 140 if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) { 141 magic = SWAPLONG(magic); 142 if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) 143 return (0); /* nope */ 144 p->sf.swapped = 1; 145 } 146 147 /* 148 * They are. Put the magic number in the header, and read 149 * the rest of the header. 150 */ 151 hdr.magic = magic; 152 amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1, 153 sizeof(hdr) - sizeof(hdr.magic), fp); 154 if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) { 155 if (ferror(fp)) { 156 snprintf(errbuf, PCAP_ERRBUF_SIZE, 157 "error reading dump file: %s", 158 pcap_strerror(errno)); 159 } else { 160 snprintf(errbuf, PCAP_ERRBUF_SIZE, 161 "truncated dump file; tried to read %lu file header bytes, only got %lu", 162 (unsigned long)sizeof(hdr), 163 (unsigned long)amt_read); 164 } 165 return (-1); 166 } 167 168 /* 169 * If it's a byte-swapped capture file, byte-swap the header. 170 */ 171 if (p->sf.swapped) { 172 hdr.version_major = SWAPSHORT(hdr.version_major); 173 hdr.version_minor = SWAPSHORT(hdr.version_minor); 174 hdr.thiszone = SWAPLONG(hdr.thiszone); 175 hdr.sigfigs = SWAPLONG(hdr.sigfigs); 176 hdr.snaplen = SWAPLONG(hdr.snaplen); 177 hdr.linktype = SWAPLONG(hdr.linktype); 178 } 179 180 if (hdr.version_major < PCAP_VERSION_MAJOR) { 181 snprintf(errbuf, PCAP_ERRBUF_SIZE, 182 "archaic pcap savefile format"); 183 return (-1); 184 } 185 p->sf.version_major = hdr.version_major; 186 p->sf.version_minor = hdr.version_minor; 187 p->tzoff = hdr.thiszone; 188 p->snapshot = hdr.snaplen; 189 p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype)); 190 p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype); 191 192 p->sf.next_packet_op = pcap_next_packet; 193 194 /* 195 * We interchanged the caplen and len fields at version 2.3, 196 * in order to match the bpf header layout. But unfortunately 197 * some files were written with version 2.3 in their headers 198 * but without the interchanged fields. 199 * 200 * In addition, DG/UX tcpdump writes out files with a version 201 * number of 543.0, and with the caplen and len fields in the 202 * pre-2.3 order. 203 */ 204 switch (hdr.version_major) { 205 206 case 2: 207 if (hdr.version_minor < 3) 208 p->sf.lengths_swapped = SWAPPED; 209 else if (hdr.version_minor == 3) 210 p->sf.lengths_swapped = MAYBE_SWAPPED; 211 else 212 p->sf.lengths_swapped = NOT_SWAPPED; 213 break; 214 215 case 543: 216 p->sf.lengths_swapped = SWAPPED; 217 break; 218 219 default: 220 p->sf.lengths_swapped = NOT_SWAPPED; 221 break; 222 } 223 224 if (magic == KUZNETZOV_TCPDUMP_MAGIC) { 225 /* 226 * XXX - the patch that's in some versions of libpcap 227 * changes the packet header but not the magic number, 228 * and some other versions with this magic number have 229 * some extra debugging information in the packet header; 230 * we'd have to use some hacks^H^H^H^H^Hheuristics to 231 * detect those variants. 232 * 233 * Ethereal does that, but it does so by trying to read 234 * the first two packets of the file with each of the 235 * record header formats. That currently means it seeks 236 * backwards and retries the reads, which doesn't work 237 * on pipes. We want to be able to read from a pipe, so 238 * that strategy won't work; we'd have to buffer some 239 * data ourselves and read from that buffer in order to 240 * make that work. 241 */ 242 p->sf.hdrsize = sizeof(struct pcap_sf_patched_pkthdr); 243 244 if (p->linktype == DLT_EN10MB) { 245 /* 246 * This capture might have been done in raw mode 247 * or cooked mode. 248 * 249 * If it was done in cooked mode, p->snapshot was 250 * passed to recvfrom() as the buffer size, meaning 251 * that the most packet data that would be copied 252 * would be p->snapshot. However, a faked Ethernet 253 * header would then have been added to it, so the 254 * most data that would be in a packet in the file 255 * would be p->snapshot + 14. 256 * 257 * We can't easily tell whether the capture was done 258 * in raw mode or cooked mode, so we'll assume it was 259 * cooked mode, and add 14 to the snapshot length. 260 * That means that, for a raw capture, the snapshot 261 * length will be misleading if you use it to figure 262 * out why a capture doesn't have all the packet data, 263 * but there's not much we can do to avoid that. 264 */ 265 p->snapshot += 14; 266 } 267 } else 268 p->sf.hdrsize = sizeof(struct pcap_sf_pkthdr); 269 270 /* 271 * Allocate a buffer for the packet data. 272 */ 273 p->bufsize = p->snapshot; 274 if (p->bufsize <= 0) { 275 /* 276 * Bogus snapshot length; use 64KiB as a fallback. 277 */ 278 p->bufsize = 65536; 279 } 280 p->buffer = malloc(p->bufsize); 281 if (p->buffer == NULL) { 282 snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory"); 283 return (-1); 284 } 285 286 return (1); 287 } 288 289 /* 290 * Read and return the next packet from the savefile. Return the header 291 * in hdr and a pointer to the contents in data. Return 0 on success, 1 292 * if there were no more packets, and -1 on an error. 293 */ 294 static int 295 pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) 296 { 297 struct pcap_sf_patched_pkthdr sf_hdr; 298 FILE *fp = p->sf.rfile; 299 size_t amt_read; 300 bpf_u_int32 t; 301 302 /* 303 * Read the packet header; the structure we use as a buffer 304 * is the longer structure for files generated by the patched 305 * libpcap, but if the file has the magic number for an 306 * unpatched libpcap we only read as many bytes as the regular 307 * header has. 308 */ 309 amt_read = fread(&sf_hdr, 1, p->sf.hdrsize, fp); 310 if (amt_read != p->sf.hdrsize) { 311 if (ferror(fp)) { 312 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 313 "error reading dump file: %s", 314 pcap_strerror(errno)); 315 return (-1); 316 } else { 317 if (amt_read != 0) { 318 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 319 "truncated dump file; tried to read %lu header bytes, only got %lu", 320 (unsigned long)p->sf.hdrsize, 321 (unsigned long)amt_read); 322 return (-1); 323 } 324 /* EOF */ 325 return (1); 326 } 327 } 328 329 if (p->sf.swapped) { 330 /* these were written in opposite byte order */ 331 hdr->caplen = SWAPLONG(sf_hdr.caplen); 332 hdr->len = SWAPLONG(sf_hdr.len); 333 hdr->ts.tv_sec = SWAPLONG(sf_hdr.ts.tv_sec); 334 hdr->ts.tv_usec = SWAPLONG(sf_hdr.ts.tv_usec); 335 } else { 336 hdr->caplen = sf_hdr.caplen; 337 hdr->len = sf_hdr.len; 338 hdr->ts.tv_sec = sf_hdr.ts.tv_sec; 339 hdr->ts.tv_usec = sf_hdr.ts.tv_usec; 340 } 341 /* Swap the caplen and len fields, if necessary. */ 342 switch (p->sf.lengths_swapped) { 343 344 case NOT_SWAPPED: 345 break; 346 347 case MAYBE_SWAPPED: 348 if (hdr->caplen <= hdr->len) { 349 /* 350 * The captured length is <= the actual length, 351 * so presumably they weren't swapped. 352 */ 353 break; 354 } 355 /* FALLTHROUGH */ 356 357 case SWAPPED: 358 t = hdr->caplen; 359 hdr->caplen = hdr->len; 360 hdr->len = t; 361 break; 362 } 363 364 if (hdr->caplen > p->bufsize) { 365 /* 366 * This can happen due to Solaris 2.3 systems tripping 367 * over the BUFMOD problem and not setting the snapshot 368 * correctly in the savefile header. If the caplen isn't 369 * grossly wrong, try to salvage. 370 */ 371 static u_char *tp = NULL; 372 static size_t tsize = 0; 373 374 if (hdr->caplen > 65535) { 375 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 376 "bogus savefile header"); 377 return (-1); 378 } 379 380 if (tsize < hdr->caplen) { 381 tsize = ((hdr->caplen + 1023) / 1024) * 1024; 382 if (tp != NULL) 383 free((u_char *)tp); 384 tp = (u_char *)malloc(tsize); 385 if (tp == NULL) { 386 tsize = 0; 387 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 388 "BUFMOD hack malloc"); 389 return (-1); 390 } 391 } 392 amt_read = fread((char *)tp, 1, hdr->caplen, fp); 393 if (amt_read != hdr->caplen) { 394 if (ferror(fp)) { 395 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 396 "error reading dump file: %s", 397 pcap_strerror(errno)); 398 } else { 399 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 400 "truncated dump file; tried to read %u captured bytes, only got %lu", 401 hdr->caplen, (unsigned long)amt_read); 402 } 403 return (-1); 404 } 405 /* 406 * We can only keep up to p->bufsize bytes. Since 407 * caplen > p->bufsize is exactly how we got here, 408 * we know we can only keep the first p->bufsize bytes 409 * and must drop the remainder. Adjust caplen accordingly, 410 * so we don't get confused later as to how many bytes we 411 * have to play with. 412 */ 413 hdr->caplen = p->bufsize; 414 memcpy(p->buffer, (char *)tp, p->bufsize); 415 } else { 416 /* read the packet itself */ 417 amt_read = fread(p->buffer, 1, hdr->caplen, fp); 418 if (amt_read != hdr->caplen) { 419 if (ferror(fp)) { 420 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 421 "error reading dump file: %s", 422 pcap_strerror(errno)); 423 } else { 424 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 425 "truncated dump file; tried to read %u captured bytes, only got %lu", 426 hdr->caplen, (unsigned long)amt_read); 427 } 428 return (-1); 429 } 430 } 431 *data = p->buffer; 432 433 if (p->sf.swapped) { 434 /* 435 * Convert pseudo-headers from the byte order of 436 * the host on which the file was saved to our 437 * byte order, as necessary. 438 */ 439 switch (p->linktype) { 440 441 case DLT_USB_LINUX: 442 swap_linux_usb_header(hdr, *data, 0); 443 break; 444 445 case DLT_USB_LINUX_MMAPPED: 446 swap_linux_usb_header(hdr, *data, 1); 447 break; 448 } 449 } 450 451 return (0); 452 } 453 454 static int 455 sf_write_header(FILE *fp, int linktype, int thiszone, int snaplen) 456 { 457 struct pcap_file_header hdr; 458 459 hdr.magic = TCPDUMP_MAGIC; 460 hdr.version_major = PCAP_VERSION_MAJOR; 461 hdr.version_minor = PCAP_VERSION_MINOR; 462 463 hdr.thiszone = thiszone; 464 hdr.snaplen = snaplen; 465 hdr.sigfigs = 0; 466 hdr.linktype = linktype; 467 468 if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) 469 return (-1); 470 471 return (0); 472 } 473 474 /* 475 * Output a packet to the initialized dump file. 476 */ 477 void 478 pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 479 { 480 register FILE *f; 481 struct pcap_sf_pkthdr sf_hdr; 482 483 f = (FILE *)user; 484 sf_hdr.ts.tv_sec = h->ts.tv_sec; 485 sf_hdr.ts.tv_usec = h->ts.tv_usec; 486 sf_hdr.caplen = h->caplen; 487 sf_hdr.len = h->len; 488 /* XXX we should check the return status */ 489 (void)fwrite(&sf_hdr, sizeof(sf_hdr), 1, f); 490 (void)fwrite(sp, h->caplen, 1, f); 491 } 492 493 static pcap_dumper_t * 494 pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname) 495 { 496 497 #if defined(WIN32) || defined(MSDOS) 498 /* 499 * If we're writing to the standard output, put it in binary 500 * mode, as savefiles are binary files. 501 * 502 * Otherwise, we turn off buffering. 503 * XXX - why? And why not on the standard output? 504 */ 505 if (f == stdout) 506 SET_BINMODE(f); 507 else 508 setbuf(f, NULL); 509 #endif 510 if (sf_write_header(f, linktype, p->tzoff, p->snapshot) == -1) { 511 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s", 512 fname, pcap_strerror(errno)); 513 if (f != stdout) 514 (void)fclose(f); 515 return (NULL); 516 } 517 return ((pcap_dumper_t *)f); 518 } 519 520 /* 521 * Initialize so that sf_write() will output to the file named 'fname'. 522 */ 523 pcap_dumper_t * 524 pcap_dump_open(pcap_t *p, const char *fname) 525 { 526 FILE *f; 527 int linktype; 528 529 /* 530 * If this pcap_t hasn't been activated, it doesn't have a 531 * link-layer type, so we can't use it. 532 */ 533 if (!p->activated) { 534 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 535 "%s: not-yet-activated pcap_t passed to pcap_dump_open", 536 fname); 537 return (NULL); 538 } 539 linktype = dlt_to_linktype(p->linktype); 540 if (linktype == -1) { 541 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 542 "%s: link-layer type %d isn't supported in savefiles", 543 fname, p->linktype); 544 return (NULL); 545 } 546 linktype |= p->linktype_ext; 547 548 if (fname[0] == '-' && fname[1] == '\0') { 549 f = stdout; 550 fname = "standard output"; 551 } else { 552 #if !defined(WIN32) && !defined(MSDOS) 553 f = fopen(fname, "w"); 554 #else 555 f = fopen(fname, "wb"); 556 #endif 557 if (f == NULL) { 558 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", 559 fname, pcap_strerror(errno)); 560 return (NULL); 561 } 562 } 563 return (pcap_setup_dump(p, linktype, f, fname)); 564 } 565 566 /* 567 * Initialize so that sf_write() will output to the given stream. 568 */ 569 pcap_dumper_t * 570 pcap_dump_fopen(pcap_t *p, FILE *f) 571 { 572 int linktype; 573 574 linktype = dlt_to_linktype(p->linktype); 575 if (linktype == -1) { 576 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 577 "stream: link-layer type %d isn't supported in savefiles", 578 p->linktype); 579 return (NULL); 580 } 581 linktype |= p->linktype_ext; 582 583 return (pcap_setup_dump(p, linktype, f, "stream")); 584 } 585 586 FILE * 587 pcap_dump_file(pcap_dumper_t *p) 588 { 589 return ((FILE *)p); 590 } 591 592 long 593 pcap_dump_ftell(pcap_dumper_t *p) 594 { 595 return (ftell((FILE *)p)); 596 } 597 598 int 599 pcap_dump_flush(pcap_dumper_t *p) 600 { 601 602 if (fflush((FILE *)p) == EOF) 603 return (-1); 604 else 605 return (0); 606 } 607 608 void 609 pcap_dump_close(pcap_dumper_t *p) 610 { 611 612 #ifdef notyet 613 if (ferror((FILE *)p)) 614 return-an-error; 615 /* XXX should check return from fclose() too */ 616 #endif 617 (void)fclose((FILE *)p); 618 } 619