xref: /minix3/external/bsd/libpcap/dist/savefile.c (revision d56f51ea7d8b9045e5c8e2028422523d3f9a5840)
1*d56f51eaSDavid van Moolenbroek /*	$NetBSD: savefile.c,v 1.3 2015/03/31 21:39:42 christos Exp $	*/
2*d56f51eaSDavid van Moolenbroek 
3*d56f51eaSDavid van Moolenbroek /*
4*d56f51eaSDavid van Moolenbroek  * Copyright (c) 1993, 1994, 1995, 1996, 1997
5*d56f51eaSDavid van Moolenbroek  *	The Regents of the University of California.  All rights reserved.
6*d56f51eaSDavid van Moolenbroek  *
7*d56f51eaSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
8*d56f51eaSDavid van Moolenbroek  * modification, are permitted provided that: (1) source code distributions
9*d56f51eaSDavid van Moolenbroek  * retain the above copyright notice and this paragraph in its entirety, (2)
10*d56f51eaSDavid van Moolenbroek  * distributions including binary code include the above copyright notice and
11*d56f51eaSDavid van Moolenbroek  * this paragraph in its entirety in the documentation or other materials
12*d56f51eaSDavid van Moolenbroek  * provided with the distribution, and (3) all advertising materials mentioning
13*d56f51eaSDavid van Moolenbroek  * features or use of this software display the following acknowledgement:
14*d56f51eaSDavid van Moolenbroek  * ``This product includes software developed by the University of California,
15*d56f51eaSDavid van Moolenbroek  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16*d56f51eaSDavid van Moolenbroek  * the University nor the names of its contributors may be used to endorse
17*d56f51eaSDavid van Moolenbroek  * or promote products derived from this software without specific prior
18*d56f51eaSDavid van Moolenbroek  * written permission.
19*d56f51eaSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20*d56f51eaSDavid van Moolenbroek  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21*d56f51eaSDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22*d56f51eaSDavid van Moolenbroek  *
23*d56f51eaSDavid van Moolenbroek  * savefile.c - supports offline use of tcpdump
24*d56f51eaSDavid van Moolenbroek  *	Extraction/creation by Jeffrey Mogul, DECWRL
25*d56f51eaSDavid van Moolenbroek  *	Modified by Steve McCanne, LBL.
26*d56f51eaSDavid van Moolenbroek  *
27*d56f51eaSDavid van Moolenbroek  * Used to save the received packet headers, after filtering, to
28*d56f51eaSDavid van Moolenbroek  * a file, and then read them later.
29*d56f51eaSDavid van Moolenbroek  * The first record in the file contains saved values for the machine
30*d56f51eaSDavid van Moolenbroek  * dependent values so we can print the dump file on any architecture.
31*d56f51eaSDavid van Moolenbroek  */
32*d56f51eaSDavid van Moolenbroek 
33*d56f51eaSDavid van Moolenbroek #include <sys/cdefs.h>
34*d56f51eaSDavid van Moolenbroek __RCSID("$NetBSD: savefile.c,v 1.3 2015/03/31 21:39:42 christos Exp $");
35*d56f51eaSDavid van Moolenbroek 
36*d56f51eaSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
37*d56f51eaSDavid van Moolenbroek #include "config.h"
38*d56f51eaSDavid van Moolenbroek #endif
39*d56f51eaSDavid van Moolenbroek 
40*d56f51eaSDavid van Moolenbroek #ifdef WIN32
41*d56f51eaSDavid van Moolenbroek #include <pcap-stdinc.h>
42*d56f51eaSDavid van Moolenbroek #else /* WIN32 */
43*d56f51eaSDavid van Moolenbroek #if HAVE_INTTYPES_H
44*d56f51eaSDavid van Moolenbroek #include <inttypes.h>
45*d56f51eaSDavid van Moolenbroek #elif HAVE_STDINT_H
46*d56f51eaSDavid van Moolenbroek #include <stdint.h>
47*d56f51eaSDavid van Moolenbroek #endif
48*d56f51eaSDavid van Moolenbroek #ifdef HAVE_SYS_BITYPES_H
49*d56f51eaSDavid van Moolenbroek #include <sys/bitypes.h>
50*d56f51eaSDavid van Moolenbroek #endif
51*d56f51eaSDavid van Moolenbroek #include <sys/types.h>
52*d56f51eaSDavid van Moolenbroek #endif /* WIN32 */
53*d56f51eaSDavid van Moolenbroek 
54*d56f51eaSDavid van Moolenbroek #include <errno.h>
55*d56f51eaSDavid van Moolenbroek #include <memory.h>
56*d56f51eaSDavid van Moolenbroek #include <stdio.h>
57*d56f51eaSDavid van Moolenbroek #include <stdlib.h>
58*d56f51eaSDavid van Moolenbroek #include <string.h>
59*d56f51eaSDavid van Moolenbroek 
60*d56f51eaSDavid van Moolenbroek #include "pcap-int.h"
61*d56f51eaSDavid van Moolenbroek #include "pcap/usb.h"
62*d56f51eaSDavid van Moolenbroek 
63*d56f51eaSDavid van Moolenbroek #ifdef HAVE_OS_PROTO_H
64*d56f51eaSDavid van Moolenbroek #include "os-proto.h"
65*d56f51eaSDavid van Moolenbroek #endif
66*d56f51eaSDavid van Moolenbroek 
67*d56f51eaSDavid van Moolenbroek #include "sf-pcap.h"
68*d56f51eaSDavid van Moolenbroek #include "sf-pcap-ng.h"
69*d56f51eaSDavid van Moolenbroek 
70*d56f51eaSDavid van Moolenbroek /*
71*d56f51eaSDavid van Moolenbroek  * Setting O_BINARY on DOS/Windows is a bit tricky
72*d56f51eaSDavid van Moolenbroek  */
73*d56f51eaSDavid van Moolenbroek #if defined(WIN32)
74*d56f51eaSDavid van Moolenbroek   #define SET_BINMODE(f)  _setmode(_fileno(f), _O_BINARY)
75*d56f51eaSDavid van Moolenbroek #elif defined(MSDOS)
76*d56f51eaSDavid van Moolenbroek   #if defined(__HIGHC__)
77*d56f51eaSDavid van Moolenbroek   #define SET_BINMODE(f)  setmode(f, O_BINARY)
78*d56f51eaSDavid van Moolenbroek   #else
79*d56f51eaSDavid van Moolenbroek   #define SET_BINMODE(f)  setmode(fileno(f), O_BINARY)
80*d56f51eaSDavid van Moolenbroek   #endif
81*d56f51eaSDavid van Moolenbroek #endif
82*d56f51eaSDavid van Moolenbroek 
83*d56f51eaSDavid van Moolenbroek static int
sf_getnonblock(pcap_t * p,char * errbuf)84*d56f51eaSDavid van Moolenbroek sf_getnonblock(pcap_t *p, char *errbuf)
85*d56f51eaSDavid van Moolenbroek {
86*d56f51eaSDavid van Moolenbroek 	/*
87*d56f51eaSDavid van Moolenbroek 	 * This is a savefile, not a live capture file, so never say
88*d56f51eaSDavid van Moolenbroek 	 * it's in non-blocking mode.
89*d56f51eaSDavid van Moolenbroek 	 */
90*d56f51eaSDavid van Moolenbroek 	return (0);
91*d56f51eaSDavid van Moolenbroek }
92*d56f51eaSDavid van Moolenbroek 
93*d56f51eaSDavid van Moolenbroek static int
sf_setnonblock(pcap_t * p,int nonblock,char * errbuf)94*d56f51eaSDavid van Moolenbroek sf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
95*d56f51eaSDavid van Moolenbroek {
96*d56f51eaSDavid van Moolenbroek 	/*
97*d56f51eaSDavid van Moolenbroek 	 * This is a savefile, not a live capture file, so reject
98*d56f51eaSDavid van Moolenbroek 	 * requests to put it in non-blocking mode.  (If it's a
99*d56f51eaSDavid van Moolenbroek 	 * pipe, it could be put in non-blocking mode, but that
100*d56f51eaSDavid van Moolenbroek 	 * would significantly complicate the code to read packets,
101*d56f51eaSDavid van Moolenbroek 	 * as it would have to handle reading partial packets and
102*d56f51eaSDavid van Moolenbroek 	 * keeping the state of the read.)
103*d56f51eaSDavid van Moolenbroek 	 */
104*d56f51eaSDavid van Moolenbroek 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
105*d56f51eaSDavid van Moolenbroek 	    "Savefiles cannot be put into non-blocking mode");
106*d56f51eaSDavid van Moolenbroek 	return (-1);
107*d56f51eaSDavid van Moolenbroek }
108*d56f51eaSDavid van Moolenbroek 
109*d56f51eaSDavid van Moolenbroek static int
sf_stats(pcap_t * p,struct pcap_stat * ps)110*d56f51eaSDavid van Moolenbroek sf_stats(pcap_t *p, struct pcap_stat *ps)
111*d56f51eaSDavid van Moolenbroek {
112*d56f51eaSDavid van Moolenbroek 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
113*d56f51eaSDavid van Moolenbroek 	    "Statistics aren't available from savefiles");
114*d56f51eaSDavid van Moolenbroek 	return (-1);
115*d56f51eaSDavid van Moolenbroek }
116*d56f51eaSDavid van Moolenbroek 
117*d56f51eaSDavid van Moolenbroek #ifdef WIN32
118*d56f51eaSDavid van Moolenbroek static int
sf_setbuff(pcap_t * p,int dim)119*d56f51eaSDavid van Moolenbroek sf_setbuff(pcap_t *p, int dim)
120*d56f51eaSDavid van Moolenbroek {
121*d56f51eaSDavid van Moolenbroek 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
122*d56f51eaSDavid van Moolenbroek 	    "The kernel buffer size cannot be set while reading from a file");
123*d56f51eaSDavid van Moolenbroek 	return (-1);
124*d56f51eaSDavid van Moolenbroek }
125*d56f51eaSDavid van Moolenbroek 
126*d56f51eaSDavid van Moolenbroek static int
sf_setmode(pcap_t * p,int mode)127*d56f51eaSDavid van Moolenbroek sf_setmode(pcap_t *p, int mode)
128*d56f51eaSDavid van Moolenbroek {
129*d56f51eaSDavid van Moolenbroek 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
130*d56f51eaSDavid van Moolenbroek 	    "impossible to set mode while reading from a file");
131*d56f51eaSDavid van Moolenbroek 	return (-1);
132*d56f51eaSDavid van Moolenbroek }
133*d56f51eaSDavid van Moolenbroek 
134*d56f51eaSDavid van Moolenbroek static int
sf_setmintocopy(pcap_t * p,int size)135*d56f51eaSDavid van Moolenbroek sf_setmintocopy(pcap_t *p, int size)
136*d56f51eaSDavid van Moolenbroek {
137*d56f51eaSDavid van Moolenbroek 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
138*d56f51eaSDavid van Moolenbroek 	    "The mintocopy parameter cannot be set while reading from a file");
139*d56f51eaSDavid van Moolenbroek 	return (-1);
140*d56f51eaSDavid van Moolenbroek }
141*d56f51eaSDavid van Moolenbroek #endif
142*d56f51eaSDavid van Moolenbroek 
143*d56f51eaSDavid van Moolenbroek static int
sf_inject(pcap_t * p,const void * buf _U_,size_t size _U_)144*d56f51eaSDavid van Moolenbroek sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
145*d56f51eaSDavid van Moolenbroek {
146*d56f51eaSDavid van Moolenbroek 	strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
147*d56f51eaSDavid van Moolenbroek 	    PCAP_ERRBUF_SIZE);
148*d56f51eaSDavid van Moolenbroek 	return (-1);
149*d56f51eaSDavid van Moolenbroek }
150*d56f51eaSDavid van Moolenbroek 
151*d56f51eaSDavid van Moolenbroek /*
152*d56f51eaSDavid van Moolenbroek  * Set direction flag: Which packets do we accept on a forwarding
153*d56f51eaSDavid van Moolenbroek  * single device? IN, OUT or both?
154*d56f51eaSDavid van Moolenbroek  */
155*d56f51eaSDavid van Moolenbroek static int
sf_setdirection(pcap_t * p,pcap_direction_t d)156*d56f51eaSDavid van Moolenbroek sf_setdirection(pcap_t *p, pcap_direction_t d)
157*d56f51eaSDavid van Moolenbroek {
158*d56f51eaSDavid van Moolenbroek 	snprintf(p->errbuf, sizeof(p->errbuf),
159*d56f51eaSDavid van Moolenbroek 	    "Setting direction is not supported on savefiles");
160*d56f51eaSDavid van Moolenbroek 	return (-1);
161*d56f51eaSDavid van Moolenbroek }
162*d56f51eaSDavid van Moolenbroek 
163*d56f51eaSDavid van Moolenbroek void
sf_cleanup(pcap_t * p)164*d56f51eaSDavid van Moolenbroek sf_cleanup(pcap_t *p)
165*d56f51eaSDavid van Moolenbroek {
166*d56f51eaSDavid van Moolenbroek 	if (p->rfile != stdin)
167*d56f51eaSDavid van Moolenbroek 		(void)fclose(p->rfile);
168*d56f51eaSDavid van Moolenbroek 	if (p->buffer != NULL)
169*d56f51eaSDavid van Moolenbroek 		free(p->buffer);
170*d56f51eaSDavid van Moolenbroek 	pcap_freecode(&p->fcode);
171*d56f51eaSDavid van Moolenbroek }
172*d56f51eaSDavid van Moolenbroek 
173*d56f51eaSDavid van Moolenbroek pcap_t *
pcap_open_offline_with_tstamp_precision(const char * fname,u_int precision,char * errbuf)174*d56f51eaSDavid van Moolenbroek pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
175*d56f51eaSDavid van Moolenbroek     char *errbuf)
176*d56f51eaSDavid van Moolenbroek {
177*d56f51eaSDavid van Moolenbroek 	FILE *fp;
178*d56f51eaSDavid van Moolenbroek 	pcap_t *p;
179*d56f51eaSDavid van Moolenbroek 
180*d56f51eaSDavid van Moolenbroek 	if (fname[0] == '-' && fname[1] == '\0')
181*d56f51eaSDavid van Moolenbroek 	{
182*d56f51eaSDavid van Moolenbroek 		fp = stdin;
183*d56f51eaSDavid van Moolenbroek #if defined(WIN32) || defined(MSDOS)
184*d56f51eaSDavid van Moolenbroek 		/*
185*d56f51eaSDavid van Moolenbroek 		 * We're reading from the standard input, so put it in binary
186*d56f51eaSDavid van Moolenbroek 		 * mode, as savefiles are binary files.
187*d56f51eaSDavid van Moolenbroek 		 */
188*d56f51eaSDavid van Moolenbroek 		SET_BINMODE(fp);
189*d56f51eaSDavid van Moolenbroek #endif
190*d56f51eaSDavid van Moolenbroek 	}
191*d56f51eaSDavid van Moolenbroek 	else {
192*d56f51eaSDavid van Moolenbroek #if !defined(WIN32) && !defined(MSDOS)
193*d56f51eaSDavid van Moolenbroek 		fp = fopen(fname, "r");
194*d56f51eaSDavid van Moolenbroek #else
195*d56f51eaSDavid van Moolenbroek 		fp = fopen(fname, "rb");
196*d56f51eaSDavid van Moolenbroek #endif
197*d56f51eaSDavid van Moolenbroek 		if (fp == NULL) {
198*d56f51eaSDavid van Moolenbroek 			snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
199*d56f51eaSDavid van Moolenbroek 			    pcap_strerror(errno));
200*d56f51eaSDavid van Moolenbroek 			return (NULL);
201*d56f51eaSDavid van Moolenbroek 		}
202*d56f51eaSDavid van Moolenbroek 	}
203*d56f51eaSDavid van Moolenbroek 	p = pcap_fopen_offline_with_tstamp_precision(fp, precision, errbuf);
204*d56f51eaSDavid van Moolenbroek 	if (p == NULL) {
205*d56f51eaSDavid van Moolenbroek 		if (fp != stdin)
206*d56f51eaSDavid van Moolenbroek 			fclose(fp);
207*d56f51eaSDavid van Moolenbroek 	}
208*d56f51eaSDavid van Moolenbroek 	return (p);
209*d56f51eaSDavid van Moolenbroek }
210*d56f51eaSDavid van Moolenbroek 
211*d56f51eaSDavid van Moolenbroek pcap_t *
pcap_open_offline(const char * fname,char * errbuf)212*d56f51eaSDavid van Moolenbroek pcap_open_offline(const char *fname, char *errbuf)
213*d56f51eaSDavid van Moolenbroek {
214*d56f51eaSDavid van Moolenbroek 	return (pcap_open_offline_with_tstamp_precision(fname,
215*d56f51eaSDavid van Moolenbroek 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf));
216*d56f51eaSDavid van Moolenbroek }
217*d56f51eaSDavid van Moolenbroek 
218*d56f51eaSDavid van Moolenbroek #ifdef WIN32
pcap_hopen_offline_with_tstamp_precision(intptr_t osfd,u_int precision,char * errbuf)219*d56f51eaSDavid van Moolenbroek pcap_t* pcap_hopen_offline_with_tstamp_precision(intptr_t osfd, u_int precision,
220*d56f51eaSDavid van Moolenbroek     char *errbuf)
221*d56f51eaSDavid van Moolenbroek {
222*d56f51eaSDavid van Moolenbroek 	int fd;
223*d56f51eaSDavid van Moolenbroek 	FILE *file;
224*d56f51eaSDavid van Moolenbroek 
225*d56f51eaSDavid van Moolenbroek 	fd = _open_osfhandle(osfd, _O_RDONLY);
226*d56f51eaSDavid van Moolenbroek 	if ( fd < 0 )
227*d56f51eaSDavid van Moolenbroek 	{
228*d56f51eaSDavid van Moolenbroek 		snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
229*d56f51eaSDavid van Moolenbroek 		return NULL;
230*d56f51eaSDavid van Moolenbroek 	}
231*d56f51eaSDavid van Moolenbroek 
232*d56f51eaSDavid van Moolenbroek 	file = _fdopen(fd, "rb");
233*d56f51eaSDavid van Moolenbroek 	if ( file == NULL )
234*d56f51eaSDavid van Moolenbroek 	{
235*d56f51eaSDavid van Moolenbroek 		snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
236*d56f51eaSDavid van Moolenbroek 		return NULL;
237*d56f51eaSDavid van Moolenbroek 	}
238*d56f51eaSDavid van Moolenbroek 
239*d56f51eaSDavid van Moolenbroek 	return pcap_fopen_offline_with_tstamp_precision(file, precision,
240*d56f51eaSDavid van Moolenbroek 	    errbuf);
241*d56f51eaSDavid van Moolenbroek }
242*d56f51eaSDavid van Moolenbroek 
pcap_hopen_offline(intptr_t osfd,char * errbuf)243*d56f51eaSDavid van Moolenbroek pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
244*d56f51eaSDavid van Moolenbroek {
245*d56f51eaSDavid van Moolenbroek 	return pcap_hopen_offline_with_tstamp_precision(osfd,
246*d56f51eaSDavid van Moolenbroek 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf);
247*d56f51eaSDavid van Moolenbroek }
248*d56f51eaSDavid van Moolenbroek #endif
249*d56f51eaSDavid van Moolenbroek 
250*d56f51eaSDavid van Moolenbroek static pcap_t *(*check_headers[])(bpf_u_int32, FILE *, u_int, char *, int *) = {
251*d56f51eaSDavid van Moolenbroek 	pcap_check_header,
252*d56f51eaSDavid van Moolenbroek 	pcap_ng_check_header
253*d56f51eaSDavid van Moolenbroek };
254*d56f51eaSDavid van Moolenbroek 
255*d56f51eaSDavid van Moolenbroek #define	N_FILE_TYPES	(sizeof check_headers / sizeof check_headers[0])
256*d56f51eaSDavid van Moolenbroek 
257*d56f51eaSDavid van Moolenbroek #ifdef WIN32
258*d56f51eaSDavid van Moolenbroek static
259*d56f51eaSDavid van Moolenbroek #endif
260*d56f51eaSDavid van Moolenbroek pcap_t *
pcap_fopen_offline_with_tstamp_precision(FILE * fp,u_int precision,char * errbuf)261*d56f51eaSDavid van Moolenbroek pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision,
262*d56f51eaSDavid van Moolenbroek     char *errbuf)
263*d56f51eaSDavid van Moolenbroek {
264*d56f51eaSDavid van Moolenbroek 	register pcap_t *p;
265*d56f51eaSDavid van Moolenbroek 	bpf_u_int32 magic;
266*d56f51eaSDavid van Moolenbroek 	size_t amt_read;
267*d56f51eaSDavid van Moolenbroek 	u_int i;
268*d56f51eaSDavid van Moolenbroek 	int err;
269*d56f51eaSDavid van Moolenbroek 
270*d56f51eaSDavid van Moolenbroek 	/*
271*d56f51eaSDavid van Moolenbroek 	 * Read the first 4 bytes of the file; the network analyzer dump
272*d56f51eaSDavid van Moolenbroek 	 * file formats we support (pcap and pcap-ng), and several other
273*d56f51eaSDavid van Moolenbroek 	 * formats we might support in the future (such as snoop, DOS and
274*d56f51eaSDavid van Moolenbroek 	 * Windows Sniffer, and Microsoft Network Monitor) all have magic
275*d56f51eaSDavid van Moolenbroek 	 * numbers that are unique in their first 4 bytes.
276*d56f51eaSDavid van Moolenbroek 	 */
277*d56f51eaSDavid van Moolenbroek 	amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
278*d56f51eaSDavid van Moolenbroek 	if (amt_read != sizeof(magic)) {
279*d56f51eaSDavid van Moolenbroek 		if (ferror(fp)) {
280*d56f51eaSDavid van Moolenbroek 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
281*d56f51eaSDavid van Moolenbroek 			    "error reading dump file: %s",
282*d56f51eaSDavid van Moolenbroek 			    pcap_strerror(errno));
283*d56f51eaSDavid van Moolenbroek 		} else {
284*d56f51eaSDavid van Moolenbroek 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
285*d56f51eaSDavid van Moolenbroek 			    "truncated dump file; tried to read %lu file header bytes, only got %lu",
286*d56f51eaSDavid van Moolenbroek 			    (unsigned long)sizeof(magic),
287*d56f51eaSDavid van Moolenbroek 			    (unsigned long)amt_read);
288*d56f51eaSDavid van Moolenbroek 		}
289*d56f51eaSDavid van Moolenbroek 		return (NULL);
290*d56f51eaSDavid van Moolenbroek 	}
291*d56f51eaSDavid van Moolenbroek 
292*d56f51eaSDavid van Moolenbroek 	/*
293*d56f51eaSDavid van Moolenbroek 	 * Try all file types.
294*d56f51eaSDavid van Moolenbroek 	 */
295*d56f51eaSDavid van Moolenbroek 	for (i = 0; i < N_FILE_TYPES; i++) {
296*d56f51eaSDavid van Moolenbroek 		p = (*check_headers[i])(magic, fp, precision, errbuf, &err);
297*d56f51eaSDavid van Moolenbroek 		if (p != NULL) {
298*d56f51eaSDavid van Moolenbroek 			/* Yup, that's it. */
299*d56f51eaSDavid van Moolenbroek 			goto found;
300*d56f51eaSDavid van Moolenbroek 		}
301*d56f51eaSDavid van Moolenbroek 		if (err) {
302*d56f51eaSDavid van Moolenbroek 			/*
303*d56f51eaSDavid van Moolenbroek 			 * Error trying to read the header.
304*d56f51eaSDavid van Moolenbroek 			 */
305*d56f51eaSDavid van Moolenbroek 			return (NULL);
306*d56f51eaSDavid van Moolenbroek 		}
307*d56f51eaSDavid van Moolenbroek 	}
308*d56f51eaSDavid van Moolenbroek 
309*d56f51eaSDavid van Moolenbroek 	/*
310*d56f51eaSDavid van Moolenbroek 	 * Well, who knows what this mess is....
311*d56f51eaSDavid van Moolenbroek 	 */
312*d56f51eaSDavid van Moolenbroek 	snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
313*d56f51eaSDavid van Moolenbroek 	return (NULL);
314*d56f51eaSDavid van Moolenbroek 
315*d56f51eaSDavid van Moolenbroek found:
316*d56f51eaSDavid van Moolenbroek 	p->rfile = fp;
317*d56f51eaSDavid van Moolenbroek 
318*d56f51eaSDavid van Moolenbroek 	/* Padding only needed for live capture fcode */
319*d56f51eaSDavid van Moolenbroek 	p->fddipad = 0;
320*d56f51eaSDavid van Moolenbroek 
321*d56f51eaSDavid van Moolenbroek #if !defined(WIN32) && !defined(MSDOS)
322*d56f51eaSDavid van Moolenbroek 	/*
323*d56f51eaSDavid van Moolenbroek 	 * You can do "select()" and "poll()" on plain files on most
324*d56f51eaSDavid van Moolenbroek 	 * platforms, and should be able to do so on pipes.
325*d56f51eaSDavid van Moolenbroek 	 *
326*d56f51eaSDavid van Moolenbroek 	 * You can't do "select()" on anything other than sockets in
327*d56f51eaSDavid van Moolenbroek 	 * Windows, so, on Win32 systems, we don't have "selectable_fd".
328*d56f51eaSDavid van Moolenbroek 	 */
329*d56f51eaSDavid van Moolenbroek 	p->selectable_fd = fileno(fp);
330*d56f51eaSDavid van Moolenbroek #endif
331*d56f51eaSDavid van Moolenbroek 
332*d56f51eaSDavid van Moolenbroek 	p->read_op = pcap_offline_read;
333*d56f51eaSDavid van Moolenbroek 	p->inject_op = sf_inject;
334*d56f51eaSDavid van Moolenbroek 	p->setfilter_op = install_bpf_program;
335*d56f51eaSDavid van Moolenbroek 	p->setdirection_op = sf_setdirection;
336*d56f51eaSDavid van Moolenbroek 	p->set_datalink_op = NULL;	/* we don't support munging link-layer headers */
337*d56f51eaSDavid van Moolenbroek 	p->getnonblock_op = sf_getnonblock;
338*d56f51eaSDavid van Moolenbroek 	p->setnonblock_op = sf_setnonblock;
339*d56f51eaSDavid van Moolenbroek 	p->stats_op = sf_stats;
340*d56f51eaSDavid van Moolenbroek #ifdef WIN32
341*d56f51eaSDavid van Moolenbroek 	p->setbuff_op = sf_setbuff;
342*d56f51eaSDavid van Moolenbroek 	p->setmode_op = sf_setmode;
343*d56f51eaSDavid van Moolenbroek 	p->setmintocopy_op = sf_setmintocopy;
344*d56f51eaSDavid van Moolenbroek #endif
345*d56f51eaSDavid van Moolenbroek 
346*d56f51eaSDavid van Moolenbroek 	/*
347*d56f51eaSDavid van Moolenbroek 	 * For offline captures, the standard one-shot callback can
348*d56f51eaSDavid van Moolenbroek 	 * be used for pcap_next()/pcap_next_ex().
349*d56f51eaSDavid van Moolenbroek 	 */
350*d56f51eaSDavid van Moolenbroek 	p->oneshot_callback = pcap_oneshot;
351*d56f51eaSDavid van Moolenbroek 
352*d56f51eaSDavid van Moolenbroek 	/*
353*d56f51eaSDavid van Moolenbroek 	 * Savefiles never require special BPF code generation.
354*d56f51eaSDavid van Moolenbroek 	 */
355*d56f51eaSDavid van Moolenbroek 	p->bpf_codegen_flags = 0;
356*d56f51eaSDavid van Moolenbroek 
357*d56f51eaSDavid van Moolenbroek 	p->activated = 1;
358*d56f51eaSDavid van Moolenbroek 
359*d56f51eaSDavid van Moolenbroek 	return (p);
360*d56f51eaSDavid van Moolenbroek }
361*d56f51eaSDavid van Moolenbroek 
362*d56f51eaSDavid van Moolenbroek #ifdef WIN32
363*d56f51eaSDavid van Moolenbroek static
364*d56f51eaSDavid van Moolenbroek #endif
365*d56f51eaSDavid van Moolenbroek pcap_t *
pcap_fopen_offline(FILE * fp,char * errbuf)366*d56f51eaSDavid van Moolenbroek pcap_fopen_offline(FILE *fp, char *errbuf)
367*d56f51eaSDavid van Moolenbroek {
368*d56f51eaSDavid van Moolenbroek 	return (pcap_fopen_offline_with_tstamp_precision(fp,
369*d56f51eaSDavid van Moolenbroek 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf));
370*d56f51eaSDavid van Moolenbroek }
371*d56f51eaSDavid van Moolenbroek 
372*d56f51eaSDavid van Moolenbroek /*
373*d56f51eaSDavid van Moolenbroek  * Read packets from a capture file, and call the callback for each
374*d56f51eaSDavid van Moolenbroek  * packet.
375*d56f51eaSDavid van Moolenbroek  * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
376*d56f51eaSDavid van Moolenbroek  */
377*d56f51eaSDavid van Moolenbroek int
pcap_offline_read(pcap_t * p,int cnt,pcap_handler callback,u_char * user)378*d56f51eaSDavid van Moolenbroek pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
379*d56f51eaSDavid van Moolenbroek {
380*d56f51eaSDavid van Moolenbroek 	struct bpf_insn *fcode;
381*d56f51eaSDavid van Moolenbroek 	int status = 0;
382*d56f51eaSDavid van Moolenbroek 	int n = 0;
383*d56f51eaSDavid van Moolenbroek 	u_char *data;
384*d56f51eaSDavid van Moolenbroek 
385*d56f51eaSDavid van Moolenbroek 	while (status == 0) {
386*d56f51eaSDavid van Moolenbroek 		struct pcap_pkthdr h;
387*d56f51eaSDavid van Moolenbroek 
388*d56f51eaSDavid van Moolenbroek 		/*
389*d56f51eaSDavid van Moolenbroek 		 * Has "pcap_breakloop()" been called?
390*d56f51eaSDavid van Moolenbroek 		 * If so, return immediately - if we haven't read any
391*d56f51eaSDavid van Moolenbroek 		 * packets, clear the flag and return -2 to indicate
392*d56f51eaSDavid van Moolenbroek 		 * that we were told to break out of the loop, otherwise
393*d56f51eaSDavid van Moolenbroek 		 * leave the flag set, so that the *next* call will break
394*d56f51eaSDavid van Moolenbroek 		 * out of the loop without having read any packets, and
395*d56f51eaSDavid van Moolenbroek 		 * return the number of packets we've processed so far.
396*d56f51eaSDavid van Moolenbroek 		 */
397*d56f51eaSDavid van Moolenbroek 		if (p->break_loop) {
398*d56f51eaSDavid van Moolenbroek 			if (n == 0) {
399*d56f51eaSDavid van Moolenbroek 				p->break_loop = 0;
400*d56f51eaSDavid van Moolenbroek 				return (-2);
401*d56f51eaSDavid van Moolenbroek 			} else
402*d56f51eaSDavid van Moolenbroek 				return (n);
403*d56f51eaSDavid van Moolenbroek 		}
404*d56f51eaSDavid van Moolenbroek 
405*d56f51eaSDavid van Moolenbroek 		status = p->next_packet_op(p, &h, &data);
406*d56f51eaSDavid van Moolenbroek 		if (status) {
407*d56f51eaSDavid van Moolenbroek 			if (status == 1)
408*d56f51eaSDavid van Moolenbroek 				return (0);
409*d56f51eaSDavid van Moolenbroek 			return (status);
410*d56f51eaSDavid van Moolenbroek 		}
411*d56f51eaSDavid van Moolenbroek 
412*d56f51eaSDavid van Moolenbroek 		if ((fcode = p->fcode.bf_insns) == NULL ||
413*d56f51eaSDavid van Moolenbroek 		    bpf_filter(fcode, data, h.len, h.caplen)) {
414*d56f51eaSDavid van Moolenbroek 			(*callback)(user, &h, data);
415*d56f51eaSDavid van Moolenbroek 			if (++n >= cnt && cnt > 0)
416*d56f51eaSDavid van Moolenbroek 				break;
417*d56f51eaSDavid van Moolenbroek 		}
418*d56f51eaSDavid van Moolenbroek 	}
419*d56f51eaSDavid van Moolenbroek 	/*XXX this breaks semantics tcpslice expects */
420*d56f51eaSDavid van Moolenbroek 	return (n);
421*d56f51eaSDavid van Moolenbroek }
422