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