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