xref: /freebsd/contrib/libpcap/savefile.c (revision d1e8733132ce92d068898e4b3fe25ce17d634590)
18cf6c252SPaul Traina /*
2a4b5b39fSBill Fenner  * Copyright (c) 1993, 1994, 1995, 1996, 1997
38cf6c252SPaul Traina  *	The Regents of the University of California.  All rights reserved.
48cf6c252SPaul Traina  *
58cf6c252SPaul Traina  * Redistribution and use in source and binary forms, with or without
68cf6c252SPaul Traina  * modification, are permitted provided that: (1) source code distributions
78cf6c252SPaul Traina  * retain the above copyright notice and this paragraph in its entirety, (2)
88cf6c252SPaul Traina  * distributions including binary code include the above copyright notice and
98cf6c252SPaul Traina  * this paragraph in its entirety in the documentation or other materials
108cf6c252SPaul Traina  * provided with the distribution, and (3) all advertising materials mentioning
118cf6c252SPaul Traina  * features or use of this software display the following acknowledgement:
128cf6c252SPaul Traina  * ``This product includes software developed by the University of California,
138cf6c252SPaul Traina  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
148cf6c252SPaul Traina  * the University nor the names of its contributors may be used to endorse
158cf6c252SPaul Traina  * or promote products derived from this software without specific prior
168cf6c252SPaul Traina  * written permission.
178cf6c252SPaul Traina  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
188cf6c252SPaul Traina  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
198cf6c252SPaul Traina  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
203052b236SBill Fenner  *
218cf6c252SPaul Traina  * savefile.c - supports offline use of tcpdump
228cf6c252SPaul Traina  *	Extraction/creation by Jeffrey Mogul, DECWRL
238cf6c252SPaul Traina  *	Modified by Steve McCanne, LBL.
248cf6c252SPaul Traina  *
258cf6c252SPaul Traina  * Used to save the received packet headers, after filtering, to
268cf6c252SPaul Traina  * a file, and then read them later.
278cf6c252SPaul Traina  * The first record in the file contains saved values for the machine
288cf6c252SPaul Traina  * dependent values so we can print the dump file on any architecture.
298cf6c252SPaul Traina  */
308cf6c252SPaul Traina 
313052b236SBill Fenner #ifndef lint
32feb4ecdbSBruce M Simpson static const char rcsid[] _U_ =
33a0ee43a1SRui Paulo     "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.183 2008-12-23 20:13:29 guy Exp $ (LBL)";
34dc2c7305SBill Fenner #endif
35dc2c7305SBill Fenner 
36dc2c7305SBill Fenner #ifdef HAVE_CONFIG_H
37dc2c7305SBill Fenner #include "config.h"
383052b236SBill Fenner #endif
393052b236SBill Fenner 
40a0ee43a1SRui Paulo #ifdef WIN32
41a0ee43a1SRui Paulo #include <pcap-stdinc.h>
42a0ee43a1SRui Paulo #else /* WIN32 */
43a0ee43a1SRui Paulo #if HAVE_INTTYPES_H
44a0ee43a1SRui Paulo #include <inttypes.h>
45a0ee43a1SRui Paulo #elif HAVE_STDINT_H
46a0ee43a1SRui Paulo #include <stdint.h>
47a0ee43a1SRui Paulo #endif
48a0ee43a1SRui Paulo #ifdef HAVE_SYS_BITYPES_H
49a0ee43a1SRui Paulo #include <sys/bitypes.h>
50a0ee43a1SRui Paulo #endif
51a0ee43a1SRui Paulo #include <sys/types.h>
52a0ee43a1SRui Paulo #endif /* WIN32 */
53a0ee43a1SRui Paulo 
548cf6c252SPaul Traina #include <errno.h>
558cf6c252SPaul Traina #include <memory.h>
568cf6c252SPaul Traina #include <stdio.h>
578cf6c252SPaul Traina #include <stdlib.h>
58dc2c7305SBill Fenner #include <string.h>
598cf6c252SPaul Traina 
608cf6c252SPaul Traina #include "pcap-int.h"
61a8e07101SRui Paulo #include "pcap/usb.h"
628cf6c252SPaul Traina 
638cf6c252SPaul Traina #ifdef HAVE_OS_PROTO_H
648cf6c252SPaul Traina #include "os-proto.h"
658cf6c252SPaul Traina #endif
668cf6c252SPaul Traina 
67a0ee43a1SRui Paulo #include "sf-pcap.h"
68a0ee43a1SRui Paulo #include "sf-pcap-ng.h"
698cf6c252SPaul Traina 
70dc2c7305SBill Fenner /*
7104fb2745SSam Leffler  * Setting O_BINARY on DOS/Windows is a bit tricky
7204fb2745SSam Leffler  */
7304fb2745SSam Leffler #if defined(WIN32)
74ee2dd488SSam Leffler   #define SET_BINMODE(f)  _setmode(_fileno(f), _O_BINARY)
7504fb2745SSam Leffler #elif defined(MSDOS)
7604fb2745SSam Leffler   #if defined(__HIGHC__)
7704fb2745SSam Leffler   #define SET_BINMODE(f)  setmode(f, O_BINARY)
7804fb2745SSam Leffler   #else
7904fb2745SSam Leffler   #define SET_BINMODE(f)  setmode(fileno(f), O_BINARY)
8004fb2745SSam Leffler   #endif
8104fb2745SSam Leffler #endif
8204fb2745SSam Leffler 
83feb4ecdbSBruce M Simpson static int
84feb4ecdbSBruce M Simpson sf_getnonblock(pcap_t *p, char *errbuf)
85feb4ecdbSBruce M Simpson {
86feb4ecdbSBruce M Simpson 	/*
87feb4ecdbSBruce M Simpson 	 * This is a savefile, not a live capture file, so never say
88feb4ecdbSBruce M Simpson 	 * it's in non-blocking mode.
89feb4ecdbSBruce M Simpson 	 */
90feb4ecdbSBruce M Simpson 	return (0);
91feb4ecdbSBruce M Simpson }
92feb4ecdbSBruce M Simpson 
93feb4ecdbSBruce M Simpson static int
94feb4ecdbSBruce M Simpson sf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
95feb4ecdbSBruce M Simpson {
96feb4ecdbSBruce M Simpson 	/*
97*d1e87331SXin LI 	 * This is a savefile, not a live capture file, so reject
98*d1e87331SXin LI 	 * requests to put it in non-blocking mode.  (If it's a
99*d1e87331SXin LI 	 * pipe, it could be put in non-blocking mode, but that
100*d1e87331SXin LI 	 * would significantly complicate the code to read packets,
101*d1e87331SXin LI 	 * as it would have to handle reading partial packets and
102*d1e87331SXin LI 	 * keeping the state of the read.)
103feb4ecdbSBruce M Simpson 	 */
104*d1e87331SXin LI 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
105*d1e87331SXin LI 	    "Savefiles cannot be put into non-blocking mode");
106*d1e87331SXin LI 	return (-1);
107feb4ecdbSBruce M Simpson }
108feb4ecdbSBruce M Simpson 
109feb4ecdbSBruce M Simpson static int
110feb4ecdbSBruce M Simpson sf_stats(pcap_t *p, struct pcap_stat *ps)
111feb4ecdbSBruce M Simpson {
112feb4ecdbSBruce M Simpson 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
113feb4ecdbSBruce M Simpson 	    "Statistics aren't available from savefiles");
114feb4ecdbSBruce M Simpson 	return (-1);
115feb4ecdbSBruce M Simpson }
116feb4ecdbSBruce M Simpson 
117a8e07101SRui Paulo #ifdef WIN32
118a8e07101SRui Paulo static int
119a8e07101SRui Paulo sf_setbuff(pcap_t *p, int dim)
120a8e07101SRui Paulo {
121a8e07101SRui Paulo 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
122a8e07101SRui Paulo 	    "The kernel buffer size cannot be set while reading from a file");
123a8e07101SRui Paulo 	return (-1);
124a8e07101SRui Paulo }
125a8e07101SRui Paulo 
126a8e07101SRui Paulo static int
127a8e07101SRui Paulo sf_setmode(pcap_t *p, int mode)
128a8e07101SRui Paulo {
129a8e07101SRui Paulo 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
130a8e07101SRui Paulo 	    "impossible to set mode while reading from a file");
131a8e07101SRui Paulo 	return (-1);
132a8e07101SRui Paulo }
133a8e07101SRui Paulo 
134a8e07101SRui Paulo static int
135a8e07101SRui Paulo sf_setmintocopy(pcap_t *p, int size)
136a8e07101SRui Paulo {
137a8e07101SRui Paulo 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
138a8e07101SRui Paulo 	    "The mintocopy parameter cannot be set while reading from a file");
139a8e07101SRui Paulo 	return (-1);
140a8e07101SRui Paulo }
141a8e07101SRui Paulo #endif
142a8e07101SRui Paulo 
14304fb2745SSam Leffler static int
14404fb2745SSam Leffler sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
14504fb2745SSam Leffler {
14604fb2745SSam Leffler 	strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
14704fb2745SSam Leffler 	    PCAP_ERRBUF_SIZE);
14804fb2745SSam Leffler 	return (-1);
14904fb2745SSam Leffler }
15004fb2745SSam Leffler 
151ee2dd488SSam Leffler /*
152ee2dd488SSam Leffler  * Set direction flag: Which packets do we accept on a forwarding
153ee2dd488SSam Leffler  * single device? IN, OUT or both?
154ee2dd488SSam Leffler  */
155ee2dd488SSam Leffler static int
1565d18909fSSam Leffler sf_setdirection(pcap_t *p, pcap_direction_t d)
157ee2dd488SSam Leffler {
158ee2dd488SSam Leffler 	snprintf(p->errbuf, sizeof(p->errbuf),
159ee2dd488SSam Leffler 	    "Setting direction is not supported on savefiles");
160ee2dd488SSam Leffler 	return (-1);
161ee2dd488SSam Leffler }
162ee2dd488SSam Leffler 
163feb4ecdbSBruce M Simpson static void
164a8e07101SRui Paulo sf_cleanup(pcap_t *p)
165feb4ecdbSBruce M Simpson {
166feb4ecdbSBruce M Simpson 	if (p->sf.rfile != stdin)
167feb4ecdbSBruce M Simpson 		(void)fclose(p->sf.rfile);
168a0ee43a1SRui Paulo 	if (p->buffer != NULL)
169a0ee43a1SRui Paulo 		free(p->buffer);
170*d1e87331SXin LI 	pcap_freecode(&p->fcode);
171feb4ecdbSBruce M Simpson }
172feb4ecdbSBruce M Simpson 
1738cf6c252SPaul Traina pcap_t *
174a4b5b39fSBill Fenner pcap_open_offline(const char *fname, char *errbuf)
1758cf6c252SPaul Traina {
17604fb2745SSam Leffler 	FILE *fp;
17704fb2745SSam Leffler 	pcap_t *p;
17804fb2745SSam Leffler 
17904fb2745SSam Leffler 	if (fname[0] == '-' && fname[1] == '\0')
180ee2dd488SSam Leffler 	{
18104fb2745SSam Leffler 		fp = stdin;
182ee2dd488SSam Leffler #if defined(WIN32) || defined(MSDOS)
183ee2dd488SSam Leffler 		/*
184ee2dd488SSam Leffler 		 * We're reading from the standard input, so put it in binary
185ee2dd488SSam Leffler 		 * mode, as savefiles are binary files.
186ee2dd488SSam Leffler 		 */
187ee2dd488SSam Leffler 		SET_BINMODE(fp);
188ee2dd488SSam Leffler #endif
189ee2dd488SSam Leffler 	}
19004fb2745SSam Leffler 	else {
19104fb2745SSam Leffler #if !defined(WIN32) && !defined(MSDOS)
19204fb2745SSam Leffler 		fp = fopen(fname, "r");
19304fb2745SSam Leffler #else
19404fb2745SSam Leffler 		fp = fopen(fname, "rb");
19504fb2745SSam Leffler #endif
19604fb2745SSam Leffler 		if (fp == NULL) {
19704fb2745SSam Leffler 			snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
19804fb2745SSam Leffler 			    pcap_strerror(errno));
19904fb2745SSam Leffler 			return (NULL);
20004fb2745SSam Leffler 		}
20104fb2745SSam Leffler 	}
20204fb2745SSam Leffler 	p = pcap_fopen_offline(fp, errbuf);
20304fb2745SSam Leffler 	if (p == NULL) {
20404fb2745SSam Leffler 		if (fp != stdin)
20504fb2745SSam Leffler 			fclose(fp);
20604fb2745SSam Leffler 	}
20704fb2745SSam Leffler 	return (p);
20804fb2745SSam Leffler }
20904fb2745SSam Leffler 
210a8e07101SRui Paulo #ifdef WIN32
211a8e07101SRui Paulo pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
212a8e07101SRui Paulo {
213a8e07101SRui Paulo 	int fd;
214a8e07101SRui Paulo 	FILE *file;
215a8e07101SRui Paulo 
216a8e07101SRui Paulo 	fd = _open_osfhandle(osfd, _O_RDONLY);
217a8e07101SRui Paulo 	if ( fd < 0 )
218a8e07101SRui Paulo 	{
219a8e07101SRui Paulo 		snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
220a8e07101SRui Paulo 		return NULL;
221a8e07101SRui Paulo 	}
222a8e07101SRui Paulo 
223a8e07101SRui Paulo 	file = _fdopen(fd, "rb");
224a8e07101SRui Paulo 	if ( file == NULL )
225a8e07101SRui Paulo 	{
226a8e07101SRui Paulo 		snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
227a8e07101SRui Paulo 		return NULL;
228a8e07101SRui Paulo 	}
229a8e07101SRui Paulo 
230a8e07101SRui Paulo 	return pcap_fopen_offline(file, errbuf);
231a8e07101SRui Paulo }
232a8e07101SRui Paulo #endif
233a8e07101SRui Paulo 
234a0ee43a1SRui Paulo static int (*check_headers[])(pcap_t *, bpf_u_int32, FILE *, char *) = {
235a0ee43a1SRui Paulo 	pcap_check_header,
236a0ee43a1SRui Paulo 	pcap_ng_check_header
237a0ee43a1SRui Paulo };
238a0ee43a1SRui Paulo 
239a0ee43a1SRui Paulo #define	N_FILE_TYPES	(sizeof check_headers / sizeof check_headers[0])
240a0ee43a1SRui Paulo 
241a8e07101SRui Paulo #ifdef WIN32
242a8e07101SRui Paulo static
243a8e07101SRui Paulo #endif
24404fb2745SSam Leffler pcap_t *
24504fb2745SSam Leffler pcap_fopen_offline(FILE *fp, char *errbuf)
24604fb2745SSam Leffler {
2478cf6c252SPaul Traina 	register pcap_t *p;
248dc2c7305SBill Fenner 	bpf_u_int32 magic;
249a0ee43a1SRui Paulo 	size_t amt_read;
250a0ee43a1SRui Paulo 	u_int i;
2518cf6c252SPaul Traina 
252a0ee43a1SRui Paulo 	p = pcap_create_common("(savefile)", errbuf);
253a0ee43a1SRui Paulo 	if (p == NULL)
2548cf6c252SPaul Traina 		return (NULL);
2558cf6c252SPaul Traina 
256a0ee43a1SRui Paulo 	/*
257a0ee43a1SRui Paulo 	 * Read the first 4 bytes of the file; the network analyzer dump
258a0ee43a1SRui Paulo 	 * file formats we support (pcap and pcap-ng), and several other
259a0ee43a1SRui Paulo 	 * formats we might support in the future (such as snoop, DOS and
260a0ee43a1SRui Paulo 	 * Windows Sniffer, and Microsoft Network Monitor) all have magic
261a0ee43a1SRui Paulo 	 * numbers that are unique in their first 4 bytes.
262a0ee43a1SRui Paulo 	 */
263a0ee43a1SRui Paulo 	amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
264a0ee43a1SRui Paulo 	if (amt_read != sizeof(magic)) {
26504fb2745SSam Leffler 		if (ferror(fp)) {
26604fb2745SSam Leffler 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
26704fb2745SSam Leffler 			    "error reading dump file: %s",
268dc2c7305SBill Fenner 			    pcap_strerror(errno));
26904fb2745SSam Leffler 		} else {
27004fb2745SSam Leffler 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
27104fb2745SSam Leffler 			    "truncated dump file; tried to read %lu file header bytes, only got %lu",
272a0ee43a1SRui Paulo 			    (unsigned long)sizeof(magic),
27304fb2745SSam Leffler 			    (unsigned long)amt_read);
2748cf6c252SPaul Traina 		}
2758cf6c252SPaul Traina 		goto bad;
2768cf6c252SPaul Traina 	}
277a0ee43a1SRui Paulo 
278dc2c7305SBill Fenner 	/*
279a0ee43a1SRui Paulo 	 * Try all file types.
280dc2c7305SBill Fenner 	 */
281a0ee43a1SRui Paulo 	for (i = 0; i < N_FILE_TYPES; i++) {
282a0ee43a1SRui Paulo 		switch ((*check_headers[i])(p, magic, fp, errbuf)) {
283a0ee43a1SRui Paulo 
284a0ee43a1SRui Paulo 		case -1:
285ef96d74fSMax Laier 			/*
286a0ee43a1SRui Paulo 			 * Error trying to read the header.
287ef96d74fSMax Laier 			 */
288a0ee43a1SRui Paulo 			goto bad;
289a0ee43a1SRui Paulo 
290a0ee43a1SRui Paulo 		case 1:
291a0ee43a1SRui Paulo 			/*
292a0ee43a1SRui Paulo 			 * Yup, that's it.
293a0ee43a1SRui Paulo 			 */
294a0ee43a1SRui Paulo 			goto found;
295ef96d74fSMax Laier 		}
296a0ee43a1SRui Paulo 	}
297a0ee43a1SRui Paulo 
298a0ee43a1SRui Paulo 	/*
299a0ee43a1SRui Paulo 	 * Well, who knows what this mess is....
300a0ee43a1SRui Paulo 	 */
301a0ee43a1SRui Paulo 	snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
302a0ee43a1SRui Paulo 	goto bad;
303a0ee43a1SRui Paulo 
304a0ee43a1SRui Paulo found:
3058cf6c252SPaul Traina 	p->sf.rfile = fp;
3068cf6c252SPaul Traina 
3078cf6c252SPaul Traina #ifdef PCAP_FDDIPAD
30804fb2745SSam Leffler 	/* Padding only needed for live capture fcode */
30904fb2745SSam Leffler 	p->fddipad = 0;
3108cf6c252SPaul Traina #endif
3118cf6c252SPaul Traina 
31204fb2745SSam Leffler #if !defined(WIN32) && !defined(MSDOS)
313feb4ecdbSBruce M Simpson 	/*
314feb4ecdbSBruce M Simpson 	 * You can do "select()" and "poll()" on plain files on most
315feb4ecdbSBruce M Simpson 	 * platforms, and should be able to do so on pipes.
316feb4ecdbSBruce M Simpson 	 *
317feb4ecdbSBruce M Simpson 	 * You can't do "select()" on anything other than sockets in
318feb4ecdbSBruce M Simpson 	 * Windows, so, on Win32 systems, we don't have "selectable_fd".
319feb4ecdbSBruce M Simpson 	 */
320feb4ecdbSBruce M Simpson 	p->selectable_fd = fileno(fp);
321feb4ecdbSBruce M Simpson #endif
322feb4ecdbSBruce M Simpson 
323feb4ecdbSBruce M Simpson 	p->read_op = pcap_offline_read;
32404fb2745SSam Leffler 	p->inject_op = sf_inject;
325feb4ecdbSBruce M Simpson 	p->setfilter_op = install_bpf_program;
326ee2dd488SSam Leffler 	p->setdirection_op = sf_setdirection;
327feb4ecdbSBruce M Simpson 	p->set_datalink_op = NULL;	/* we don't support munging link-layer headers */
328feb4ecdbSBruce M Simpson 	p->getnonblock_op = sf_getnonblock;
329feb4ecdbSBruce M Simpson 	p->setnonblock_op = sf_setnonblock;
330feb4ecdbSBruce M Simpson 	p->stats_op = sf_stats;
331a8e07101SRui Paulo #ifdef WIN32
332a8e07101SRui Paulo 	p->setbuff_op = sf_setbuff;
333a8e07101SRui Paulo 	p->setmode_op = sf_setmode;
334a8e07101SRui Paulo 	p->setmintocopy_op = sf_setmintocopy;
335a8e07101SRui Paulo #endif
336a8e07101SRui Paulo 	p->cleanup_op = sf_cleanup;
337a8e07101SRui Paulo 	p->activated = 1;
338feb4ecdbSBruce M Simpson 
3398cf6c252SPaul Traina 	return (p);
3408cf6c252SPaul Traina  bad:
3418cf6c252SPaul Traina 	free(p);
3428cf6c252SPaul Traina 	return (NULL);
3438cf6c252SPaul Traina }
3448cf6c252SPaul Traina 
3458cf6c252SPaul Traina /*
346a0ee43a1SRui Paulo  * Read packets from a capture file, and call the callback for each
347a0ee43a1SRui Paulo  * packet.
3488cf6c252SPaul Traina  * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
3498cf6c252SPaul Traina  */
3508cf6c252SPaul Traina int
3518cf6c252SPaul Traina pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
3528cf6c252SPaul Traina {
35304fb2745SSam Leffler 	struct bpf_insn *fcode;
3548cf6c252SPaul Traina 	int status = 0;
3558cf6c252SPaul Traina 	int n = 0;
356a0ee43a1SRui Paulo 	u_char *data;
3578cf6c252SPaul Traina 
3588cf6c252SPaul Traina 	while (status == 0) {
3598cf6c252SPaul Traina 		struct pcap_pkthdr h;
3608cf6c252SPaul Traina 
361feb4ecdbSBruce M Simpson 		/*
362feb4ecdbSBruce M Simpson 		 * Has "pcap_breakloop()" been called?
363feb4ecdbSBruce M Simpson 		 * If so, return immediately - if we haven't read any
364feb4ecdbSBruce M Simpson 		 * packets, clear the flag and return -2 to indicate
365feb4ecdbSBruce M Simpson 		 * that we were told to break out of the loop, otherwise
366feb4ecdbSBruce M Simpson 		 * leave the flag set, so that the *next* call will break
367feb4ecdbSBruce M Simpson 		 * out of the loop without having read any packets, and
368feb4ecdbSBruce M Simpson 		 * return the number of packets we've processed so far.
369feb4ecdbSBruce M Simpson 		 */
370feb4ecdbSBruce M Simpson 		if (p->break_loop) {
371feb4ecdbSBruce M Simpson 			if (n == 0) {
372feb4ecdbSBruce M Simpson 				p->break_loop = 0;
373feb4ecdbSBruce M Simpson 				return (-2);
374feb4ecdbSBruce M Simpson 			} else
375feb4ecdbSBruce M Simpson 				return (n);
376feb4ecdbSBruce M Simpson 		}
377feb4ecdbSBruce M Simpson 
378a0ee43a1SRui Paulo 		status = p->sf.next_packet_op(p, &h, &data);
3798cf6c252SPaul Traina 		if (status) {
3808cf6c252SPaul Traina 			if (status == 1)
3818cf6c252SPaul Traina 				return (0);
3828cf6c252SPaul Traina 			return (status);
3838cf6c252SPaul Traina 		}
3848cf6c252SPaul Traina 
38504fb2745SSam Leffler 		if ((fcode = p->fcode.bf_insns) == NULL ||
386*d1e87331SXin LI 		    bpf_filter(fcode, data, h.len, h.caplen)) {
387a0ee43a1SRui Paulo 			(*callback)(user, &h, data);
3888cf6c252SPaul Traina 			if (++n >= cnt && cnt > 0)
3898cf6c252SPaul Traina 				break;
3908cf6c252SPaul Traina 		}
3918cf6c252SPaul Traina 	}
3928cf6c252SPaul Traina 	/*XXX this breaks semantics tcpslice expects */
3938cf6c252SPaul Traina 	return (n);
3948cf6c252SPaul Traina }
395