xref: /freebsd/contrib/libpcap/savefile.c (revision afdbf109c6a661a729938f68211054a0a50d38ac)
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 
31b00ab754SHans Petter Selasky #include <config.h>
323052b236SBill Fenner 
33b00ab754SHans Petter Selasky #include <pcap-types.h>
34ada6f083SXin LI #ifdef _WIN32
35b00ab754SHans Petter Selasky #include <io.h>
36b00ab754SHans Petter Selasky #include <fcntl.h>
37ada6f083SXin LI #endif /* _WIN32 */
38a0ee43a1SRui Paulo 
398cf6c252SPaul Traina #include <errno.h>
408cf6c252SPaul Traina #include <memory.h>
418cf6c252SPaul Traina #include <stdio.h>
428cf6c252SPaul Traina #include <stdlib.h>
43dc2c7305SBill Fenner #include <string.h>
4457e22627SCy Schubert #include <limits.h> /* for INT_MAX */
458cf6c252SPaul Traina 
468cf6c252SPaul Traina #include "pcap-int.h"
478cf6c252SPaul Traina 
488cf6c252SPaul Traina #ifdef HAVE_OS_PROTO_H
498cf6c252SPaul Traina #include "os-proto.h"
508cf6c252SPaul Traina #endif
518cf6c252SPaul Traina 
52a0ee43a1SRui Paulo #include "sf-pcap.h"
53b00ab754SHans Petter Selasky #include "sf-pcapng.h"
5457e22627SCy Schubert #include "pcap-common.h"
556f9cba8fSJoseph Mingrone #include "charconv.h"
568cf6c252SPaul Traina 
57ada6f083SXin LI #ifdef _WIN32
58ada6f083SXin LI /*
596f9cba8fSJoseph Mingrone  * This isn't exported on Windows, because it would only work if both
6057e22627SCy Schubert  * WinPcap/Npcap and the code using it were to use the Universal CRT; otherwise,
6157e22627SCy Schubert  * a FILE structure in WinPcap/Npcap and a FILE structure in the code using it
62ada6f083SXin LI  * could be different if they're using different versions of the C runtime.
63ada6f083SXin LI  *
646f9cba8fSJoseph Mingrone  * Instead, pcap/pcap.h defines it as a macro that wraps the hopen version,
656f9cba8fSJoseph Mingrone  * with the wrapper calling _fileno() and _get_osfhandle() themselves,
666f9cba8fSJoseph Mingrone  * so that it convert the appropriate CRT version's FILE structure to
67ada6f083SXin LI  * a HANDLE (which is OS-defined, not CRT-defined, and is part of the Win32
68ada6f083SXin LI  * and Win64 ABIs).
69ada6f083SXin LI  */
70ada6f083SXin LI static pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
71ada6f083SXin LI #endif
72ada6f083SXin LI 
73dc2c7305SBill Fenner /*
7404fb2745SSam Leffler  * Setting O_BINARY on DOS/Windows is a bit tricky
7504fb2745SSam Leffler  */
76ada6f083SXin LI #if defined(_WIN32)
77ee2dd488SSam Leffler   #define SET_BINMODE(f)  _setmode(_fileno(f), _O_BINARY)
7804fb2745SSam Leffler #elif defined(MSDOS)
7904fb2745SSam Leffler   #if defined(__HIGHC__)
8004fb2745SSam Leffler   #define SET_BINMODE(f)  setmode(f, O_BINARY)
8104fb2745SSam Leffler   #else
8204fb2745SSam Leffler   #define SET_BINMODE(f)  setmode(fileno(f), O_BINARY)
8304fb2745SSam Leffler   #endif
8404fb2745SSam Leffler #endif
8504fb2745SSam Leffler 
86feb4ecdbSBruce M Simpson static int
sf_getnonblock(pcap_t * p _U_)87b00ab754SHans Petter Selasky sf_getnonblock(pcap_t *p _U_)
88feb4ecdbSBruce M Simpson {
89feb4ecdbSBruce M Simpson 	/*
90feb4ecdbSBruce M Simpson 	 * This is a savefile, not a live capture file, so never say
91feb4ecdbSBruce M Simpson 	 * it's in non-blocking mode.
92feb4ecdbSBruce M Simpson 	 */
93feb4ecdbSBruce M Simpson 	return (0);
94feb4ecdbSBruce M Simpson }
95feb4ecdbSBruce M Simpson 
96feb4ecdbSBruce M Simpson static int
sf_setnonblock(pcap_t * p,int nonblock _U_)97b00ab754SHans Petter Selasky sf_setnonblock(pcap_t *p, int nonblock _U_)
98feb4ecdbSBruce M Simpson {
99feb4ecdbSBruce M Simpson 	/*
100d1e87331SXin LI 	 * This is a savefile, not a live capture file, so reject
101d1e87331SXin LI 	 * requests to put it in non-blocking mode.  (If it's a
102d1e87331SXin LI 	 * pipe, it could be put in non-blocking mode, but that
103d1e87331SXin LI 	 * would significantly complicate the code to read packets,
104d1e87331SXin LI 	 * as it would have to handle reading partial packets and
105d1e87331SXin LI 	 * keeping the state of the read.)
106feb4ecdbSBruce M Simpson 	 */
1076f9cba8fSJoseph Mingrone 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
108d1e87331SXin LI 	    "Savefiles cannot be put into non-blocking mode");
109d1e87331SXin LI 	return (-1);
110feb4ecdbSBruce M Simpson }
111feb4ecdbSBruce M Simpson 
112feb4ecdbSBruce M Simpson static int
sf_cant_set_rfmon(pcap_t * p _U_)1136f9cba8fSJoseph Mingrone sf_cant_set_rfmon(pcap_t *p _U_)
1146f9cba8fSJoseph Mingrone {
1156f9cba8fSJoseph Mingrone 	/*
1166f9cba8fSJoseph Mingrone 	 * This is a savefile, not a device on which you can capture,
1176f9cba8fSJoseph Mingrone 	 * so never say it supports being put into monitor mode.
1186f9cba8fSJoseph Mingrone 	 */
1196f9cba8fSJoseph Mingrone 	return (0);
1206f9cba8fSJoseph Mingrone }
1216f9cba8fSJoseph Mingrone 
1226f9cba8fSJoseph Mingrone static int
sf_stats(pcap_t * p,struct pcap_stat * ps _U_)123b00ab754SHans Petter Selasky sf_stats(pcap_t *p, struct pcap_stat *ps _U_)
124feb4ecdbSBruce M Simpson {
1256f9cba8fSJoseph Mingrone 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
126feb4ecdbSBruce M Simpson 	    "Statistics aren't available from savefiles");
127feb4ecdbSBruce M Simpson 	return (-1);
128feb4ecdbSBruce M Simpson }
129feb4ecdbSBruce M Simpson 
130ada6f083SXin LI #ifdef _WIN32
131ada6f083SXin LI static struct pcap_stat *
sf_stats_ex(pcap_t * p,int * size _U_)1326f9cba8fSJoseph Mingrone sf_stats_ex(pcap_t *p, int *size _U_)
133ada6f083SXin LI {
1346f9cba8fSJoseph Mingrone 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
135ada6f083SXin LI 	    "Statistics aren't available from savefiles");
136ada6f083SXin LI 	return (NULL);
137ada6f083SXin LI }
138ada6f083SXin LI 
139a8e07101SRui Paulo static int
sf_setbuff(pcap_t * p,int dim _U_)1406f9cba8fSJoseph Mingrone sf_setbuff(pcap_t *p, int dim _U_)
141a8e07101SRui Paulo {
1426f9cba8fSJoseph Mingrone 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
143a8e07101SRui Paulo 	    "The kernel buffer size cannot be set while reading from a file");
144a8e07101SRui Paulo 	return (-1);
145a8e07101SRui Paulo }
146a8e07101SRui Paulo 
147a8e07101SRui Paulo static int
sf_setmode(pcap_t * p,int mode _U_)1486f9cba8fSJoseph Mingrone sf_setmode(pcap_t *p, int mode _U_)
149a8e07101SRui Paulo {
1506f9cba8fSJoseph Mingrone 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
151a8e07101SRui Paulo 	    "impossible to set mode while reading from a file");
152a8e07101SRui Paulo 	return (-1);
153a8e07101SRui Paulo }
154a8e07101SRui Paulo 
155a8e07101SRui Paulo static int
sf_setmintocopy(pcap_t * p,int size _U_)1566f9cba8fSJoseph Mingrone sf_setmintocopy(pcap_t *p, int size _U_)
157a8e07101SRui Paulo {
1586f9cba8fSJoseph Mingrone 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
159a8e07101SRui Paulo 	    "The mintocopy parameter cannot be set while reading from a file");
160a8e07101SRui Paulo 	return (-1);
161a8e07101SRui Paulo }
162ada6f083SXin LI 
163ada6f083SXin LI static HANDLE
sf_getevent(pcap_t * pcap)164ada6f083SXin LI sf_getevent(pcap_t *pcap)
165ada6f083SXin LI {
1666f9cba8fSJoseph Mingrone 	(void)snprintf(pcap->errbuf, sizeof(pcap->errbuf),
167ada6f083SXin LI 	    "The read event cannot be retrieved while reading from a file");
168ada6f083SXin LI 	return (INVALID_HANDLE_VALUE);
169ada6f083SXin LI }
170ada6f083SXin LI 
171ada6f083SXin LI static int
sf_oid_get_request(pcap_t * p,bpf_u_int32 oid _U_,void * data _U_,size_t * lenp _U_)172ada6f083SXin LI sf_oid_get_request(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_,
173ada6f083SXin LI     size_t *lenp _U_)
174ada6f083SXin LI {
1756f9cba8fSJoseph Mingrone 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
176ada6f083SXin LI 	    "An OID get request cannot be performed on a file");
177ada6f083SXin LI 	return (PCAP_ERROR);
178ada6f083SXin LI }
179ada6f083SXin LI 
180ada6f083SXin LI static int
sf_oid_set_request(pcap_t * p,bpf_u_int32 oid _U_,const void * data _U_,size_t * lenp _U_)181ada6f083SXin LI sf_oid_set_request(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
182ada6f083SXin LI     size_t *lenp _U_)
183ada6f083SXin LI {
1846f9cba8fSJoseph Mingrone 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
185ada6f083SXin LI 	    "An OID set request cannot be performed on a file");
186ada6f083SXin LI 	return (PCAP_ERROR);
187ada6f083SXin LI }
188ada6f083SXin LI 
189ada6f083SXin LI static u_int
sf_sendqueue_transmit(pcap_t * p,pcap_send_queue * queue _U_,int sync _U_)1906f9cba8fSJoseph Mingrone sf_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue _U_, int sync _U_)
191ada6f083SXin LI {
192*afdbf109SJoseph Mingrone 	pcapint_strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
193ada6f083SXin LI 	    PCAP_ERRBUF_SIZE);
194ada6f083SXin LI 	return (0);
195ada6f083SXin LI }
196ada6f083SXin LI 
197ada6f083SXin LI static int
sf_setuserbuffer(pcap_t * p,int size _U_)1986f9cba8fSJoseph Mingrone sf_setuserbuffer(pcap_t *p, int size _U_)
199ada6f083SXin LI {
2006f9cba8fSJoseph Mingrone 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
201ada6f083SXin LI 	    "The user buffer cannot be set when reading from a file");
202ada6f083SXin LI 	return (-1);
203ada6f083SXin LI }
204ada6f083SXin LI 
205ada6f083SXin LI static int
sf_live_dump(pcap_t * p,char * filename _U_,int maxsize _U_,int maxpacks _U_)2066f9cba8fSJoseph Mingrone sf_live_dump(pcap_t *p, char *filename _U_, int maxsize _U_, int maxpacks _U_)
207ada6f083SXin LI {
2086f9cba8fSJoseph Mingrone 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
209ada6f083SXin LI 	    "Live packet dumping cannot be performed when reading from a file");
210ada6f083SXin LI 	return (-1);
211ada6f083SXin LI }
212ada6f083SXin LI 
213ada6f083SXin LI static int
sf_live_dump_ended(pcap_t * p,int sync _U_)2146f9cba8fSJoseph Mingrone sf_live_dump_ended(pcap_t *p, int sync _U_)
215ada6f083SXin LI {
2166f9cba8fSJoseph Mingrone 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
217ada6f083SXin LI 	    "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
218ada6f083SXin LI 	return (-1);
219ada6f083SXin LI }
220ada6f083SXin LI 
221ada6f083SXin LI static PAirpcapHandle
sf_get_airpcap_handle(pcap_t * pcap _U_)2226f9cba8fSJoseph Mingrone sf_get_airpcap_handle(pcap_t *pcap _U_)
223ada6f083SXin LI {
224ada6f083SXin LI 	return (NULL);
225ada6f083SXin LI }
226a8e07101SRui Paulo #endif
227a8e07101SRui Paulo 
22804fb2745SSam Leffler static int
sf_inject(pcap_t * p,const void * buf _U_,int size _U_)2296f9cba8fSJoseph Mingrone sf_inject(pcap_t *p, const void *buf _U_, int size _U_)
23004fb2745SSam Leffler {
231*afdbf109SJoseph Mingrone 	pcapint_strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
23204fb2745SSam Leffler 	    PCAP_ERRBUF_SIZE);
23304fb2745SSam Leffler 	return (-1);
23404fb2745SSam Leffler }
23504fb2745SSam Leffler 
236ee2dd488SSam Leffler /*
237ee2dd488SSam Leffler  * Set direction flag: Which packets do we accept on a forwarding
238ee2dd488SSam Leffler  * single device? IN, OUT or both?
239ee2dd488SSam Leffler  */
240ee2dd488SSam Leffler static int
sf_setdirection(pcap_t * p,pcap_direction_t d _U_)241b00ab754SHans Petter Selasky sf_setdirection(pcap_t *p, pcap_direction_t d _U_)
242ee2dd488SSam Leffler {
2436f9cba8fSJoseph Mingrone 	snprintf(p->errbuf, sizeof(p->errbuf),
244ee2dd488SSam Leffler 	    "Setting direction is not supported on savefiles");
245ee2dd488SSam Leffler 	return (-1);
246ee2dd488SSam Leffler }
247ee2dd488SSam Leffler 
248681ed54cSXin LI void
pcapint_sf_cleanup(pcap_t * p)249*afdbf109SJoseph Mingrone pcapint_sf_cleanup(pcap_t *p)
250feb4ecdbSBruce M Simpson {
251681ed54cSXin LI 	if (p->rfile != stdin)
252681ed54cSXin LI 		(void)fclose(p->rfile);
253a0ee43a1SRui Paulo 	if (p->buffer != NULL)
254a0ee43a1SRui Paulo 		free(p->buffer);
255d1e87331SXin LI 	pcap_freecode(&p->fcode);
256feb4ecdbSBruce M Simpson }
257feb4ecdbSBruce M Simpson 
2586f9cba8fSJoseph Mingrone #ifdef _WIN32
2596f9cba8fSJoseph Mingrone /*
2606f9cba8fSJoseph Mingrone  * Wrapper for fopen() and _wfopen().
2616f9cba8fSJoseph Mingrone  *
2626f9cba8fSJoseph Mingrone  * If we're in UTF-8 mode, map the pathname from UTF-8 to UTF-16LE and
2636f9cba8fSJoseph Mingrone  * call _wfopen().
2646f9cba8fSJoseph Mingrone  *
2656f9cba8fSJoseph Mingrone  * If we're not, just use fopen(); that'll treat it as being in the
2666f9cba8fSJoseph Mingrone  * local code page.
2676f9cba8fSJoseph Mingrone  */
2686f9cba8fSJoseph Mingrone FILE *
pcapint_charset_fopen(const char * path,const char * mode)269*afdbf109SJoseph Mingrone pcapint_charset_fopen(const char *path, const char *mode)
2706f9cba8fSJoseph Mingrone {
2716f9cba8fSJoseph Mingrone 	wchar_t *utf16_path;
2726f9cba8fSJoseph Mingrone #define MAX_MODE_LEN	16
2736f9cba8fSJoseph Mingrone 	wchar_t utf16_mode[MAX_MODE_LEN+1];
2746f9cba8fSJoseph Mingrone 	int i;
2756f9cba8fSJoseph Mingrone 	char c;
2766f9cba8fSJoseph Mingrone 	FILE *fp;
2776f9cba8fSJoseph Mingrone 	int save_errno;
2786f9cba8fSJoseph Mingrone 
279*afdbf109SJoseph Mingrone 	if (pcapint_utf_8_mode) {
2806f9cba8fSJoseph Mingrone 		/*
2816f9cba8fSJoseph Mingrone 		 * Map from UTF-8 to UTF-16LE.
2826f9cba8fSJoseph Mingrone 		 * Fail if there are invalid characters in the input
2836f9cba8fSJoseph Mingrone 		 * string, rather than converting them to REPLACEMENT
2846f9cba8fSJoseph Mingrone 		 * CHARACTER; the latter is appropriate for strings
2856f9cba8fSJoseph Mingrone 		 * to be displayed to the user, but for file names
2866f9cba8fSJoseph Mingrone 		 * you just want the attempt to open the file to fail.
2876f9cba8fSJoseph Mingrone 		 */
2886f9cba8fSJoseph Mingrone 		utf16_path = cp_to_utf_16le(CP_UTF8, path,
2896f9cba8fSJoseph Mingrone 		    MB_ERR_INVALID_CHARS);
2906f9cba8fSJoseph Mingrone 		if (utf16_path == NULL) {
2916f9cba8fSJoseph Mingrone 			/*
2926f9cba8fSJoseph Mingrone 			 * Error.  Assume errno has been set.
2936f9cba8fSJoseph Mingrone 			 *
2946f9cba8fSJoseph Mingrone 			 * XXX - what about Windows errors?
2956f9cba8fSJoseph Mingrone 			 */
2966f9cba8fSJoseph Mingrone 			return (NULL);
2976f9cba8fSJoseph Mingrone 		}
2986f9cba8fSJoseph Mingrone 
2996f9cba8fSJoseph Mingrone 		/*
3006f9cba8fSJoseph Mingrone 		 * Now convert the mode to UTF-16LE as well.
3016f9cba8fSJoseph Mingrone 		 * We assume the mode is ASCII, and that
3026f9cba8fSJoseph Mingrone 		 * it's short, so that's easy.
3036f9cba8fSJoseph Mingrone 		 */
3046f9cba8fSJoseph Mingrone 		for (i = 0; (c = *mode) != '\0'; i++, mode++) {
3056f9cba8fSJoseph Mingrone 			if (c > 0x7F) {
3066f9cba8fSJoseph Mingrone 				/* Not an ASCII character; fail with EINVAL. */
3076f9cba8fSJoseph Mingrone 				free(utf16_path);
3086f9cba8fSJoseph Mingrone 				errno = EINVAL;
3096f9cba8fSJoseph Mingrone 				return (NULL);
3106f9cba8fSJoseph Mingrone 			}
3116f9cba8fSJoseph Mingrone 			if (i >= MAX_MODE_LEN) {
3126f9cba8fSJoseph Mingrone 				/* The mode string is longer than we allow. */
3136f9cba8fSJoseph Mingrone 				free(utf16_path);
3146f9cba8fSJoseph Mingrone 				errno = EINVAL;
3156f9cba8fSJoseph Mingrone 				return (NULL);
3166f9cba8fSJoseph Mingrone 			}
3176f9cba8fSJoseph Mingrone 			utf16_mode[i] = c;
3186f9cba8fSJoseph Mingrone 		}
3196f9cba8fSJoseph Mingrone 		utf16_mode[i] = '\0';
3206f9cba8fSJoseph Mingrone 
3216f9cba8fSJoseph Mingrone 		/*
3226f9cba8fSJoseph Mingrone 		 * OK, we have UTF-16LE strings; hand them to
3236f9cba8fSJoseph Mingrone 		 * _wfopen().
3246f9cba8fSJoseph Mingrone 		 */
3256f9cba8fSJoseph Mingrone 		fp = _wfopen(utf16_path, utf16_mode);
3266f9cba8fSJoseph Mingrone 
3276f9cba8fSJoseph Mingrone 		/*
3286f9cba8fSJoseph Mingrone 		 * Make sure freeing the UTF-16LE string doesn't
3296f9cba8fSJoseph Mingrone 		 * overwrite the error code we got from _wfopen().
3306f9cba8fSJoseph Mingrone 		 */
3316f9cba8fSJoseph Mingrone 		save_errno = errno;
3326f9cba8fSJoseph Mingrone 		free(utf16_path);
3336f9cba8fSJoseph Mingrone 		errno = save_errno;
3346f9cba8fSJoseph Mingrone 
3356f9cba8fSJoseph Mingrone 		return (fp);
3366f9cba8fSJoseph Mingrone 	} else {
3376f9cba8fSJoseph Mingrone 		/*
3386f9cba8fSJoseph Mingrone 		 * This takes strings in the local code page as an
3396f9cba8fSJoseph Mingrone 		 * argument.
3406f9cba8fSJoseph Mingrone 		 */
3416f9cba8fSJoseph Mingrone 		return (fopen(path, mode));
3426f9cba8fSJoseph Mingrone 	}
3436f9cba8fSJoseph Mingrone }
3446f9cba8fSJoseph Mingrone #endif
3456f9cba8fSJoseph Mingrone 
3468cf6c252SPaul Traina pcap_t *
pcap_open_offline_with_tstamp_precision(const char * fname,u_int precision,char * errbuf)347681ed54cSXin LI pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
348681ed54cSXin LI 					char *errbuf)
3498cf6c252SPaul Traina {
35004fb2745SSam Leffler 	FILE *fp;
35104fb2745SSam Leffler 	pcap_t *p;
35204fb2745SSam Leffler 
353ada6f083SXin LI 	if (fname == NULL) {
3546f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
355ada6f083SXin LI 		    "A null pointer was supplied as the file name");
356ada6f083SXin LI 		return (NULL);
357ada6f083SXin LI 	}
35804fb2745SSam Leffler 	if (fname[0] == '-' && fname[1] == '\0')
359ee2dd488SSam Leffler 	{
36004fb2745SSam Leffler 		fp = stdin;
3616f9cba8fSJoseph Mingrone 		if (fp == NULL) {
3626f9cba8fSJoseph Mingrone 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
3636f9cba8fSJoseph Mingrone 			    "The standard input is not open");
3646f9cba8fSJoseph Mingrone 			return (NULL);
3656f9cba8fSJoseph Mingrone 		}
366ada6f083SXin LI #if defined(_WIN32) || defined(MSDOS)
367ee2dd488SSam Leffler 		/*
368ee2dd488SSam Leffler 		 * We're reading from the standard input, so put it in binary
369ee2dd488SSam Leffler 		 * mode, as savefiles are binary files.
370ee2dd488SSam Leffler 		 */
371ee2dd488SSam Leffler 		SET_BINMODE(fp);
372ee2dd488SSam Leffler #endif
373ee2dd488SSam Leffler 	}
37404fb2745SSam Leffler 	else {
375b00ab754SHans Petter Selasky 		/*
376*afdbf109SJoseph Mingrone 		 * Use pcapint_charset_fopen(); on Windows, it tests whether we're
3776f9cba8fSJoseph Mingrone 		 * in "local code page" or "UTF-8" mode, and treats the
3786f9cba8fSJoseph Mingrone 		 * pathname appropriately, and on other platforms, it just
3796f9cba8fSJoseph Mingrone 		 * wraps fopen().
3806f9cba8fSJoseph Mingrone 		 *
381b00ab754SHans Petter Selasky 		 * "b" is supported as of C90, so *all* UN*Xes should
3826f9cba8fSJoseph Mingrone 		 * support it, even though it does nothing.  For MS-DOS,
3836f9cba8fSJoseph Mingrone 		 * we again need it.
384b00ab754SHans Petter Selasky 		 */
385*afdbf109SJoseph Mingrone 		fp = pcapint_charset_fopen(fname, "rb");
38604fb2745SSam Leffler 		if (fp == NULL) {
387*afdbf109SJoseph Mingrone 			pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
388b00ab754SHans Petter Selasky 			    errno, "%s", fname);
38904fb2745SSam Leffler 			return (NULL);
39004fb2745SSam Leffler 		}
39104fb2745SSam Leffler 	}
392681ed54cSXin LI 	p = pcap_fopen_offline_with_tstamp_precision(fp, precision, errbuf);
39304fb2745SSam Leffler 	if (p == NULL) {
39404fb2745SSam Leffler 		if (fp != stdin)
39504fb2745SSam Leffler 			fclose(fp);
39604fb2745SSam Leffler 	}
39704fb2745SSam Leffler 	return (p);
39804fb2745SSam Leffler }
39904fb2745SSam Leffler 
400681ed54cSXin LI pcap_t *
pcap_open_offline(const char * fname,char * errbuf)401681ed54cSXin LI pcap_open_offline(const char *fname, char *errbuf)
402681ed54cSXin LI {
403681ed54cSXin LI 	return (pcap_open_offline_with_tstamp_precision(fname,
404681ed54cSXin LI 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf));
405681ed54cSXin LI }
406681ed54cSXin LI 
407ada6f083SXin LI #ifdef _WIN32
pcap_hopen_offline_with_tstamp_precision(intptr_t osfd,u_int precision,char * errbuf)408681ed54cSXin LI pcap_t* pcap_hopen_offline_with_tstamp_precision(intptr_t osfd, u_int precision,
409681ed54cSXin LI     char *errbuf)
410a8e07101SRui Paulo {
411a8e07101SRui Paulo 	int fd;
412a8e07101SRui Paulo 	FILE *file;
413a8e07101SRui Paulo 
414a8e07101SRui Paulo 	fd = _open_osfhandle(osfd, _O_RDONLY);
415a8e07101SRui Paulo 	if ( fd < 0 )
416a8e07101SRui Paulo 	{
417*afdbf109SJoseph Mingrone 		pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
418b00ab754SHans Petter Selasky 		    errno, "_open_osfhandle");
419a8e07101SRui Paulo 		return NULL;
420a8e07101SRui Paulo 	}
421a8e07101SRui Paulo 
422a8e07101SRui Paulo 	file = _fdopen(fd, "rb");
423a8e07101SRui Paulo 	if ( file == NULL )
424a8e07101SRui Paulo 	{
425*afdbf109SJoseph Mingrone 		pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
426b00ab754SHans Petter Selasky 		    errno, "_fdopen");
42757e22627SCy Schubert 		_close(fd);
428a8e07101SRui Paulo 		return NULL;
429a8e07101SRui Paulo 	}
430a8e07101SRui Paulo 
431681ed54cSXin LI 	return pcap_fopen_offline_with_tstamp_precision(file, precision,
432681ed54cSXin LI 	    errbuf);
433681ed54cSXin LI }
434681ed54cSXin LI 
pcap_hopen_offline(intptr_t osfd,char * errbuf)435681ed54cSXin LI pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
436681ed54cSXin LI {
437681ed54cSXin LI 	return pcap_hopen_offline_with_tstamp_precision(osfd,
438681ed54cSXin LI 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf);
439a8e07101SRui Paulo }
440a8e07101SRui Paulo #endif
441a8e07101SRui Paulo 
44257e22627SCy Schubert /*
44357e22627SCy Schubert  * Given a link-layer header type and snapshot length, return a
44457e22627SCy Schubert  * snapshot length to use when reading the file; it's guaranteed
44557e22627SCy Schubert  * to be > 0 and <= INT_MAX.
44657e22627SCy Schubert  *
44757e22627SCy Schubert  * XXX - the only reason why we limit it to <= INT_MAX is so that
44857e22627SCy Schubert  * it fits in p->snapshot, and the only reason that p->snapshot is
44957e22627SCy Schubert  * signed is that pcap_snapshot() returns an int, not an unsigned int.
45057e22627SCy Schubert  */
45157e22627SCy Schubert bpf_u_int32
pcapint_adjust_snapshot(bpf_u_int32 linktype,bpf_u_int32 snaplen)452*afdbf109SJoseph Mingrone pcapint_adjust_snapshot(bpf_u_int32 linktype, bpf_u_int32 snaplen)
45357e22627SCy Schubert {
45457e22627SCy Schubert 	if (snaplen == 0 || snaplen > INT_MAX) {
45557e22627SCy Schubert 		/*
45657e22627SCy Schubert 		 * Bogus snapshot length; use the maximum for this
45757e22627SCy Schubert 		 * link-layer type as a fallback.
45857e22627SCy Schubert 		 *
45957e22627SCy Schubert 		 * XXX - we don't clamp snapshot lengths that are
46057e22627SCy Schubert 		 * <= INT_MAX but > max_snaplen_for_dlt(linktype),
46157e22627SCy Schubert 		 * so a capture file could cause us to allocate
46257e22627SCy Schubert 		 * a Really Big Buffer.
46357e22627SCy Schubert 		 */
46457e22627SCy Schubert 		snaplen = max_snaplen_for_dlt(linktype);
46557e22627SCy Schubert 	}
46657e22627SCy Schubert 	return snaplen;
46757e22627SCy Schubert }
46857e22627SCy Schubert 
46957e22627SCy Schubert static pcap_t *(*check_headers[])(const uint8_t *, FILE *, u_int, char *, int *) = {
470a0ee43a1SRui Paulo 	pcap_check_header,
471a0ee43a1SRui Paulo 	pcap_ng_check_header
472a0ee43a1SRui Paulo };
473a0ee43a1SRui Paulo 
474a0ee43a1SRui Paulo #define	N_FILE_TYPES	(sizeof check_headers / sizeof check_headers[0])
475a0ee43a1SRui Paulo 
476ada6f083SXin LI #ifdef _WIN32
477a8e07101SRui Paulo static
478a8e07101SRui Paulo #endif
47904fb2745SSam Leffler pcap_t *
pcap_fopen_offline_with_tstamp_precision(FILE * fp,u_int precision,char * errbuf)480681ed54cSXin LI pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision,
481681ed54cSXin LI     char *errbuf)
48204fb2745SSam Leffler {
4838cf6c252SPaul Traina 	register pcap_t *p;
48457e22627SCy Schubert 	uint8_t magic[4];
485a0ee43a1SRui Paulo 	size_t amt_read;
486a0ee43a1SRui Paulo 	u_int i;
487681ed54cSXin LI 	int err;
4888cf6c252SPaul Traina 
489a0ee43a1SRui Paulo 	/*
4906f9cba8fSJoseph Mingrone 	 * Fail if we were passed a NULL fp.
4916f9cba8fSJoseph Mingrone 	 *
4926f9cba8fSJoseph Mingrone 	 * That shouldn't happen if we're opening with a path name, but
4936f9cba8fSJoseph Mingrone 	 * it could happen if buggy code is opening with a FILE * and
4946f9cba8fSJoseph Mingrone 	 * didn't bother to make sure the FILE * isn't null.
4956f9cba8fSJoseph Mingrone 	 */
4966f9cba8fSJoseph Mingrone 	if (fp == NULL) {
4976f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
4986f9cba8fSJoseph Mingrone 		    "Null FILE * pointer provided to savefile open routine");
4996f9cba8fSJoseph Mingrone 		return (NULL);
5006f9cba8fSJoseph Mingrone 	}
5016f9cba8fSJoseph Mingrone 
5026f9cba8fSJoseph Mingrone 	/*
503a0ee43a1SRui Paulo 	 * Read the first 4 bytes of the file; the network analyzer dump
504b00ab754SHans Petter Selasky 	 * file formats we support (pcap and pcapng), and several other
505a0ee43a1SRui Paulo 	 * formats we might support in the future (such as snoop, DOS and
506a0ee43a1SRui Paulo 	 * Windows Sniffer, and Microsoft Network Monitor) all have magic
507a0ee43a1SRui Paulo 	 * numbers that are unique in their first 4 bytes.
508a0ee43a1SRui Paulo 	 */
50957e22627SCy Schubert 	amt_read = fread(&magic, 1, sizeof(magic), fp);
510a0ee43a1SRui Paulo 	if (amt_read != sizeof(magic)) {
51104fb2745SSam Leffler 		if (ferror(fp)) {
512*afdbf109SJoseph Mingrone 			pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
513b00ab754SHans Petter Selasky 			    errno, "error reading dump file");
51404fb2745SSam Leffler 		} else {
5156f9cba8fSJoseph Mingrone 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
5166f9cba8fSJoseph Mingrone 			    "truncated dump file; tried to read %zu file header bytes, only got %zu",
51757e22627SCy Schubert 			    sizeof(magic), amt_read);
5188cf6c252SPaul Traina 		}
519681ed54cSXin LI 		return (NULL);
5208cf6c252SPaul Traina 	}
521a0ee43a1SRui Paulo 
522dc2c7305SBill Fenner 	/*
523a0ee43a1SRui Paulo 	 * Try all file types.
524dc2c7305SBill Fenner 	 */
525a0ee43a1SRui Paulo 	for (i = 0; i < N_FILE_TYPES; i++) {
526681ed54cSXin LI 		p = (*check_headers[i])(magic, fp, precision, errbuf, &err);
527681ed54cSXin LI 		if (p != NULL) {
528681ed54cSXin LI 			/* Yup, that's it. */
529681ed54cSXin LI 			goto found;
530681ed54cSXin LI 		}
531681ed54cSXin LI 		if (err) {
532ef96d74fSMax Laier 			/*
533a0ee43a1SRui Paulo 			 * Error trying to read the header.
534ef96d74fSMax Laier 			 */
535681ed54cSXin LI 			return (NULL);
536ef96d74fSMax Laier 		}
537a0ee43a1SRui Paulo 	}
538a0ee43a1SRui Paulo 
539a0ee43a1SRui Paulo 	/*
540a0ee43a1SRui Paulo 	 * Well, who knows what this mess is....
541a0ee43a1SRui Paulo 	 */
5426f9cba8fSJoseph Mingrone 	snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
543681ed54cSXin LI 	return (NULL);
544a0ee43a1SRui Paulo 
545a0ee43a1SRui Paulo found:
546681ed54cSXin LI 	p->rfile = fp;
5478cf6c252SPaul Traina 
54804fb2745SSam Leffler 	/* Padding only needed for live capture fcode */
54904fb2745SSam Leffler 	p->fddipad = 0;
5508cf6c252SPaul Traina 
551ada6f083SXin LI #if !defined(_WIN32) && !defined(MSDOS)
552feb4ecdbSBruce M Simpson 	/*
553feb4ecdbSBruce M Simpson 	 * You can do "select()" and "poll()" on plain files on most
554feb4ecdbSBruce M Simpson 	 * platforms, and should be able to do so on pipes.
555feb4ecdbSBruce M Simpson 	 *
556feb4ecdbSBruce M Simpson 	 * You can't do "select()" on anything other than sockets in
557feb4ecdbSBruce M Simpson 	 * Windows, so, on Win32 systems, we don't have "selectable_fd".
558feb4ecdbSBruce M Simpson 	 */
559feb4ecdbSBruce M Simpson 	p->selectable_fd = fileno(fp);
560feb4ecdbSBruce M Simpson #endif
561feb4ecdbSBruce M Simpson 
5626f9cba8fSJoseph Mingrone 	p->can_set_rfmon_op = sf_cant_set_rfmon;
563*afdbf109SJoseph Mingrone 	p->read_op = pcapint_offline_read;
56404fb2745SSam Leffler 	p->inject_op = sf_inject;
565*afdbf109SJoseph Mingrone 	p->setfilter_op = pcapint_install_bpf_program;
566ee2dd488SSam Leffler 	p->setdirection_op = sf_setdirection;
567feb4ecdbSBruce M Simpson 	p->set_datalink_op = NULL;	/* we don't support munging link-layer headers */
568feb4ecdbSBruce M Simpson 	p->getnonblock_op = sf_getnonblock;
569feb4ecdbSBruce M Simpson 	p->setnonblock_op = sf_setnonblock;
570feb4ecdbSBruce M Simpson 	p->stats_op = sf_stats;
571ada6f083SXin LI #ifdef _WIN32
572ada6f083SXin LI 	p->stats_ex_op = sf_stats_ex;
573a8e07101SRui Paulo 	p->setbuff_op = sf_setbuff;
574a8e07101SRui Paulo 	p->setmode_op = sf_setmode;
575a8e07101SRui Paulo 	p->setmintocopy_op = sf_setmintocopy;
576ada6f083SXin LI 	p->getevent_op = sf_getevent;
577ada6f083SXin LI 	p->oid_get_request_op = sf_oid_get_request;
578ada6f083SXin LI 	p->oid_set_request_op = sf_oid_set_request;
579ada6f083SXin LI 	p->sendqueue_transmit_op = sf_sendqueue_transmit;
580ada6f083SXin LI 	p->setuserbuffer_op = sf_setuserbuffer;
581ada6f083SXin LI 	p->live_dump_op = sf_live_dump;
582ada6f083SXin LI 	p->live_dump_ended_op = sf_live_dump_ended;
583ada6f083SXin LI 	p->get_airpcap_handle_op = sf_get_airpcap_handle;
584a8e07101SRui Paulo #endif
585681ed54cSXin LI 
586681ed54cSXin LI 	/*
587681ed54cSXin LI 	 * For offline captures, the standard one-shot callback can
588681ed54cSXin LI 	 * be used for pcap_next()/pcap_next_ex().
589681ed54cSXin LI 	 */
590*afdbf109SJoseph Mingrone 	p->oneshot_callback = pcapint_oneshot;
591681ed54cSXin LI 
592ada6f083SXin LI 	/*
5936f9cba8fSJoseph Mingrone 	 * Default breakloop operation.
5946f9cba8fSJoseph Mingrone 	 */
595*afdbf109SJoseph Mingrone 	p->breakloop_op = pcapint_breakloop_common;
5966f9cba8fSJoseph Mingrone 
5976f9cba8fSJoseph Mingrone 	/*
598ada6f083SXin LI 	 * Savefiles never require special BPF code generation.
599ada6f083SXin LI 	 */
600ada6f083SXin LI 	p->bpf_codegen_flags = 0;
601ada6f083SXin LI 
602a8e07101SRui Paulo 	p->activated = 1;
603feb4ecdbSBruce M Simpson 
6048cf6c252SPaul Traina 	return (p);
605681ed54cSXin LI }
606681ed54cSXin LI 
6076f9cba8fSJoseph Mingrone /*
6086f9cba8fSJoseph Mingrone  * This isn't needed on Windows; we #define pcap_fopen_offline() as
6096f9cba8fSJoseph Mingrone  * a wrapper around pcap_hopen_offline(), and we don't call it from
6106f9cba8fSJoseph Mingrone  * inside this file, so it's unused.
6116f9cba8fSJoseph Mingrone  */
6126f9cba8fSJoseph Mingrone #ifndef _WIN32
613681ed54cSXin LI pcap_t *
pcap_fopen_offline(FILE * fp,char * errbuf)614681ed54cSXin LI pcap_fopen_offline(FILE *fp, char *errbuf)
615681ed54cSXin LI {
616681ed54cSXin LI 	return (pcap_fopen_offline_with_tstamp_precision(fp,
617681ed54cSXin LI 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf));
6188cf6c252SPaul Traina }
6196f9cba8fSJoseph Mingrone #endif
6208cf6c252SPaul Traina 
6218cf6c252SPaul Traina /*
622a0ee43a1SRui Paulo  * Read packets from a capture file, and call the callback for each
623a0ee43a1SRui Paulo  * packet.
6248cf6c252SPaul Traina  * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
6258cf6c252SPaul Traina  */
6268cf6c252SPaul Traina int
pcapint_offline_read(pcap_t * p,int cnt,pcap_handler callback,u_char * user)627*afdbf109SJoseph Mingrone pcapint_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
6288cf6c252SPaul Traina {
62904fb2745SSam Leffler 	struct bpf_insn *fcode;
6308cf6c252SPaul Traina 	int n = 0;
631a0ee43a1SRui Paulo 	u_char *data;
6328cf6c252SPaul Traina 
6336f9cba8fSJoseph Mingrone 	/*
6346f9cba8fSJoseph Mingrone 	 * This can conceivably process more than INT_MAX packets,
6356f9cba8fSJoseph Mingrone 	 * which would overflow the packet count, causing it either
6366f9cba8fSJoseph Mingrone 	 * to look like a negative number, and thus cause us to
6376f9cba8fSJoseph Mingrone 	 * return a value that looks like an error, or overflow
6386f9cba8fSJoseph Mingrone 	 * back into positive territory, and thus cause us to
6396f9cba8fSJoseph Mingrone 	 * return a too-low count.
6406f9cba8fSJoseph Mingrone 	 *
6416f9cba8fSJoseph Mingrone 	 * Therefore, if the packet count is unlimited, we clip
6426f9cba8fSJoseph Mingrone 	 * it at INT_MAX; this routine is not expected to
6436f9cba8fSJoseph Mingrone 	 * process packets indefinitely, so that's not an issue.
6446f9cba8fSJoseph Mingrone 	 */
6456f9cba8fSJoseph Mingrone 	if (PACKET_COUNT_IS_UNLIMITED(cnt))
6466f9cba8fSJoseph Mingrone 		cnt = INT_MAX;
6476f9cba8fSJoseph Mingrone 
6486f9cba8fSJoseph Mingrone 	for (;;) {
6498cf6c252SPaul Traina 		struct pcap_pkthdr h;
6506f9cba8fSJoseph Mingrone 		int status;
6518cf6c252SPaul Traina 
652feb4ecdbSBruce M Simpson 		/*
653feb4ecdbSBruce M Simpson 		 * Has "pcap_breakloop()" been called?
654feb4ecdbSBruce M Simpson 		 * If so, return immediately - if we haven't read any
655feb4ecdbSBruce M Simpson 		 * packets, clear the flag and return -2 to indicate
656feb4ecdbSBruce M Simpson 		 * that we were told to break out of the loop, otherwise
657feb4ecdbSBruce M Simpson 		 * leave the flag set, so that the *next* call will break
658feb4ecdbSBruce M Simpson 		 * out of the loop without having read any packets, and
659feb4ecdbSBruce M Simpson 		 * return the number of packets we've processed so far.
660feb4ecdbSBruce M Simpson 		 */
661feb4ecdbSBruce M Simpson 		if (p->break_loop) {
662feb4ecdbSBruce M Simpson 			if (n == 0) {
663feb4ecdbSBruce M Simpson 				p->break_loop = 0;
664feb4ecdbSBruce M Simpson 				return (-2);
665feb4ecdbSBruce M Simpson 			} else
666feb4ecdbSBruce M Simpson 				return (n);
667feb4ecdbSBruce M Simpson 		}
668feb4ecdbSBruce M Simpson 
669681ed54cSXin LI 		status = p->next_packet_op(p, &h, &data);
6706f9cba8fSJoseph Mingrone 		if (status < 0) {
6716f9cba8fSJoseph Mingrone 			/*
6726f9cba8fSJoseph Mingrone 			 * Error.  Pass it back to the caller.
6736f9cba8fSJoseph Mingrone 			 */
6748cf6c252SPaul Traina 			return (status);
6758cf6c252SPaul Traina 		}
6766f9cba8fSJoseph Mingrone 		if (status == 0) {
6776f9cba8fSJoseph Mingrone 			/*
6786f9cba8fSJoseph Mingrone 			 * EOF.  Nothing more to process;
6796f9cba8fSJoseph Mingrone 			 */
6806f9cba8fSJoseph Mingrone 			break;
6816f9cba8fSJoseph Mingrone 		}
6828cf6c252SPaul Traina 
6836f9cba8fSJoseph Mingrone 		/*
6846f9cba8fSJoseph Mingrone 		 * OK, we've read a packet; run it through the filter
6856f9cba8fSJoseph Mingrone 		 * and, if it passes, process it.
6866f9cba8fSJoseph Mingrone 		 */
68704fb2745SSam Leffler 		if ((fcode = p->fcode.bf_insns) == NULL ||
688*afdbf109SJoseph Mingrone 		    pcapint_filter(fcode, data, h.len, h.caplen)) {
689a0ee43a1SRui Paulo 			(*callback)(user, &h, data);
6906f9cba8fSJoseph Mingrone 			n++;	/* count the packet */
6916f9cba8fSJoseph Mingrone 			if (n >= cnt)
6928cf6c252SPaul Traina 				break;
6938cf6c252SPaul Traina 		}
6948cf6c252SPaul Traina 	}
6958cf6c252SPaul Traina 	/*XXX this breaks semantics tcpslice expects */
6968cf6c252SPaul Traina 	return (n);
6978cf6c252SPaul Traina }
698