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