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