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