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