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