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