Home | History | Annotate | Download | only in libpcap
      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 #ifdef _WIN32
     36 #include <pcap-stdinc.h>
     37 #else /* _WIN32 */
     38 #if HAVE_INTTYPES_H
     39 #include <inttypes.h>
     40 #elif HAVE_STDINT_H
     41 #include <stdint.h>
     42 #endif
     43 #ifdef HAVE_SYS_BITYPES_H
     44 #include <sys/bitypes.h>
     45 #endif
     46 #include <sys/types.h>
     47 #endif /* _WIN32 */
     48 
     49 #include <errno.h>
     50 #include <memory.h>
     51 #include <stdio.h>
     52 #include <stdlib.h>
     53 #include <string.h>
     54 
     55 #include "pcap-int.h"
     56 
     57 #ifdef HAVE_OS_PROTO_H
     58 #include "os-proto.h"
     59 #endif
     60 
     61 #include "sf-pcap.h"
     62 #include "sf-pcap-ng.h"
     63 
     64 #ifdef _WIN32
     65 /*
     66  * These aren't exported on Windows, because they would only work if both
     67  * WinPcap and the code using it were to use the Universal CRT; otherwise,
     68  * a FILE structure in WinPcap and a FILE structure in the code using it
     69  * could be different if they're using different versions of the C runtime.
     70  *
     71  * Instead, pcap/pcap.h defines them as macros that wrap the hopen versions,
     72  * with the wrappers calling _fileno() and _get_osfhandle() themselves,
     73  * so that they convert the appropriate CRT version's FILE structure to
     74  * a HANDLE (which is OS-defined, not CRT-defined, and is part of the Win32
     75  * and Win64 ABIs).
     76  */
     77 static pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
     78 static pcap_t *pcap_fopen_offline(FILE *, char *);
     79 #endif
     80 
     81 /*
     82  * Setting O_BINARY on DOS/Windows is a bit tricky
     83  */
     84 #if defined(_WIN32)
     85   #define SET_BINMODE(f)  _setmode(_fileno(f), _O_BINARY)
     86 #elif defined(MSDOS)
     87   #if defined(__HIGHC__)
     88   #define SET_BINMODE(f)  setmode(f, O_BINARY)
     89   #else
     90   #define SET_BINMODE(f)  setmode(fileno(f), O_BINARY)
     91   #endif
     92 #endif
     93 
     94 static int
     95 sf_getnonblock(pcap_t *p, char *errbuf)
     96 {
     97 	/*
     98 	 * This is a savefile, not a live capture file, so never say
     99 	 * it's in non-blocking mode.
    100 	 */
    101 	return (0);
    102 }
    103 
    104 static int
    105 sf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
    106 {
    107 	/*
    108 	 * This is a savefile, not a live capture file, so reject
    109 	 * requests to put it in non-blocking mode.  (If it's a
    110 	 * pipe, it could be put in non-blocking mode, but that
    111 	 * would significantly complicate the code to read packets,
    112 	 * as it would have to handle reading partial packets and
    113 	 * keeping the state of the read.)
    114 	 */
    115 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    116 	    "Savefiles cannot be put into non-blocking mode");
    117 	return (-1);
    118 }
    119 
    120 static int
    121 sf_stats(pcap_t *p, struct pcap_stat *ps)
    122 {
    123 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    124 	    "Statistics aren't available from savefiles");
    125 	return (-1);
    126 }
    127 
    128 #ifdef _WIN32
    129 static struct pcap_stat *
    130 sf_stats_ex(pcap_t *p, int *size)
    131 {
    132 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    133 	    "Statistics aren't available from savefiles");
    134 	return (NULL);
    135 }
    136 
    137 static int
    138 sf_setbuff(pcap_t *p, int dim)
    139 {
    140 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    141 	    "The kernel buffer size cannot be set while reading from a file");
    142 	return (-1);
    143 }
    144 
    145 static int
    146 sf_setmode(pcap_t *p, int mode)
    147 {
    148 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    149 	    "impossible to set mode while reading from a file");
    150 	return (-1);
    151 }
    152 
    153 static int
    154 sf_setmintocopy(pcap_t *p, int size)
    155 {
    156 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    157 	    "The mintocopy parameter cannot be set while reading from a file");
    158 	return (-1);
    159 }
    160 
    161 static HANDLE
    162 sf_getevent(pcap_t *pcap)
    163 {
    164 	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
    165 	    "The read event cannot be retrieved while reading from a file");
    166 	return (INVALID_HANDLE_VALUE);
    167 }
    168 
    169 static int
    170 sf_oid_get_request(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_,
    171     size_t *lenp _U_)
    172 {
    173 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    174 	    "An OID get request cannot be performed on a file");
    175 	return (PCAP_ERROR);
    176 }
    177 
    178 static int
    179 sf_oid_set_request(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
    180     size_t *lenp _U_)
    181 {
    182 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    183 	    "An OID set request cannot be performed on a file");
    184 	return (PCAP_ERROR);
    185 }
    186 
    187 static u_int
    188 sf_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue, int sync)
    189 {
    190 	strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
    191 	    PCAP_ERRBUF_SIZE);
    192 	return (0);
    193 }
    194 
    195 static int
    196 sf_setuserbuffer(pcap_t *p, int size)
    197 {
    198 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    199 	    "The user buffer cannot be set when reading from a file");
    200 	return (-1);
    201 }
    202 
    203 static int
    204 sf_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks)
    205 {
    206 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    207 	    "Live packet dumping cannot be performed when reading from a file");
    208 	return (-1);
    209 }
    210 
    211 static int
    212 sf_live_dump_ended(pcap_t *p, int sync)
    213 {
    214 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    215 	    "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
    216 	return (-1);
    217 }
    218 
    219 static PAirpcapHandle
    220 sf_get_airpcap_handle(pcap_t *pcap)
    221 {
    222 	return (NULL);
    223 }
    224 #endif
    225 
    226 static int
    227 sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
    228 {
    229 	strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
    230 	    PCAP_ERRBUF_SIZE);
    231 	return (-1);
    232 }
    233 
    234 /*
    235  * Set direction flag: Which packets do we accept on a forwarding
    236  * single device? IN, OUT or both?
    237  */
    238 static int
    239 sf_setdirection(pcap_t *p, pcap_direction_t d)
    240 {
    241 	pcap_snprintf(p->errbuf, sizeof(p->errbuf),
    242 	    "Setting direction is not supported on savefiles");
    243 	return (-1);
    244 }
    245 
    246 void
    247 sf_cleanup(pcap_t *p)
    248 {
    249 	if (p->rfile != stdin)
    250 		(void)fclose(p->rfile);
    251 	if (p->buffer != NULL)
    252 		free(p->buffer);
    253 	pcap_freecode(&p->fcode);
    254 }
    255 
    256 /*
    257 * fopen's safe version on Windows.
    258 */
    259 #ifdef _MSC_VER
    260 FILE *fopen_safe(const char *filename, const char* mode)
    261 {
    262 	FILE *fp = NULL;
    263 	errno_t errno;
    264 	errno = fopen_s(&fp, filename, mode);
    265 	if (errno == 0)
    266 		return fp;
    267 	else
    268 		return NULL;
    269 }
    270 #endif
    271 
    272 pcap_t *
    273 pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
    274 					char *errbuf)
    275 {
    276 	FILE *fp;
    277 	pcap_t *p;
    278 
    279 	if (fname == NULL) {
    280 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
    281 		    "A null pointer was supplied as the file name");
    282 		return (NULL);
    283 	}
    284 	if (fname[0] == '-' && fname[1] == '\0')
    285 	{
    286 		fp = stdin;
    287 #if defined(_WIN32) || defined(MSDOS)
    288 		/*
    289 		 * We're reading from the standard input, so put it in binary
    290 		 * mode, as savefiles are binary files.
    291 		 */
    292 		SET_BINMODE(fp);
    293 #endif
    294 	}
    295 	else {
    296 #if !defined(_WIN32) && !defined(MSDOS)
    297 		fp = fopen(fname, "r");
    298 #else
    299 		fp = fopen(fname, "rb");
    300 #endif
    301 		if (fp == NULL) {
    302 			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
    303 			    pcap_strerror(errno));
    304 			return (NULL);
    305 		}
    306 	}
    307 	p = pcap_fopen_offline_with_tstamp_precision(fp, precision, errbuf);
    308 	if (p == NULL) {
    309 		if (fp != stdin)
    310 			fclose(fp);
    311 	}
    312 	return (p);
    313 }
    314 
    315 pcap_t *
    316 pcap_open_offline(const char *fname, char *errbuf)
    317 {
    318 	return (pcap_open_offline_with_tstamp_precision(fname,
    319 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf));
    320 }
    321 
    322 #ifdef _WIN32
    323 pcap_t* pcap_hopen_offline_with_tstamp_precision(intptr_t osfd, u_int precision,
    324     char *errbuf)
    325 {
    326 	int fd;
    327 	FILE *file;
    328 
    329 	fd = _open_osfhandle(osfd, _O_RDONLY);
    330 	if ( fd < 0 )
    331 	{
    332 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
    333 		return NULL;
    334 	}
    335 
    336 	file = _fdopen(fd, "rb");
    337 	if ( file == NULL )
    338 	{
    339 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
    340 		return NULL;
    341 	}
    342 
    343 	return pcap_fopen_offline_with_tstamp_precision(file, precision,
    344 	    errbuf);
    345 }
    346 
    347 pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
    348 {
    349 	return pcap_hopen_offline_with_tstamp_precision(osfd,
    350 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf);
    351 }
    352 #endif
    353 
    354 static pcap_t *(*check_headers[])(bpf_u_int32, FILE *, u_int, char *, int *) = {
    355 	pcap_check_header,
    356 	pcap_ng_check_header
    357 };
    358 
    359 #define	N_FILE_TYPES	(sizeof check_headers / sizeof check_headers[0])
    360 
    361 #ifdef _WIN32
    362 static
    363 #endif
    364 pcap_t *
    365 pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision,
    366     char *errbuf)
    367 {
    368 	register pcap_t *p;
    369 	bpf_u_int32 magic;
    370 	size_t amt_read;
    371 	u_int i;
    372 	int err;
    373 
    374 	/*
    375 	 * Read the first 4 bytes of the file; the network analyzer dump
    376 	 * file formats we support (pcap and pcap-ng), and several other
    377 	 * formats we might support in the future (such as snoop, DOS and
    378 	 * Windows Sniffer, and Microsoft Network Monitor) all have magic
    379 	 * numbers that are unique in their first 4 bytes.
    380 	 */
    381 	amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
    382 	if (amt_read != sizeof(magic)) {
    383 		if (ferror(fp)) {
    384 			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
    385 			    "error reading dump file: %s",
    386 			    pcap_strerror(errno));
    387 		} else {
    388 			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
    389 			    "truncated dump file; tried to read %lu file header bytes, only got %lu",
    390 			    (unsigned long)sizeof(magic),
    391 			    (unsigned long)amt_read);
    392 		}
    393 		return (NULL);
    394 	}
    395 
    396 	/*
    397 	 * Try all file types.
    398 	 */
    399 	for (i = 0; i < N_FILE_TYPES; i++) {
    400 		p = (*check_headers[i])(magic, fp, precision, errbuf, &err);
    401 		if (p != NULL) {
    402 			/* Yup, that's it. */
    403 			goto found;
    404 		}
    405 		if (err) {
    406 			/*
    407 			 * Error trying to read the header.
    408 			 */
    409 			return (NULL);
    410 		}
    411 	}
    412 
    413 	/*
    414 	 * Well, who knows what this mess is....
    415 	 */
    416 	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
    417 	return (NULL);
    418 
    419 found:
    420 	p->rfile = fp;
    421 
    422 	/* Padding only needed for live capture fcode */
    423 	p->fddipad = 0;
    424 
    425 #if !defined(_WIN32) && !defined(MSDOS)
    426 	/*
    427 	 * You can do "select()" and "poll()" on plain files on most
    428 	 * platforms, and should be able to do so on pipes.
    429 	 *
    430 	 * You can't do "select()" on anything other than sockets in
    431 	 * Windows, so, on Win32 systems, we don't have "selectable_fd".
    432 	 */
    433 	p->selectable_fd = fileno(fp);
    434 #endif
    435 
    436 	p->read_op = pcap_offline_read;
    437 	p->inject_op = sf_inject;
    438 	p->setfilter_op = install_bpf_program;
    439 	p->setdirection_op = sf_setdirection;
    440 	p->set_datalink_op = NULL;	/* we don't support munging link-layer headers */
    441 	p->getnonblock_op = sf_getnonblock;
    442 	p->setnonblock_op = sf_setnonblock;
    443 	p->stats_op = sf_stats;
    444 #ifdef _WIN32
    445 	p->stats_ex_op = sf_stats_ex;
    446 	p->setbuff_op = sf_setbuff;
    447 	p->setmode_op = sf_setmode;
    448 	p->setmintocopy_op = sf_setmintocopy;
    449 	p->getevent_op = sf_getevent;
    450 	p->oid_get_request_op = sf_oid_get_request;
    451 	p->oid_set_request_op = sf_oid_set_request;
    452 	p->sendqueue_transmit_op = sf_sendqueue_transmit;
    453 	p->setuserbuffer_op = sf_setuserbuffer;
    454 	p->live_dump_op = sf_live_dump;
    455 	p->live_dump_ended_op = sf_live_dump_ended;
    456 	p->get_airpcap_handle_op = sf_get_airpcap_handle;
    457 #endif
    458 
    459 	/*
    460 	 * For offline captures, the standard one-shot callback can
    461 	 * be used for pcap_next()/pcap_next_ex().
    462 	 */
    463 	p->oneshot_callback = pcap_oneshot;
    464 
    465 	/*
    466 	 * Savefiles never require special BPF code generation.
    467 	 */
    468 	p->bpf_codegen_flags = 0;
    469 
    470 	p->activated = 1;
    471 
    472 	return (p);
    473 }
    474 
    475 #ifdef _WIN32
    476 static
    477 #endif
    478 pcap_t *
    479 pcap_fopen_offline(FILE *fp, char *errbuf)
    480 {
    481 	return (pcap_fopen_offline_with_tstamp_precision(fp,
    482 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf));
    483 }
    484 
    485 /*
    486  * Read packets from a capture file, and call the callback for each
    487  * packet.
    488  * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
    489  */
    490 int
    491 pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
    492 {
    493 	struct bpf_insn *fcode;
    494 	int status = 0;
    495 	int n = 0;
    496 	u_char *data;
    497 
    498 	while (status == 0) {
    499 		struct pcap_pkthdr h;
    500 
    501 		/*
    502 		 * Has "pcap_breakloop()" been called?
    503 		 * If so, return immediately - if we haven't read any
    504 		 * packets, clear the flag and return -2 to indicate
    505 		 * that we were told to break out of the loop, otherwise
    506 		 * leave the flag set, so that the *next* call will break
    507 		 * out of the loop without having read any packets, and
    508 		 * return the number of packets we've processed so far.
    509 		 */
    510 		if (p->break_loop) {
    511 			if (n == 0) {
    512 				p->break_loop = 0;
    513 				return (-2);
    514 			} else
    515 				return (n);
    516 		}
    517 
    518 		status = p->next_packet_op(p, &h, &data);
    519 		if (status) {
    520 			if (status == 1)
    521 				return (0);
    522 			return (status);
    523 		}
    524 
    525 		if ((fcode = p->fcode.bf_insns) == NULL ||
    526 		    bpf_filter(fcode, data, h.len, h.caplen)) {
    527 			(*callback)(user, &h, data);
    528 			if (++n >= cnt && cnt > 0)
    529 				break;
    530 		}
    531 	}
    532 	/*XXX this breaks semantics tcpslice expects */
    533 	return (n);
    534 }
    535