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 #include "pcap/usb.h"
     57 
     58 #ifdef HAVE_OS_PROTO_H
     59 #include "os-proto.h"
     60 #endif
     61 
     62 #include "sf-pcap.h"
     63 #include "sf-pcap-ng.h"
     64 
     65 /*
     66  * Setting O_BINARY on DOS/Windows is a bit tricky
     67  */
     68 #if defined(WIN32)
     69   #define SET_BINMODE(f)  _setmode(_fileno(f), _O_BINARY)
     70 #elif defined(MSDOS)
     71   #if defined(__HIGHC__)
     72   #define SET_BINMODE(f)  setmode(f, O_BINARY)
     73   #else
     74   #define SET_BINMODE(f)  setmode(fileno(f), O_BINARY)
     75   #endif
     76 #endif
     77 
     78 static int
     79 sf_getnonblock(pcap_t *p, char *errbuf)
     80 {
     81 	/*
     82 	 * This is a savefile, not a live capture file, so never say
     83 	 * it's in non-blocking mode.
     84 	 */
     85 	return (0);
     86 }
     87 
     88 static int
     89 sf_setnonblock(pcap_t *p, int nonblock, char *errbuf)
     90 {
     91 	/*
     92 	 * This is a savefile, not a live capture file, so reject
     93 	 * requests to put it in non-blocking mode.  (If it's a
     94 	 * pipe, it could be put in non-blocking mode, but that
     95 	 * would significantly complicate the code to read packets,
     96 	 * as it would have to handle reading partial packets and
     97 	 * keeping the state of the read.)
     98 	 */
     99 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    100 	    "Savefiles cannot be put into non-blocking mode");
    101 	return (-1);
    102 }
    103 
    104 static int
    105 sf_stats(pcap_t *p, struct pcap_stat *ps)
    106 {
    107 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    108 	    "Statistics aren't available from savefiles");
    109 	return (-1);
    110 }
    111 
    112 #ifdef WIN32
    113 static int
    114 sf_setbuff(pcap_t *p, int dim)
    115 {
    116 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    117 	    "The kernel buffer size cannot be set while reading from a file");
    118 	return (-1);
    119 }
    120 
    121 static int
    122 sf_setmode(pcap_t *p, int mode)
    123 {
    124 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    125 	    "impossible to set mode while reading from a file");
    126 	return (-1);
    127 }
    128 
    129 static int
    130 sf_setmintocopy(pcap_t *p, int size)
    131 {
    132 	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    133 	    "The mintocopy parameter cannot be set while reading from a file");
    134 	return (-1);
    135 }
    136 #endif
    137 
    138 static int
    139 sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
    140 {
    141 	strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
    142 	    PCAP_ERRBUF_SIZE);
    143 	return (-1);
    144 }
    145 
    146 /*
    147  * Set direction flag: Which packets do we accept on a forwarding
    148  * single device? IN, OUT or both?
    149  */
    150 static int
    151 sf_setdirection(pcap_t *p, pcap_direction_t d)
    152 {
    153 	snprintf(p->errbuf, sizeof(p->errbuf),
    154 	    "Setting direction is not supported on savefiles");
    155 	return (-1);
    156 }
    157 
    158 void
    159 sf_cleanup(pcap_t *p)
    160 {
    161 	if (p->rfile != stdin)
    162 		(void)fclose(p->rfile);
    163 	if (p->buffer != NULL)
    164 		free(p->buffer);
    165 	pcap_freecode(&p->fcode);
    166 }
    167 
    168 pcap_t *
    169 pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
    170     char *errbuf)
    171 {
    172 	FILE *fp;
    173 	pcap_t *p;
    174 
    175 	if (fname[0] == '-' && fname[1] == '\0')
    176 	{
    177 		fp = stdin;
    178 #if defined(WIN32) || defined(MSDOS)
    179 		/*
    180 		 * We're reading from the standard input, so put it in binary
    181 		 * mode, as savefiles are binary files.
    182 		 */
    183 		SET_BINMODE(fp);
    184 #endif
    185 	}
    186 	else {
    187 #if !defined(WIN32) && !defined(MSDOS)
    188 		fp = fopen(fname, "r");
    189 #else
    190 		fp = fopen(fname, "rb");
    191 #endif
    192 		if (fp == NULL) {
    193 			snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
    194 			    pcap_strerror(errno));
    195 			return (NULL);
    196 		}
    197 	}
    198 	p = pcap_fopen_offline_with_tstamp_precision(fp, precision, errbuf);
    199 	if (p == NULL) {
    200 		if (fp != stdin)
    201 			fclose(fp);
    202 	}
    203 	return (p);
    204 }
    205 
    206 pcap_t *
    207 pcap_open_offline(const char *fname, char *errbuf)
    208 {
    209 	return (pcap_open_offline_with_tstamp_precision(fname,
    210 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf));
    211 }
    212 
    213 #ifdef WIN32
    214 pcap_t* pcap_hopen_offline_with_tstamp_precision(intptr_t osfd, u_int precision,
    215     char *errbuf)
    216 {
    217 	int fd;
    218 	FILE *file;
    219 
    220 	fd = _open_osfhandle(osfd, _O_RDONLY);
    221 	if ( fd < 0 )
    222 	{
    223 		snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
    224 		return NULL;
    225 	}
    226 
    227 	file = _fdopen(fd, "rb");
    228 	if ( file == NULL )
    229 	{
    230 		snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
    231 		return NULL;
    232 	}
    233 
    234 	return pcap_fopen_offline_with_tstamp_precision(file, precision,
    235 	    errbuf);
    236 }
    237 
    238 pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
    239 {
    240 	return pcap_hopen_offline_with_tstamp_precision(osfd,
    241 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf);
    242 }
    243 #endif
    244 
    245 static pcap_t *(*check_headers[])(bpf_u_int32, FILE *, u_int, char *, int *) = {
    246 	pcap_check_header,
    247 	pcap_ng_check_header
    248 };
    249 
    250 #define	N_FILE_TYPES	(sizeof check_headers / sizeof check_headers[0])
    251 
    252 #ifdef WIN32
    253 static
    254 #endif
    255 pcap_t *
    256 pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision,
    257     char *errbuf)
    258 {
    259 	register pcap_t *p;
    260 	bpf_u_int32 magic;
    261 	size_t amt_read;
    262 	u_int i;
    263 	int err;
    264 
    265 	/*
    266 	 * Read the first 4 bytes of the file; the network analyzer dump
    267 	 * file formats we support (pcap and pcap-ng), and several other
    268 	 * formats we might support in the future (such as snoop, DOS and
    269 	 * Windows Sniffer, and Microsoft Network Monitor) all have magic
    270 	 * numbers that are unique in their first 4 bytes.
    271 	 */
    272 	amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
    273 	if (amt_read != sizeof(magic)) {
    274 		if (ferror(fp)) {
    275 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
    276 			    "error reading dump file: %s",
    277 			    pcap_strerror(errno));
    278 		} else {
    279 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
    280 			    "truncated dump file; tried to read %lu file header bytes, only got %lu",
    281 			    (unsigned long)sizeof(magic),
    282 			    (unsigned long)amt_read);
    283 		}
    284 		return (NULL);
    285 	}
    286 
    287 	/*
    288 	 * Try all file types.
    289 	 */
    290 	for (i = 0; i < N_FILE_TYPES; i++) {
    291 		p = (*check_headers[i])(magic, fp, precision, errbuf, &err);
    292 		if (p != NULL) {
    293 			/* Yup, that's it. */
    294 			goto found;
    295 		}
    296 		if (err) {
    297 			/*
    298 			 * Error trying to read the header.
    299 			 */
    300 			return (NULL);
    301 		}
    302 	}
    303 
    304 	/*
    305 	 * Well, who knows what this mess is....
    306 	 */
    307 	snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
    308 	return (NULL);
    309 
    310 found:
    311 	p->rfile = fp;
    312 
    313 	/* Padding only needed for live capture fcode */
    314 	p->fddipad = 0;
    315 
    316 #if !defined(WIN32) && !defined(MSDOS)
    317 	/*
    318 	 * You can do "select()" and "poll()" on plain files on most
    319 	 * platforms, and should be able to do so on pipes.
    320 	 *
    321 	 * You can't do "select()" on anything other than sockets in
    322 	 * Windows, so, on Win32 systems, we don't have "selectable_fd".
    323 	 */
    324 	p->selectable_fd = fileno(fp);
    325 #endif
    326 
    327 	p->read_op = pcap_offline_read;
    328 	p->inject_op = sf_inject;
    329 	p->setfilter_op = install_bpf_program;
    330 	p->setdirection_op = sf_setdirection;
    331 	p->set_datalink_op = NULL;	/* we don't support munging link-layer headers */
    332 	p->getnonblock_op = sf_getnonblock;
    333 	p->setnonblock_op = sf_setnonblock;
    334 	p->stats_op = sf_stats;
    335 #ifdef WIN32
    336 	p->setbuff_op = sf_setbuff;
    337 	p->setmode_op = sf_setmode;
    338 	p->setmintocopy_op = sf_setmintocopy;
    339 #endif
    340 
    341 	/*
    342 	 * For offline captures, the standard one-shot callback can
    343 	 * be used for pcap_next()/pcap_next_ex().
    344 	 */
    345 	p->oneshot_callback = pcap_oneshot;
    346 
    347 	/*
    348 	 * Savefiles never require special BPF code generation.
    349 	 */
    350 	p->bpf_codegen_flags = 0;
    351 
    352 	p->activated = 1;
    353 
    354 	return (p);
    355 }
    356 
    357 #ifdef WIN32
    358 static
    359 #endif
    360 pcap_t *
    361 pcap_fopen_offline(FILE *fp, char *errbuf)
    362 {
    363 	return (pcap_fopen_offline_with_tstamp_precision(fp,
    364 	    PCAP_TSTAMP_PRECISION_MICRO, errbuf));
    365 }
    366 
    367 /*
    368  * Read packets from a capture file, and call the callback for each
    369  * packet.
    370  * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
    371  */
    372 int
    373 pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
    374 {
    375 	struct bpf_insn *fcode;
    376 	int status = 0;
    377 	int n = 0;
    378 	u_char *data;
    379 
    380 	while (status == 0) {
    381 		struct pcap_pkthdr h;
    382 
    383 		/*
    384 		 * Has "pcap_breakloop()" been called?
    385 		 * If so, return immediately - if we haven't read any
    386 		 * packets, clear the flag and return -2 to indicate
    387 		 * that we were told to break out of the loop, otherwise
    388 		 * leave the flag set, so that the *next* call will break
    389 		 * out of the loop without having read any packets, and
    390 		 * return the number of packets we've processed so far.
    391 		 */
    392 		if (p->break_loop) {
    393 			if (n == 0) {
    394 				p->break_loop = 0;
    395 				return (-2);
    396 			} else
    397 				return (n);
    398 		}
    399 
    400 		status = p->next_packet_op(p, &h, &data);
    401 		if (status) {
    402 			if (status == 1)
    403 				return (0);
    404 			return (status);
    405 		}
    406 
    407 		if ((fcode = p->fcode.bf_insns) == NULL ||
    408 		    bpf_filter(fcode, data, h.len, h.caplen)) {
    409 			(*callback)(user, &h, data);
    410 			if (++n >= cnt && cnt > 0)
    411 				break;
    412 		}
    413 	}
    414 	/*XXX this breaks semantics tcpslice expects */
    415 	return (n);
    416 }
    417