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 313052b236SBill Fenner #ifndef lint 32feb4ecdbSBruce M Simpson static const char rcsid[] _U_ = 33a0ee43a1SRui Paulo "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.183 2008-12-23 20:13:29 guy Exp $ (LBL)"; 34dc2c7305SBill Fenner #endif 35dc2c7305SBill Fenner 36dc2c7305SBill Fenner #ifdef HAVE_CONFIG_H 37dc2c7305SBill Fenner #include "config.h" 383052b236SBill Fenner #endif 393052b236SBill Fenner 40a0ee43a1SRui Paulo #ifdef WIN32 41a0ee43a1SRui Paulo #include <pcap-stdinc.h> 42a0ee43a1SRui Paulo #else /* WIN32 */ 43a0ee43a1SRui Paulo #if HAVE_INTTYPES_H 44a0ee43a1SRui Paulo #include <inttypes.h> 45a0ee43a1SRui Paulo #elif HAVE_STDINT_H 46a0ee43a1SRui Paulo #include <stdint.h> 47a0ee43a1SRui Paulo #endif 48a0ee43a1SRui Paulo #ifdef HAVE_SYS_BITYPES_H 49a0ee43a1SRui Paulo #include <sys/bitypes.h> 50a0ee43a1SRui Paulo #endif 51a0ee43a1SRui Paulo #include <sys/types.h> 52a0ee43a1SRui Paulo #endif /* WIN32 */ 53a0ee43a1SRui Paulo 548cf6c252SPaul Traina #include <errno.h> 558cf6c252SPaul Traina #include <memory.h> 568cf6c252SPaul Traina #include <stdio.h> 578cf6c252SPaul Traina #include <stdlib.h> 58dc2c7305SBill Fenner #include <string.h> 598cf6c252SPaul Traina 608cf6c252SPaul Traina #include "pcap-int.h" 61a8e07101SRui Paulo #include "pcap/usb.h" 628cf6c252SPaul Traina 638cf6c252SPaul Traina #ifdef HAVE_OS_PROTO_H 648cf6c252SPaul Traina #include "os-proto.h" 658cf6c252SPaul Traina #endif 668cf6c252SPaul Traina 67a0ee43a1SRui Paulo #include "sf-pcap.h" 68a0ee43a1SRui Paulo #include "sf-pcap-ng.h" 698cf6c252SPaul Traina 70dc2c7305SBill Fenner /* 7104fb2745SSam Leffler * Setting O_BINARY on DOS/Windows is a bit tricky 7204fb2745SSam Leffler */ 7304fb2745SSam Leffler #if defined(WIN32) 74ee2dd488SSam Leffler #define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY) 7504fb2745SSam Leffler #elif defined(MSDOS) 7604fb2745SSam Leffler #if defined(__HIGHC__) 7704fb2745SSam Leffler #define SET_BINMODE(f) setmode(f, O_BINARY) 7804fb2745SSam Leffler #else 7904fb2745SSam Leffler #define SET_BINMODE(f) setmode(fileno(f), O_BINARY) 8004fb2745SSam Leffler #endif 8104fb2745SSam Leffler #endif 8204fb2745SSam Leffler 83feb4ecdbSBruce M Simpson static int 84feb4ecdbSBruce M Simpson sf_getnonblock(pcap_t *p, char *errbuf) 85feb4ecdbSBruce M Simpson { 86feb4ecdbSBruce M Simpson /* 87feb4ecdbSBruce M Simpson * This is a savefile, not a live capture file, so never say 88feb4ecdbSBruce M Simpson * it's in non-blocking mode. 89feb4ecdbSBruce M Simpson */ 90feb4ecdbSBruce M Simpson return (0); 91feb4ecdbSBruce M Simpson } 92feb4ecdbSBruce M Simpson 93feb4ecdbSBruce M Simpson static int 94feb4ecdbSBruce M Simpson sf_setnonblock(pcap_t *p, int nonblock, char *errbuf) 95feb4ecdbSBruce M Simpson { 96feb4ecdbSBruce M Simpson /* 97*d1e87331SXin LI * This is a savefile, not a live capture file, so reject 98*d1e87331SXin LI * requests to put it in non-blocking mode. (If it's a 99*d1e87331SXin LI * pipe, it could be put in non-blocking mode, but that 100*d1e87331SXin LI * would significantly complicate the code to read packets, 101*d1e87331SXin LI * as it would have to handle reading partial packets and 102*d1e87331SXin LI * keeping the state of the read.) 103feb4ecdbSBruce M Simpson */ 104*d1e87331SXin LI snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 105*d1e87331SXin LI "Savefiles cannot be put into non-blocking mode"); 106*d1e87331SXin LI return (-1); 107feb4ecdbSBruce M Simpson } 108feb4ecdbSBruce M Simpson 109feb4ecdbSBruce M Simpson static int 110feb4ecdbSBruce M Simpson sf_stats(pcap_t *p, struct pcap_stat *ps) 111feb4ecdbSBruce M Simpson { 112feb4ecdbSBruce M Simpson snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 113feb4ecdbSBruce M Simpson "Statistics aren't available from savefiles"); 114feb4ecdbSBruce M Simpson return (-1); 115feb4ecdbSBruce M Simpson } 116feb4ecdbSBruce M Simpson 117a8e07101SRui Paulo #ifdef WIN32 118a8e07101SRui Paulo static int 119a8e07101SRui Paulo sf_setbuff(pcap_t *p, int dim) 120a8e07101SRui Paulo { 121a8e07101SRui Paulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 122a8e07101SRui Paulo "The kernel buffer size cannot be set while reading from a file"); 123a8e07101SRui Paulo return (-1); 124a8e07101SRui Paulo } 125a8e07101SRui Paulo 126a8e07101SRui Paulo static int 127a8e07101SRui Paulo sf_setmode(pcap_t *p, int mode) 128a8e07101SRui Paulo { 129a8e07101SRui Paulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 130a8e07101SRui Paulo "impossible to set mode while reading from a file"); 131a8e07101SRui Paulo return (-1); 132a8e07101SRui Paulo } 133a8e07101SRui Paulo 134a8e07101SRui Paulo static int 135a8e07101SRui Paulo sf_setmintocopy(pcap_t *p, int size) 136a8e07101SRui Paulo { 137a8e07101SRui Paulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 138a8e07101SRui Paulo "The mintocopy parameter cannot be set while reading from a file"); 139a8e07101SRui Paulo return (-1); 140a8e07101SRui Paulo } 141a8e07101SRui Paulo #endif 142a8e07101SRui Paulo 14304fb2745SSam Leffler static int 14404fb2745SSam Leffler sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_) 14504fb2745SSam Leffler { 14604fb2745SSam Leffler strlcpy(p->errbuf, "Sending packets isn't supported on savefiles", 14704fb2745SSam Leffler PCAP_ERRBUF_SIZE); 14804fb2745SSam Leffler return (-1); 14904fb2745SSam Leffler } 15004fb2745SSam Leffler 151ee2dd488SSam Leffler /* 152ee2dd488SSam Leffler * Set direction flag: Which packets do we accept on a forwarding 153ee2dd488SSam Leffler * single device? IN, OUT or both? 154ee2dd488SSam Leffler */ 155ee2dd488SSam Leffler static int 1565d18909fSSam Leffler sf_setdirection(pcap_t *p, pcap_direction_t d) 157ee2dd488SSam Leffler { 158ee2dd488SSam Leffler snprintf(p->errbuf, sizeof(p->errbuf), 159ee2dd488SSam Leffler "Setting direction is not supported on savefiles"); 160ee2dd488SSam Leffler return (-1); 161ee2dd488SSam Leffler } 162ee2dd488SSam Leffler 163feb4ecdbSBruce M Simpson static void 164a8e07101SRui Paulo sf_cleanup(pcap_t *p) 165feb4ecdbSBruce M Simpson { 166feb4ecdbSBruce M Simpson if (p->sf.rfile != stdin) 167feb4ecdbSBruce M Simpson (void)fclose(p->sf.rfile); 168a0ee43a1SRui Paulo if (p->buffer != NULL) 169a0ee43a1SRui Paulo free(p->buffer); 170*d1e87331SXin LI pcap_freecode(&p->fcode); 171feb4ecdbSBruce M Simpson } 172feb4ecdbSBruce M Simpson 1738cf6c252SPaul Traina pcap_t * 174a4b5b39fSBill Fenner pcap_open_offline(const char *fname, char *errbuf) 1758cf6c252SPaul Traina { 17604fb2745SSam Leffler FILE *fp; 17704fb2745SSam Leffler pcap_t *p; 17804fb2745SSam Leffler 17904fb2745SSam Leffler if (fname[0] == '-' && fname[1] == '\0') 180ee2dd488SSam Leffler { 18104fb2745SSam Leffler fp = stdin; 182ee2dd488SSam Leffler #if defined(WIN32) || defined(MSDOS) 183ee2dd488SSam Leffler /* 184ee2dd488SSam Leffler * We're reading from the standard input, so put it in binary 185ee2dd488SSam Leffler * mode, as savefiles are binary files. 186ee2dd488SSam Leffler */ 187ee2dd488SSam Leffler SET_BINMODE(fp); 188ee2dd488SSam Leffler #endif 189ee2dd488SSam Leffler } 19004fb2745SSam Leffler else { 19104fb2745SSam Leffler #if !defined(WIN32) && !defined(MSDOS) 19204fb2745SSam Leffler fp = fopen(fname, "r"); 19304fb2745SSam Leffler #else 19404fb2745SSam Leffler fp = fopen(fname, "rb"); 19504fb2745SSam Leffler #endif 19604fb2745SSam Leffler if (fp == NULL) { 19704fb2745SSam Leffler snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, 19804fb2745SSam Leffler pcap_strerror(errno)); 19904fb2745SSam Leffler return (NULL); 20004fb2745SSam Leffler } 20104fb2745SSam Leffler } 20204fb2745SSam Leffler p = pcap_fopen_offline(fp, errbuf); 20304fb2745SSam Leffler if (p == NULL) { 20404fb2745SSam Leffler if (fp != stdin) 20504fb2745SSam Leffler fclose(fp); 20604fb2745SSam Leffler } 20704fb2745SSam Leffler return (p); 20804fb2745SSam Leffler } 20904fb2745SSam Leffler 210a8e07101SRui Paulo #ifdef WIN32 211a8e07101SRui Paulo pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf) 212a8e07101SRui Paulo { 213a8e07101SRui Paulo int fd; 214a8e07101SRui Paulo FILE *file; 215a8e07101SRui Paulo 216a8e07101SRui Paulo fd = _open_osfhandle(osfd, _O_RDONLY); 217a8e07101SRui Paulo if ( fd < 0 ) 218a8e07101SRui Paulo { 219a8e07101SRui Paulo snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno)); 220a8e07101SRui Paulo return NULL; 221a8e07101SRui Paulo } 222a8e07101SRui Paulo 223a8e07101SRui Paulo file = _fdopen(fd, "rb"); 224a8e07101SRui Paulo if ( file == NULL ) 225a8e07101SRui Paulo { 226a8e07101SRui Paulo snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno)); 227a8e07101SRui Paulo return NULL; 228a8e07101SRui Paulo } 229a8e07101SRui Paulo 230a8e07101SRui Paulo return pcap_fopen_offline(file, errbuf); 231a8e07101SRui Paulo } 232a8e07101SRui Paulo #endif 233a8e07101SRui Paulo 234a0ee43a1SRui Paulo static int (*check_headers[])(pcap_t *, bpf_u_int32, FILE *, char *) = { 235a0ee43a1SRui Paulo pcap_check_header, 236a0ee43a1SRui Paulo pcap_ng_check_header 237a0ee43a1SRui Paulo }; 238a0ee43a1SRui Paulo 239a0ee43a1SRui Paulo #define N_FILE_TYPES (sizeof check_headers / sizeof check_headers[0]) 240a0ee43a1SRui Paulo 241a8e07101SRui Paulo #ifdef WIN32 242a8e07101SRui Paulo static 243a8e07101SRui Paulo #endif 24404fb2745SSam Leffler pcap_t * 24504fb2745SSam Leffler pcap_fopen_offline(FILE *fp, char *errbuf) 24604fb2745SSam Leffler { 2478cf6c252SPaul Traina register pcap_t *p; 248dc2c7305SBill Fenner bpf_u_int32 magic; 249a0ee43a1SRui Paulo size_t amt_read; 250a0ee43a1SRui Paulo u_int i; 2518cf6c252SPaul Traina 252a0ee43a1SRui Paulo p = pcap_create_common("(savefile)", errbuf); 253a0ee43a1SRui Paulo if (p == NULL) 2548cf6c252SPaul Traina return (NULL); 2558cf6c252SPaul Traina 256a0ee43a1SRui Paulo /* 257a0ee43a1SRui Paulo * Read the first 4 bytes of the file; the network analyzer dump 258a0ee43a1SRui Paulo * file formats we support (pcap and pcap-ng), and several other 259a0ee43a1SRui Paulo * formats we might support in the future (such as snoop, DOS and 260a0ee43a1SRui Paulo * Windows Sniffer, and Microsoft Network Monitor) all have magic 261a0ee43a1SRui Paulo * numbers that are unique in their first 4 bytes. 262a0ee43a1SRui Paulo */ 263a0ee43a1SRui Paulo amt_read = fread((char *)&magic, 1, sizeof(magic), fp); 264a0ee43a1SRui Paulo if (amt_read != sizeof(magic)) { 26504fb2745SSam Leffler if (ferror(fp)) { 26604fb2745SSam Leffler snprintf(errbuf, PCAP_ERRBUF_SIZE, 26704fb2745SSam Leffler "error reading dump file: %s", 268dc2c7305SBill Fenner pcap_strerror(errno)); 26904fb2745SSam Leffler } else { 27004fb2745SSam Leffler snprintf(errbuf, PCAP_ERRBUF_SIZE, 27104fb2745SSam Leffler "truncated dump file; tried to read %lu file header bytes, only got %lu", 272a0ee43a1SRui Paulo (unsigned long)sizeof(magic), 27304fb2745SSam Leffler (unsigned long)amt_read); 2748cf6c252SPaul Traina } 2758cf6c252SPaul Traina goto bad; 2768cf6c252SPaul Traina } 277a0ee43a1SRui Paulo 278dc2c7305SBill Fenner /* 279a0ee43a1SRui Paulo * Try all file types. 280dc2c7305SBill Fenner */ 281a0ee43a1SRui Paulo for (i = 0; i < N_FILE_TYPES; i++) { 282a0ee43a1SRui Paulo switch ((*check_headers[i])(p, magic, fp, errbuf)) { 283a0ee43a1SRui Paulo 284a0ee43a1SRui Paulo case -1: 285ef96d74fSMax Laier /* 286a0ee43a1SRui Paulo * Error trying to read the header. 287ef96d74fSMax Laier */ 288a0ee43a1SRui Paulo goto bad; 289a0ee43a1SRui Paulo 290a0ee43a1SRui Paulo case 1: 291a0ee43a1SRui Paulo /* 292a0ee43a1SRui Paulo * Yup, that's it. 293a0ee43a1SRui Paulo */ 294a0ee43a1SRui Paulo goto found; 295ef96d74fSMax Laier } 296a0ee43a1SRui Paulo } 297a0ee43a1SRui Paulo 298a0ee43a1SRui Paulo /* 299a0ee43a1SRui Paulo * Well, who knows what this mess is.... 300a0ee43a1SRui Paulo */ 301a0ee43a1SRui Paulo snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format"); 302a0ee43a1SRui Paulo goto bad; 303a0ee43a1SRui Paulo 304a0ee43a1SRui Paulo found: 3058cf6c252SPaul Traina p->sf.rfile = fp; 3068cf6c252SPaul Traina 3078cf6c252SPaul Traina #ifdef PCAP_FDDIPAD 30804fb2745SSam Leffler /* Padding only needed for live capture fcode */ 30904fb2745SSam Leffler p->fddipad = 0; 3108cf6c252SPaul Traina #endif 3118cf6c252SPaul Traina 31204fb2745SSam Leffler #if !defined(WIN32) && !defined(MSDOS) 313feb4ecdbSBruce M Simpson /* 314feb4ecdbSBruce M Simpson * You can do "select()" and "poll()" on plain files on most 315feb4ecdbSBruce M Simpson * platforms, and should be able to do so on pipes. 316feb4ecdbSBruce M Simpson * 317feb4ecdbSBruce M Simpson * You can't do "select()" on anything other than sockets in 318feb4ecdbSBruce M Simpson * Windows, so, on Win32 systems, we don't have "selectable_fd". 319feb4ecdbSBruce M Simpson */ 320feb4ecdbSBruce M Simpson p->selectable_fd = fileno(fp); 321feb4ecdbSBruce M Simpson #endif 322feb4ecdbSBruce M Simpson 323feb4ecdbSBruce M Simpson p->read_op = pcap_offline_read; 32404fb2745SSam Leffler p->inject_op = sf_inject; 325feb4ecdbSBruce M Simpson p->setfilter_op = install_bpf_program; 326ee2dd488SSam Leffler p->setdirection_op = sf_setdirection; 327feb4ecdbSBruce M Simpson p->set_datalink_op = NULL; /* we don't support munging link-layer headers */ 328feb4ecdbSBruce M Simpson p->getnonblock_op = sf_getnonblock; 329feb4ecdbSBruce M Simpson p->setnonblock_op = sf_setnonblock; 330feb4ecdbSBruce M Simpson p->stats_op = sf_stats; 331a8e07101SRui Paulo #ifdef WIN32 332a8e07101SRui Paulo p->setbuff_op = sf_setbuff; 333a8e07101SRui Paulo p->setmode_op = sf_setmode; 334a8e07101SRui Paulo p->setmintocopy_op = sf_setmintocopy; 335a8e07101SRui Paulo #endif 336a8e07101SRui Paulo p->cleanup_op = sf_cleanup; 337a8e07101SRui Paulo p->activated = 1; 338feb4ecdbSBruce M Simpson 3398cf6c252SPaul Traina return (p); 3408cf6c252SPaul Traina bad: 3418cf6c252SPaul Traina free(p); 3428cf6c252SPaul Traina return (NULL); 3438cf6c252SPaul Traina } 3448cf6c252SPaul Traina 3458cf6c252SPaul Traina /* 346a0ee43a1SRui Paulo * Read packets from a capture file, and call the callback for each 347a0ee43a1SRui Paulo * packet. 3488cf6c252SPaul Traina * If cnt > 0, return after 'cnt' packets, otherwise continue until eof. 3498cf6c252SPaul Traina */ 3508cf6c252SPaul Traina int 3518cf6c252SPaul Traina pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 3528cf6c252SPaul Traina { 35304fb2745SSam Leffler struct bpf_insn *fcode; 3548cf6c252SPaul Traina int status = 0; 3558cf6c252SPaul Traina int n = 0; 356a0ee43a1SRui Paulo u_char *data; 3578cf6c252SPaul Traina 3588cf6c252SPaul Traina while (status == 0) { 3598cf6c252SPaul Traina struct pcap_pkthdr h; 3608cf6c252SPaul Traina 361feb4ecdbSBruce M Simpson /* 362feb4ecdbSBruce M Simpson * Has "pcap_breakloop()" been called? 363feb4ecdbSBruce M Simpson * If so, return immediately - if we haven't read any 364feb4ecdbSBruce M Simpson * packets, clear the flag and return -2 to indicate 365feb4ecdbSBruce M Simpson * that we were told to break out of the loop, otherwise 366feb4ecdbSBruce M Simpson * leave the flag set, so that the *next* call will break 367feb4ecdbSBruce M Simpson * out of the loop without having read any packets, and 368feb4ecdbSBruce M Simpson * return the number of packets we've processed so far. 369feb4ecdbSBruce M Simpson */ 370feb4ecdbSBruce M Simpson if (p->break_loop) { 371feb4ecdbSBruce M Simpson if (n == 0) { 372feb4ecdbSBruce M Simpson p->break_loop = 0; 373feb4ecdbSBruce M Simpson return (-2); 374feb4ecdbSBruce M Simpson } else 375feb4ecdbSBruce M Simpson return (n); 376feb4ecdbSBruce M Simpson } 377feb4ecdbSBruce M Simpson 378a0ee43a1SRui Paulo status = p->sf.next_packet_op(p, &h, &data); 3798cf6c252SPaul Traina if (status) { 3808cf6c252SPaul Traina if (status == 1) 3818cf6c252SPaul Traina return (0); 3828cf6c252SPaul Traina return (status); 3838cf6c252SPaul Traina } 3848cf6c252SPaul Traina 38504fb2745SSam Leffler if ((fcode = p->fcode.bf_insns) == NULL || 386*d1e87331SXin LI bpf_filter(fcode, data, h.len, h.caplen)) { 387a0ee43a1SRui Paulo (*callback)(user, &h, data); 3888cf6c252SPaul Traina if (++n >= cnt && cnt > 0) 3898cf6c252SPaul Traina break; 3908cf6c252SPaul Traina } 3918cf6c252SPaul Traina } 3928cf6c252SPaul Traina /*XXX this breaks semantics tcpslice expects */ 3938cf6c252SPaul Traina return (n); 3948cf6c252SPaul Traina } 395