• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * savefile.c - supports offline use of tcpdump
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 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34 
35 #include <pcap-types.h>
36 #ifdef _WIN32
37 #include <io.h>
38 #include <fcntl.h>
39 #endif /* _WIN32 */
40 
41 #include <errno.h>
42 #include <memory.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <limits.h> /* for INT_MAX */
47 
48 #include "pcap-int.h"
49 
50 #ifdef HAVE_OS_PROTO_H
51 #include "os-proto.h"
52 #endif
53 
54 #include "sf-pcap.h"
55 #include "sf-pcapng.h"
56 #include "pcap-common.h"
57 #include "charconv.h"
58 
59 #ifdef _WIN32
60 /*
61  * This isn't exported on Windows, because it would only work if both
62  * WinPcap/Npcap and the code using it were to use the Universal CRT; otherwise,
63  * a FILE structure in WinPcap/Npcap and a FILE structure in the code using it
64  * could be different if they're using different versions of the C runtime.
65  *
66  * Instead, pcap/pcap.h defines it as a macro that wraps the hopen version,
67  * with the wrapper calling _fileno() and _get_osfhandle() themselves,
68  * so that it convert the appropriate CRT version's FILE structure to
69  * a HANDLE (which is OS-defined, not CRT-defined, and is part of the Win32
70  * and Win64 ABIs).
71  */
72 static pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
73 #endif
74 
75 /*
76  * Setting O_BINARY on DOS/Windows is a bit tricky
77  */
78 #if defined(_WIN32)
79   #define SET_BINMODE(f)  _setmode(_fileno(f), _O_BINARY)
80 #elif defined(MSDOS)
81   #if defined(__HIGHC__)
82   #define SET_BINMODE(f)  setmode(f, O_BINARY)
83   #else
84   #define SET_BINMODE(f)  setmode(fileno(f), O_BINARY)
85   #endif
86 #endif
87 
88 static int
sf_getnonblock(pcap_t * p _U_)89 sf_getnonblock(pcap_t *p _U_)
90 {
91 	/*
92 	 * This is a savefile, not a live capture file, so never say
93 	 * it's in non-blocking mode.
94 	 */
95 	return (0);
96 }
97 
98 static int
sf_setnonblock(pcap_t * p,int nonblock _U_)99 sf_setnonblock(pcap_t *p, int nonblock _U_)
100 {
101 	/*
102 	 * This is a savefile, not a live capture file, so reject
103 	 * requests to put it in non-blocking mode.  (If it's a
104 	 * pipe, it could be put in non-blocking mode, but that
105 	 * would significantly complicate the code to read packets,
106 	 * as it would have to handle reading partial packets and
107 	 * keeping the state of the read.)
108 	 */
109 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
110 	    "Savefiles cannot be put into non-blocking mode");
111 	return (-1);
112 }
113 
114 static int
sf_stats(pcap_t * p,struct pcap_stat * ps _U_)115 sf_stats(pcap_t *p, struct pcap_stat *ps _U_)
116 {
117 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
118 	    "Statistics aren't available from savefiles");
119 	return (-1);
120 }
121 
122 #ifdef _WIN32
123 static struct pcap_stat *
sf_stats_ex(pcap_t * p,int * size _U_)124 sf_stats_ex(pcap_t *p, int *size _U_)
125 {
126 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
127 	    "Statistics aren't available from savefiles");
128 	return (NULL);
129 }
130 
131 static int
sf_setbuff(pcap_t * p,int dim _U_)132 sf_setbuff(pcap_t *p, int dim _U_)
133 {
134 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
135 	    "The kernel buffer size cannot be set while reading from a file");
136 	return (-1);
137 }
138 
139 static int
sf_setmode(pcap_t * p,int mode _U_)140 sf_setmode(pcap_t *p, int mode _U_)
141 {
142 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
143 	    "impossible to set mode while reading from a file");
144 	return (-1);
145 }
146 
147 static int
sf_setmintocopy(pcap_t * p,int size _U_)148 sf_setmintocopy(pcap_t *p, int size _U_)
149 {
150 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
151 	    "The mintocopy parameter cannot be set while reading from a file");
152 	return (-1);
153 }
154 
155 static HANDLE
sf_getevent(pcap_t * pcap)156 sf_getevent(pcap_t *pcap)
157 {
158 	(void)snprintf(pcap->errbuf, sizeof(pcap->errbuf),
159 	    "The read event cannot be retrieved while reading from a file");
160 	return (INVALID_HANDLE_VALUE);
161 }
162 
163 static int
sf_oid_get_request(pcap_t * p,bpf_u_int32 oid _U_,void * data _U_,size_t * lenp _U_)164 sf_oid_get_request(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_,
165     size_t *lenp _U_)
166 {
167 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
168 	    "An OID get request cannot be performed on a file");
169 	return (PCAP_ERROR);
170 }
171 
172 static int
sf_oid_set_request(pcap_t * p,bpf_u_int32 oid _U_,const void * data _U_,size_t * lenp _U_)173 sf_oid_set_request(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
174     size_t *lenp _U_)
175 {
176 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
177 	    "An OID set request cannot be performed on a file");
178 	return (PCAP_ERROR);
179 }
180 
181 static u_int
sf_sendqueue_transmit(pcap_t * p,pcap_send_queue * queue _U_,int sync _U_)182 sf_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue _U_, int sync _U_)
183 {
184 	pcap_strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
185 	    PCAP_ERRBUF_SIZE);
186 	return (0);
187 }
188 
189 static int
sf_setuserbuffer(pcap_t * p,int size _U_)190 sf_setuserbuffer(pcap_t *p, int size _U_)
191 {
192 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
193 	    "The user buffer cannot be set when reading from a file");
194 	return (-1);
195 }
196 
197 static int
sf_live_dump(pcap_t * p,char * filename _U_,int maxsize _U_,int maxpacks _U_)198 sf_live_dump(pcap_t *p, char *filename _U_, int maxsize _U_, int maxpacks _U_)
199 {
200 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
201 	    "Live packet dumping cannot be performed when reading from a file");
202 	return (-1);
203 }
204 
205 static int
sf_live_dump_ended(pcap_t * p,int sync _U_)206 sf_live_dump_ended(pcap_t *p, int sync _U_)
207 {
208 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
209 	    "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
210 	return (-1);
211 }
212 
213 static PAirpcapHandle
sf_get_airpcap_handle(pcap_t * pcap _U_)214 sf_get_airpcap_handle(pcap_t *pcap _U_)
215 {
216 	return (NULL);
217 }
218 #endif
219 
220 static int
sf_inject(pcap_t * p,const void * buf _U_,int size _U_)221 sf_inject(pcap_t *p, const void *buf _U_, int size _U_)
222 {
223 	pcap_strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
224 	    PCAP_ERRBUF_SIZE);
225 	return (-1);
226 }
227 
228 /*
229  * Set direction flag: Which packets do we accept on a forwarding
230  * single device? IN, OUT or both?
231  */
232 static int
sf_setdirection(pcap_t * p,pcap_direction_t d _U_)233 sf_setdirection(pcap_t *p, pcap_direction_t d _U_)
234 {
235 	snprintf(p->errbuf, sizeof(p->errbuf),
236 	    "Setting direction is not supported on savefiles");
237 	return (-1);
238 }
239 
240 void
sf_cleanup(pcap_t * p)241 sf_cleanup(pcap_t *p)
242 {
243 	if (p->rfile != stdin)
244 		(void)fclose(p->rfile);
245 	if (p->buffer != NULL)
246 		free(p->buffer);
247 	pcap_freecode(&p->fcode);
248 }
249 
250 #ifdef _WIN32
251 /*
252  * Wrapper for fopen() and _wfopen().
253  *
254  * If we're in UTF-8 mode, map the pathname from UTF-8 to UTF-16LE and
255  * call _wfopen().
256  *
257  * If we're not, just use fopen(); that'll treat it as being in the
258  * local code page.
259  */
260 FILE *
charset_fopen(const char * path,const char * mode)261 charset_fopen(const char *path, const char *mode)
262 {
263 	wchar_t *utf16_path;
264 #define MAX_MODE_LEN	16
265 	wchar_t utf16_mode[MAX_MODE_LEN+1];
266 	int i;
267 	char c;
268 	FILE *fp;
269 	int save_errno;
270 
271 	if (pcap_utf_8_mode) {
272 		/*
273 		 * Map from UTF-8 to UTF-16LE.
274 		 * Fail if there are invalid characters in the input
275 		 * string, rather than converting them to REPLACEMENT
276 		 * CHARACTER; the latter is appropriate for strings
277 		 * to be displayed to the user, but for file names
278 		 * you just want the attempt to open the file to fail.
279 		 */
280 		utf16_path = cp_to_utf_16le(CP_UTF8, path,
281 		    MB_ERR_INVALID_CHARS);
282 		if (utf16_path == NULL) {
283 			/*
284 			 * Error.  Assume errno has been set.
285 			 *
286 			 * XXX - what about Windows errors?
287 			 */
288 			return (NULL);
289 		}
290 
291 		/*
292 		 * Now convert the mode to UTF-16LE as well.
293 		 * We assume the mode is ASCII, and that
294 		 * it's short, so that's easy.
295 		 */
296 		for (i = 0; (c = *mode) != '\0'; i++, mode++) {
297 			if (c > 0x7F) {
298 				/* Not an ASCII character; fail with EINVAL. */
299 				free(utf16_path);
300 				errno = EINVAL;
301 				return (NULL);
302 			}
303 			if (i >= MAX_MODE_LEN) {
304 				/* The mode string is longer than we allow. */
305 				free(utf16_path);
306 				errno = EINVAL;
307 				return (NULL);
308 			}
309 			utf16_mode[i] = c;
310 		}
311 		utf16_mode[i] = '\0';
312 
313 		/*
314 		 * OK, we have UTF-16LE strings; hand them to
315 		 * _wfopen().
316 		 */
317 		fp = _wfopen(utf16_path, utf16_mode);
318 
319 		/*
320 		 * Make sure freeing the UTF-16LE string doesn't
321 		 * overwrite the error code we got from _wfopen().
322 		 */
323 		save_errno = errno;
324 		free(utf16_path);
325 		errno = save_errno;
326 
327 		return (fp);
328 	} else {
329 		/*
330 		 * This takes strings in the local code page as an
331 		 * argument.
332 		 */
333 		return (fopen(path, mode));
334 	}
335 }
336 #endif
337 
338 pcap_t *
pcap_open_offline_with_tstamp_precision(const char * fname,u_int precision,char * errbuf)339 pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
340 					char *errbuf)
341 {
342 	FILE *fp;
343 	pcap_t *p;
344 
345 	if (fname == NULL) {
346 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
347 		    "A null pointer was supplied as the file name");
348 		return (NULL);
349 	}
350 	if (fname[0] == '-' && fname[1] == '\0')
351 	{
352 		fp = stdin;
353 		if (stdin == NULL) {
354 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
355 			    "The standard input is not open");
356 			return (NULL);
357 		}
358 #if defined(_WIN32) || defined(MSDOS)
359 		/*
360 		 * We're reading from the standard input, so put it in binary
361 		 * mode, as savefiles are binary files.
362 		 */
363 		SET_BINMODE(fp);
364 #endif
365 	}
366 	else {
367 		/*
368 		 * Use charset_fopen(); on Windows, it tests whether we're
369 		 * in "local code page" or "UTF-8" mode, and treats the
370 		 * pathname appropriately, and on other platforms, it just
371 		 * wraps fopen().
372 		 *
373 		 * "b" is supported as of C90, so *all* UN*Xes should
374 		 * support it, even though it does nothing.  For MS-DOS,
375 		 * we again need it.
376 		 */
377 		fp = charset_fopen(fname, "rb");
378 		if (fp == NULL) {
379 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
380 			    errno, "%s", fname);
381 			return (NULL);
382 		}
383 	}
384 	p = pcap_fopen_offline_with_tstamp_precision(fp, precision, errbuf);
385 	if (p == NULL) {
386 		if (fp != stdin)
387 			fclose(fp);
388 	}
389 	return (p);
390 }
391 
392 pcap_t *
pcap_open_offline(const char * fname,char * errbuf)393 pcap_open_offline(const char *fname, char *errbuf)
394 {
395 	return (pcap_open_offline_with_tstamp_precision(fname,
396 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf));
397 }
398 
399 #ifdef _WIN32
pcap_hopen_offline_with_tstamp_precision(intptr_t osfd,u_int precision,char * errbuf)400 pcap_t* pcap_hopen_offline_with_tstamp_precision(intptr_t osfd, u_int precision,
401     char *errbuf)
402 {
403 	int fd;
404 	FILE *file;
405 
406 	fd = _open_osfhandle(osfd, _O_RDONLY);
407 	if ( fd < 0 )
408 	{
409 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
410 		    errno, "_open_osfhandle");
411 		return NULL;
412 	}
413 
414 	file = _fdopen(fd, "rb");
415 	if ( file == NULL )
416 	{
417 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
418 		    errno, "_fdopen");
419 		_close(fd);
420 		return NULL;
421 	}
422 
423 	return pcap_fopen_offline_with_tstamp_precision(file, precision,
424 	    errbuf);
425 }
426 
pcap_hopen_offline(intptr_t osfd,char * errbuf)427 pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
428 {
429 	return pcap_hopen_offline_with_tstamp_precision(osfd,
430 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf);
431 }
432 #endif
433 
434 /*
435  * Given a link-layer header type and snapshot length, return a
436  * snapshot length to use when reading the file; it's guaranteed
437  * to be > 0 and <= INT_MAX.
438  *
439  * XXX - the only reason why we limit it to <= INT_MAX is so that
440  * it fits in p->snapshot, and the only reason that p->snapshot is
441  * signed is that pcap_snapshot() returns an int, not an unsigned int.
442  */
443 bpf_u_int32
pcap_adjust_snapshot(bpf_u_int32 linktype,bpf_u_int32 snaplen)444 pcap_adjust_snapshot(bpf_u_int32 linktype, bpf_u_int32 snaplen)
445 {
446 	if (snaplen == 0 || snaplen > INT_MAX) {
447 		/*
448 		 * Bogus snapshot length; use the maximum for this
449 		 * link-layer type as a fallback.
450 		 *
451 		 * XXX - we don't clamp snapshot lengths that are
452 		 * <= INT_MAX but > max_snaplen_for_dlt(linktype),
453 		 * so a capture file could cause us to allocate
454 		 * a Really Big Buffer.
455 		 */
456 		snaplen = max_snaplen_for_dlt(linktype);
457 	}
458 	return snaplen;
459 }
460 
461 static pcap_t *(*check_headers[])(const uint8_t *, FILE *, u_int, char *, int *) = {
462 	pcap_check_header,
463 	pcap_ng_check_header
464 };
465 
466 #define	N_FILE_TYPES	(sizeof check_headers / sizeof check_headers[0])
467 
468 #ifdef _WIN32
469 static
470 #endif
471 pcap_t *
pcap_fopen_offline_with_tstamp_precision(FILE * fp,u_int precision,char * errbuf)472 pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision,
473     char *errbuf)
474 {
475 	register pcap_t *p;
476 	uint8_t magic[4];
477 	size_t amt_read;
478 	u_int i;
479 	int err;
480 
481 	/*
482 	 * Fail if we were passed a NULL fp.
483 	 *
484 	 * That shouldn't happen if we're opening with a path name, but
485 	 * it could happen if buggy code is opening with a FILE * and
486 	 * didn't bother to make sure the FILE * isn't null.
487 	 */
488 	if (fp == NULL) {
489 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
490 		    "Null FILE * pointer provided to savefile open routine");
491 		return (NULL);
492 	}
493 
494 	/*
495 	 * Read the first 4 bytes of the file; the network analyzer dump
496 	 * file formats we support (pcap and pcapng), and several other
497 	 * formats we might support in the future (such as snoop, DOS and
498 	 * Windows Sniffer, and Microsoft Network Monitor) all have magic
499 	 * numbers that are unique in their first 4 bytes.
500 	 */
501 	amt_read = fread(&magic, 1, sizeof(magic), fp);
502 	if (amt_read != sizeof(magic)) {
503 		if (ferror(fp)) {
504 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
505 			    errno, "error reading dump file");
506 		} else {
507 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
508 			    "truncated dump file; tried to read %zu file header bytes, only got %zu",
509 			    sizeof(magic), amt_read);
510 		}
511 		return (NULL);
512 	}
513 
514 	/*
515 	 * Try all file types.
516 	 */
517 	for (i = 0; i < N_FILE_TYPES; i++) {
518 		p = (*check_headers[i])(magic, fp, precision, errbuf, &err);
519 		if (p != NULL) {
520 			/* Yup, that's it. */
521 			goto found;
522 		}
523 		if (err) {
524 			/*
525 			 * Error trying to read the header.
526 			 */
527 			return (NULL);
528 		}
529 	}
530 
531 	/*
532 	 * Well, who knows what this mess is....
533 	 */
534 	snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
535 	return (NULL);
536 
537 found:
538 	p->rfile = fp;
539 
540 	/* Padding only needed for live capture fcode */
541 	p->fddipad = 0;
542 
543 #if !defined(_WIN32) && !defined(MSDOS)
544 	/*
545 	 * You can do "select()" and "poll()" on plain files on most
546 	 * platforms, and should be able to do so on pipes.
547 	 *
548 	 * You can't do "select()" on anything other than sockets in
549 	 * Windows, so, on Win32 systems, we don't have "selectable_fd".
550 	 */
551 	p->selectable_fd = fileno(fp);
552 #endif
553 
554 	p->read_op = pcap_offline_read;
555 	p->inject_op = sf_inject;
556 	p->setfilter_op = install_bpf_program;
557 	p->setdirection_op = sf_setdirection;
558 	p->set_datalink_op = NULL;	/* we don't support munging link-layer headers */
559 	p->getnonblock_op = sf_getnonblock;
560 	p->setnonblock_op = sf_setnonblock;
561 	p->stats_op = sf_stats;
562 #ifdef _WIN32
563 	p->stats_ex_op = sf_stats_ex;
564 	p->setbuff_op = sf_setbuff;
565 	p->setmode_op = sf_setmode;
566 	p->setmintocopy_op = sf_setmintocopy;
567 	p->getevent_op = sf_getevent;
568 	p->oid_get_request_op = sf_oid_get_request;
569 	p->oid_set_request_op = sf_oid_set_request;
570 	p->sendqueue_transmit_op = sf_sendqueue_transmit;
571 	p->setuserbuffer_op = sf_setuserbuffer;
572 	p->live_dump_op = sf_live_dump;
573 	p->live_dump_ended_op = sf_live_dump_ended;
574 	p->get_airpcap_handle_op = sf_get_airpcap_handle;
575 #endif
576 
577 	/*
578 	 * For offline captures, the standard one-shot callback can
579 	 * be used for pcap_next()/pcap_next_ex().
580 	 */
581 	p->oneshot_callback = pcap_oneshot;
582 
583 	/*
584 	 * Default breakloop operation.
585 	 */
586 	p->breakloop_op = pcap_breakloop_common;
587 
588 	/*
589 	 * Savefiles never require special BPF code generation.
590 	 */
591 	p->bpf_codegen_flags = 0;
592 
593 	p->activated = 1;
594 
595 	return (p);
596 }
597 
598 /*
599  * This isn't needed on Windows; we #define pcap_fopen_offline() as
600  * a wrapper around pcap_hopen_offline(), and we don't call it from
601  * inside this file, so it's unused.
602  */
603 #ifndef _WIN32
604 pcap_t *
pcap_fopen_offline(FILE * fp,char * errbuf)605 pcap_fopen_offline(FILE *fp, char *errbuf)
606 {
607 	return (pcap_fopen_offline_with_tstamp_precision(fp,
608 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf));
609 }
610 #endif
611 
612 /*
613  * Read packets from a capture file, and call the callback for each
614  * packet.
615  * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
616  */
617 int
pcap_offline_read(pcap_t * p,int cnt,pcap_handler callback,u_char * user)618 pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
619 {
620 	struct bpf_insn *fcode;
621 	int status = 0;
622 	int n = 0;
623 	u_char *data;
624 
625 	while (status == 0) {
626 		struct pcap_pkthdr h;
627 
628 		/*
629 		 * Has "pcap_breakloop()" been called?
630 		 * If so, return immediately - if we haven't read any
631 		 * packets, clear the flag and return -2 to indicate
632 		 * that we were told to break out of the loop, otherwise
633 		 * leave the flag set, so that the *next* call will break
634 		 * out of the loop without having read any packets, and
635 		 * return the number of packets we've processed so far.
636 		 */
637 		if (p->break_loop) {
638 			if (n == 0) {
639 				p->break_loop = 0;
640 				return (-2);
641 			} else
642 				return (n);
643 		}
644 
645 		status = p->next_packet_op(p, &h, &data);
646 		if (status) {
647 			if (status == 1)
648 				return (0);
649 			return (status);
650 		}
651 
652 		if ((fcode = p->fcode.bf_insns) == NULL ||
653 		    pcap_filter(fcode, data, h.len, h.caplen)) {
654 			(*callback)(user, &h, data);
655 			if (++n >= cnt && cnt > 0)
656 				break;
657 		}
658 	}
659 	/*XXX this breaks semantics tcpslice expects */
660 	return (n);
661 }
662