1279377Simp/* 2279377Simp * Copyright (c) 1993, 1994, 1995, 1996, 1997 3279377Simp * The Regents of the University of California. All rights reserved. 4279377Simp * 5279377Simp * Redistribution and use in source and binary forms, with or without 6279377Simp * modification, are permitted provided that: (1) source code distributions 7279377Simp * retain the above copyright notice and this paragraph in its entirety, (2) 8279377Simp * distributions including binary code include the above copyright notice and 9279377Simp * this paragraph in its entirety in the documentation or other materials 10279377Simp * provided with the distribution, and (3) all advertising materials mentioning 11279377Simp * features or use of this software display the following acknowledgement: 12279377Simp * ``This product includes software developed by the University of California, 13279377Simp * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14279377Simp * the University nor the names of its contributors may be used to endorse 15279377Simp * or promote products derived from this software without specific prior 16279377Simp * written permission. 17279377Simp * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18279377Simp * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19279377Simp * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20279377Simp * 21279377Simp * savefile.c - supports offline use of tcpdump 22279377Simp * Extraction/creation by Jeffrey Mogul, DECWRL 23279377Simp * Modified by Steve McCanne, LBL. 24279377Simp * 25279377Simp * Used to save the received packet headers, after filtering, to 26279377Simp * a file, and then read them later. 27279377Simp * The first record in the file contains saved values for the machine 28279377Simp * dependent values so we can print the dump file on any architecture. 29279377Simp */ 30279377Simp 31279377Simp#ifndef lint 32279377Simpstatic const char rcsid[] _U_ = 33279377Simp "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.183 2008-12-23 20:13:29 guy Exp $ (LBL)"; 34279377Simp#endif 35279377Simp 36279377Simp#ifdef HAVE_CONFIG_H 37279377Simp#include "config.h" 38279377Simp#endif 39279377Simp 40279377Simp#ifdef WIN32 41279377Simp#include <pcap-stdinc.h> 42279377Simp#else /* WIN32 */ 43279377Simp#if HAVE_INTTYPES_H 44279377Simp#include <inttypes.h> 45279377Simp#elif HAVE_STDINT_H 46295436Sandrew#include <stdint.h> 47295436Sandrew#endif 48295436Sandrew#ifdef HAVE_SYS_BITYPES_H 49295436Sandrew#include <sys/bitypes.h> 50295436Sandrew#endif 51295436Sandrew#include <sys/types.h> 52295436Sandrew#endif /* WIN32 */ 53295436Sandrew 54279377Simp#include <errno.h> 55279377Simp#include <memory.h> 56279377Simp#include <stdio.h> 57279377Simp#include <stdlib.h> 58279377Simp#include <string.h> 59279377Simp 60279377Simp#include "pcap-int.h" 61279377Simp#include "pcap/usb.h" 62279377Simp 63279377Simp#ifdef HAVE_OS_PROTO_H 64279377Simp#include "os-proto.h" 65279377Simp#endif 66279377Simp 67279377Simp#include "sf-pcap.h" 68279377Simp#include "sf-pcap-ng.h" 69279377Simp 70279377Simp/* 71279377Simp * Setting O_BINARY on DOS/Windows is a bit tricky 72279377Simp */ 73279377Simp#if defined(WIN32) 74279377Simp #define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY) 75279377Simp#elif defined(MSDOS) 76279377Simp #if defined(__HIGHC__) 77279377Simp #define SET_BINMODE(f) setmode(f, O_BINARY) 78279377Simp #else 79279377Simp #define SET_BINMODE(f) setmode(fileno(f), O_BINARY) 80279377Simp #endif 81279377Simp#endif 82279377Simp 83279377Simpstatic int 84279377Simpsf_getnonblock(pcap_t *p, char *errbuf) 85279377Simp{ 86279377Simp /* 87279377Simp * This is a savefile, not a live capture file, so never say 88279377Simp * it's in non-blocking mode. 89279377Simp */ 90279377Simp return (0); 91279377Simp} 92279377Simp 93279377Simpstatic int 94279377Simpsf_setnonblock(pcap_t *p, int nonblock, char *errbuf) 95279377Simp{ 96279377Simp /* 97279377Simp * This is a savefile, not a live capture file, so reject 98279377Simp * requests to put it in non-blocking mode. (If it's a 99279377Simp * pipe, it could be put in non-blocking mode, but that 100279377Simp * would significantly complicate the code to read packets, 101279377Simp * as it would have to handle reading partial packets and 102279377Simp * keeping the state of the read.) 103279377Simp */ 104279377Simp snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 105279377Simp "Savefiles cannot be put into non-blocking mode"); 106279377Simp return (-1); 107279377Simp} 108279377Simp 109279377Simpstatic int 110279377Simpsf_stats(pcap_t *p, struct pcap_stat *ps) 111279377Simp{ 112279377Simp snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 113279377Simp "Statistics aren't available from savefiles"); 114279377Simp return (-1); 115279377Simp} 116279377Simp 117279377Simp#ifdef WIN32 118279377Simpstatic int 119279377Simpsf_setbuff(pcap_t *p, int dim) 120279377Simp{ 121279377Simp snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 122279377Simp "The kernel buffer size cannot be set while reading from a file"); 123279377Simp return (-1); 124279377Simp} 125279377Simp 126279377Simpstatic int 127279377Simpsf_setmode(pcap_t *p, int mode) 128279377Simp{ 129279377Simp snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 130279377Simp "impossible to set mode while reading from a file"); 131279377Simp return (-1); 132279377Simp} 133279377Simp 134279377Simpstatic int 135279377Simpsf_setmintocopy(pcap_t *p, int size) 136279377Simp{ 137279377Simp snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 138279377Simp "The mintocopy parameter cannot be set while reading from a file"); 139279377Simp return (-1); 140279377Simp} 141279377Simp#endif 142279377Simp 143279377Simpstatic int 144279377Simpsf_inject(pcap_t *p, const void *buf _U_, size_t size _U_) 145279377Simp{ 146279377Simp strlcpy(p->errbuf, "Sending packets isn't supported on savefiles", 147279377Simp PCAP_ERRBUF_SIZE); 148279377Simp return (-1); 149279377Simp} 150279377Simp 151279377Simp/* 152279377Simp * Set direction flag: Which packets do we accept on a forwarding 153279377Simp * single device? IN, OUT or both? 154279377Simp */ 155279377Simpstatic int 156279377Simpsf_setdirection(pcap_t *p, pcap_direction_t d) 157279377Simp{ 158279377Simp snprintf(p->errbuf, sizeof(p->errbuf), 159279377Simp "Setting direction is not supported on savefiles"); 160279377Simp return (-1); 161279377Simp} 162279377Simp 163279377Simpstatic void 164279377Simpsf_cleanup(pcap_t *p) 165279377Simp{ 166279377Simp if (p->sf.rfile != stdin) 167279377Simp (void)fclose(p->sf.rfile); 168279377Simp if (p->buffer != NULL) 169279377Simp free(p->buffer); 170279377Simp pcap_freecode(&p->fcode); 171279377Simp} 172279377Simp 173279377Simppcap_t * 174279377Simppcap_open_offline(const char *fname, char *errbuf) 175279377Simp{ 176279377Simp FILE *fp; 177279377Simp pcap_t *p; 178279377Simp 179279377Simp if (fname[0] == '-' && fname[1] == '\0') 180279377Simp { 181279377Simp fp = stdin; 182279377Simp#if defined(WIN32) || defined(MSDOS) 183279377Simp /* 184279377Simp * We're reading from the standard input, so put it in binary 185279377Simp * mode, as savefiles are binary files. 186279377Simp */ 187279377Simp SET_BINMODE(fp); 188279377Simp#endif 189279377Simp } 190279377Simp else { 191279377Simp#if !defined(WIN32) && !defined(MSDOS) 192279377Simp fp = fopen(fname, "r"); 193279377Simp#else 194279377Simp fp = fopen(fname, "rb"); 195279377Simp#endif 196279377Simp if (fp == NULL) { 197279377Simp snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, 198279377Simp pcap_strerror(errno)); 199279377Simp return (NULL); 200279377Simp } 201279377Simp } 202279377Simp p = pcap_fopen_offline(fp, errbuf); 203279377Simp if (p == NULL) { 204279377Simp if (fp != stdin) 205279377Simp fclose(fp); 206279377Simp } 207279377Simp return (p); 208279377Simp} 209279377Simp 210279377Simp#ifdef WIN32 211279377Simppcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf) 212279377Simp{ 213279377Simp int fd; 214279377Simp FILE *file; 215279377Simp 216279377Simp fd = _open_osfhandle(osfd, _O_RDONLY); 217279377Simp if ( fd < 0 ) 218279377Simp { 219279377Simp snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno)); 220279377Simp return NULL; 221279377Simp } 222279377Simp 223279377Simp file = _fdopen(fd, "rb"); 224279377Simp if ( file == NULL ) 225279377Simp { 226279377Simp snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno)); 227279377Simp return NULL; 228279377Simp } 229279377Simp 230279377Simp return pcap_fopen_offline(file, errbuf); 231279377Simp} 232279377Simp#endif 233279377Simp 234279377Simpstatic int (*check_headers[])(pcap_t *, bpf_u_int32, FILE *, char *) = { 235279377Simp pcap_check_header, 236279377Simp pcap_ng_check_header 237279377Simp}; 238279377Simp 239279377Simp#define N_FILE_TYPES (sizeof check_headers / sizeof check_headers[0]) 240279377Simp 241279377Simp#ifdef WIN32 242279377Simpstatic 243279377Simp#endif 244279377Simppcap_t * 245279377Simppcap_fopen_offline(FILE *fp, char *errbuf) 246279377Simp{ 247279377Simp register pcap_t *p; 248279377Simp bpf_u_int32 magic; 249279377Simp size_t amt_read; 250279377Simp u_int i; 251279377Simp 252279377Simp p = pcap_create_common("(savefile)", errbuf); 253279377Simp if (p == NULL) 254279377Simp return (NULL); 255279377Simp 256279377Simp /* 257279377Simp * Read the first 4 bytes of the file; the network analyzer dump 258279377Simp * file formats we support (pcap and pcap-ng), and several other 259279377Simp * formats we might support in the future (such as snoop, DOS and 260279377Simp * Windows Sniffer, and Microsoft Network Monitor) all have magic 261279377Simp * numbers that are unique in their first 4 bytes. 262279377Simp */ 263279377Simp amt_read = fread((char *)&magic, 1, sizeof(magic), fp); 264279377Simp if (amt_read != sizeof(magic)) { 265279377Simp if (ferror(fp)) { 266279377Simp snprintf(errbuf, PCAP_ERRBUF_SIZE, 267279377Simp "error reading dump file: %s", 268279377Simp pcap_strerror(errno)); 269279377Simp } else { 270279377Simp snprintf(errbuf, PCAP_ERRBUF_SIZE, 271279377Simp "truncated dump file; tried to read %lu file header bytes, only got %lu", 272279377Simp (unsigned long)sizeof(magic), 273279377Simp (unsigned long)amt_read); 274279377Simp } 275279377Simp goto bad; 276279377Simp } 277279377Simp 278279377Simp /* 279279377Simp * Try all file types. 280279377Simp */ 281279377Simp for (i = 0; i < N_FILE_TYPES; i++) { 282279377Simp switch ((*check_headers[i])(p, magic, fp, errbuf)) { 283279377Simp 284279377Simp case -1: 285279377Simp /* 286279377Simp * Error trying to read the header. 287279377Simp */ 288279377Simp goto bad; 289279377Simp 290279377Simp case 1: 291279377Simp /* 292279377Simp * Yup, that's it. 293279377Simp */ 294279377Simp goto found; 295279377Simp } 296279377Simp } 297279377Simp 298279377Simp /* 299279377Simp * Well, who knows what this mess is.... 300279377Simp */ 301279377Simp snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format"); 302279377Simp goto bad; 303279377Simp 304279377Simpfound: 305279377Simp p->sf.rfile = fp; 306279377Simp 307279377Simp#ifdef PCAP_FDDIPAD 308279377Simp /* Padding only needed for live capture fcode */ 309279377Simp p->fddipad = 0; 310279377Simp#endif 311279377Simp 312279377Simp#if !defined(WIN32) && !defined(MSDOS) 313279377Simp /* 314279377Simp * You can do "select()" and "poll()" on plain files on most 315279377Simp * platforms, and should be able to do so on pipes. 316279377Simp * 317279377Simp * You can't do "select()" on anything other than sockets in 318279377Simp * Windows, so, on Win32 systems, we don't have "selectable_fd". 319279377Simp */ 320279377Simp p->selectable_fd = fileno(fp); 321279377Simp#endif 322279377Simp 323279377Simp p->read_op = pcap_offline_read; 324279377Simp p->inject_op = sf_inject; 325279377Simp p->setfilter_op = install_bpf_program; 326279377Simp p->setdirection_op = sf_setdirection; 327279377Simp p->set_datalink_op = NULL; /* we don't support munging link-layer headers */ 328279377Simp p->getnonblock_op = sf_getnonblock; 329279377Simp p->setnonblock_op = sf_setnonblock; 330279377Simp p->stats_op = sf_stats; 331279377Simp#ifdef WIN32 332279377Simp p->setbuff_op = sf_setbuff; 333279377Simp p->setmode_op = sf_setmode; 334279377Simp p->setmintocopy_op = sf_setmintocopy; 335279377Simp#endif 336279377Simp p->cleanup_op = sf_cleanup; 337279377Simp p->activated = 1; 338279377Simp 339279377Simp return (p); 340279377Simp bad: 341279377Simp free(p); 342279377Simp return (NULL); 343279377Simp} 344279377Simp 345279377Simp/* 346279377Simp * Read packets from a capture file, and call the callback for each 347279377Simp * packet. 348279377Simp * If cnt > 0, return after 'cnt' packets, otherwise continue until eof. 349279377Simp */ 350279377Simpint 351279377Simppcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 352279377Simp{ 353279377Simp struct bpf_insn *fcode; 354279377Simp int status = 0; 355279377Simp int n = 0; 356279377Simp u_char *data; 357279377Simp 358279377Simp while (status == 0) { 359279377Simp struct pcap_pkthdr h; 360279377Simp 361279377Simp /* 362279377Simp * Has "pcap_breakloop()" been called? 363279377Simp * If so, return immediately - if we haven't read any 364279377Simp * packets, clear the flag and return -2 to indicate 365279377Simp * that we were told to break out of the loop, otherwise 366279377Simp * leave the flag set, so that the *next* call will break 367279377Simp * out of the loop without having read any packets, and 368279377Simp * return the number of packets we've processed so far. 369279377Simp */ 370279377Simp if (p->break_loop) { 371279377Simp if (n == 0) { 372279377Simp p->break_loop = 0; 373279377Simp return (-2); 374279377Simp } else 375279377Simp return (n); 376279377Simp } 377279377Simp 378279377Simp status = p->sf.next_packet_op(p, &h, &data); 379279377Simp if (status) { 380279377Simp if (status == 1) 381279377Simp return (0); 382279377Simp return (status); 383279377Simp } 384279377Simp 385279377Simp if ((fcode = p->fcode.bf_insns) == NULL || 386279377Simp bpf_filter(fcode, data, h.len, h.caplen)) { 387279377Simp (*callback)(user, &h, data); 388279377Simp if (++n >= cnt && cnt > 0) 389279377Simp break; 390279377Simp } 391279377Simp } 392279377Simp /*XXX this breaks semantics tcpslice expects */ 393279377Simp return (n); 394279377Simp} 395279377Simp