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 70static pcap_t * 71pcap_fopen_offline_internal(FILE *fp, u_int precision, 72 char *errbuf, int isng); 73 74 75/* 76 * Setting O_BINARY on DOS/Windows is a bit tricky 77 */ 78#if defined(WIN32) 79 #define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY) 80#elif defined(MSDOS) 81 #if defined(__HIGHC__) 82 #define SET_BINMODE(f) setmode(f, O_BINARY) 83 #else 84 #define SET_BINMODE(f) setmode(fileno(f), O_BINARY) 85 #endif 86#endif 87 88static int 89sf_getnonblock(pcap_t *p, char *errbuf) 90{ 91 /* 92 * This is a savefile, not a live capture file, so never say 93 * it's in non-blocking mode. 94 */ 95 return (0); 96} 97 98static int 99sf_setnonblock(pcap_t *p, int nonblock, char *errbuf) 100{ 101 /* 102 * This is a savefile, not a live capture file, so reject 103 * requests to put it in non-blocking mode. (If it's a 104 * pipe, it could be put in non-blocking mode, but that 105 * would significantly complicate the code to read packets, 106 * as it would have to handle reading partial packets and 107 * keeping the state of the read.) 108 */ 109 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 110 "Savefiles cannot be put into non-blocking mode"); 111 return (-1); 112} 113 114static int 115sf_stats(pcap_t *p, struct pcap_stat *ps) 116{ 117 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 118 "Statistics aren't available from savefiles"); 119 return (-1); 120} 121 122#ifdef WIN32 123static int 124sf_setbuff(pcap_t *p, int dim) 125{ 126 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 127 "The kernel buffer size cannot be set while reading from a file"); 128 return (-1); 129} 130 131static int 132sf_setmode(pcap_t *p, int mode) 133{ 134 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 135 "impossible to set mode while reading from a file"); 136 return (-1); 137} 138 139static int 140sf_setmintocopy(pcap_t *p, int size) 141{ 142 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 143 "The mintocopy parameter cannot be set while reading from a file"); 144 return (-1); 145} 146#endif 147 148static int 149sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_) 150{ 151 strlcpy(p->errbuf, "Sending packets isn't supported on savefiles", 152 PCAP_ERRBUF_SIZE); 153 return (-1); 154} 155 156/* 157 * Set direction flag: Which packets do we accept on a forwarding 158 * single device? IN, OUT or both? 159 */ 160static int 161sf_setdirection(pcap_t *p, pcap_direction_t d) 162{ 163 snprintf(p->errbuf, sizeof(p->errbuf), 164 "Setting direction is not supported on savefiles"); 165 return (-1); 166} 167 168void 169sf_cleanup(pcap_t *p) 170{ 171 if (p->rfile != stdin) 172 (void)fclose(p->rfile); 173 if (p->buffer != NULL) 174 free(p->buffer); 175 pcap_freecode(&p->fcode); 176} 177 178pcap_t * 179pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision, 180 char *errbuf) 181{ 182 FILE *fp; 183 pcap_t *p; 184 185 if (fname[0] == '-' && fname[1] == '\0') 186 { 187 fp = stdin; 188#if defined(WIN32) || defined(MSDOS) 189 /* 190 * We're reading from the standard input, so put it in binary 191 * mode, as savefiles are binary files. 192 */ 193 SET_BINMODE(fp); 194#endif 195 } 196 else { 197#if !defined(WIN32) && !defined(MSDOS) 198 fp = fopen(fname, "r"); 199#else 200 fp = fopen(fname, "rb"); 201#endif 202 if (fp == NULL) { 203 snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, 204 pcap_strerror(errno)); 205 return (NULL); 206 } 207 } 208 p = pcap_fopen_offline_with_tstamp_precision(fp, precision, errbuf); 209 if (p == NULL) { 210 if (fp != stdin) 211 fclose(fp); 212 } 213 return (p); 214} 215 216pcap_t * 217pcap_open_offline(const char *fname, char *errbuf) 218{ 219 return (pcap_open_offline_with_tstamp_precision(fname, 220 PCAP_TSTAMP_PRECISION_MICRO, errbuf)); 221} 222 223#ifdef WIN32 224pcap_t* pcap_hopen_offline_with_tstamp_precision(intptr_t osfd, u_int precision, 225 char *errbuf) 226{ 227 int fd; 228 FILE *file; 229 230 fd = _open_osfhandle(osfd, _O_RDONLY); 231 if ( fd < 0 ) 232 { 233 snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno)); 234 return NULL; 235 } 236 237 file = _fdopen(fd, "rb"); 238 if ( file == NULL ) 239 { 240 snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno)); 241 return NULL; 242 } 243 244 return pcap_fopen_offline_with_tstamp_precision(file, precision, 245 errbuf); 246} 247 248pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf) 249{ 250 return pcap_hopen_offline_with_tstamp_precision(osfd, 251 PCAP_TSTAMP_PRECISION_MICRO, errbuf); 252} 253#endif 254 255static pcap_t *(*check_headers[])(bpf_u_int32, FILE *, u_int, char *, int *, int) = { 256 pcap_check_header, 257 pcap_ng_check_header 258}; 259 260#define N_FILE_TYPES (sizeof check_headers / sizeof check_headers[0]) 261 262#ifdef WIN32 263static 264#endif 265pcap_t * 266pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision, 267 char *errbuf) 268{ 269 return pcap_fopen_offline_internal(fp, precision, errbuf, 0); 270} 271 272#ifdef __APPLE__ 273 274pcap_t * 275pcap_ng_open_offline(const char *fname, char *errbuf) 276{ 277 FILE *fp; 278 pcap_t *p; 279 280 if (fname[0] == '-' && fname[1] == '\0') 281 { 282 fp = stdin; 283#if defined(WIN32) || defined(MSDOS) 284 /* 285 * We're reading from the standard input, so put it in binary 286 * mode, as savefiles are binary files. 287 */ 288 SET_BINMODE(fp); 289#endif 290 } 291 else { 292#if !defined(WIN32) && !defined(MSDOS) 293 fp = fopen(fname, "r"); 294#else 295 fp = fopen(fname, "rb"); 296#endif 297 if (fp == NULL) { 298 snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, 299 pcap_strerror(errno)); 300 return (NULL); 301 } 302 } 303 p = pcap_fopen_offline_internal(fp, 304 PCAP_TSTAMP_PRECISION_MICRO, 305 errbuf, 1); 306 if (p == NULL) { 307 if (fp != stdin) 308 fclose(fp); 309 } 310 return (p); 311} 312 313pcap_t * 314pcap_ng_fopen_offline(FILE *fp, char *errbuf) 315{ 316 return pcap_fopen_offline_internal(fp, 317 PCAP_TSTAMP_PRECISION_MICRO, 318 errbuf, 1); 319} 320 321#endif /* __APPLE__ */ 322 323static pcap_t * 324pcap_fopen_offline_internal(FILE *fp, u_int precision, 325 char *errbuf, int isng) 326{ 327 register pcap_t *p = NULL; 328 bpf_u_int32 magic; 329 size_t amt_read; 330 u_int i; 331 int err; 332 off_t offset = ftello(fp); 333 334 /* 335 * Read the first 4 bytes of the file; the network analyzer dump 336 * file formats we support (pcap and pcap-ng), and several other 337 * formats we might support in the future (such as snoop, DOS and 338 * Windows Sniffer, and Microsoft Network Monitor) all have magic 339 * numbers that are unique in their first 4 bytes. 340 */ 341 amt_read = fread((char *)&magic, 1, sizeof(magic), fp); 342 if (amt_read != sizeof(magic)) { 343 if (ferror(fp)) { 344 snprintf(errbuf, PCAP_ERRBUF_SIZE, 345 "error reading dump file: %s", 346 pcap_strerror(errno)); 347 } else { 348 snprintf(errbuf, PCAP_ERRBUF_SIZE, 349 "truncated dump file; tried to read %lu file header bytes, only got %lu", 350 (unsigned long)sizeof(magic), 351 (unsigned long)amt_read); 352 } 353 goto bad; 354 } 355 356 /* 357 * When using the PCAP-NG extension APIs we are expected a PCAP-NG file 358 */ 359 if (isng) { 360 p = pcap_ng_check_header(magic, fp, precision, errbuf, &err, isng); 361 if (p != NULL) { 362 /* 363 * Yup, that's a PCAP-NG file. 364 */ 365 goto found; 366 } 367 /* 368 * That's not a PCAP-NG file 369 */ 370 snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format"); 371 goto bad; 372 } 373 /* 374 * Try all file types. 375 */ 376 for (i = 0; i < N_FILE_TYPES; i++) { 377 p = (*check_headers[i])(magic, fp, precision, errbuf, &err, isng); 378 if (p != NULL) { 379 /* Yup, that's it. */ 380 goto found; 381 } 382 if (err) { 383 /* 384 * Error trying to read the header. 385 */ 386 snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format"); 387 goto bad; 388 } 389 } 390 391 /* 392 * Well, who knows what this mess is.... 393 */ 394 snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format"); 395 goto bad; 396 397found: 398 p->rfile = fp; 399 400 /* Padding only needed for live capture fcode */ 401 p->fddipad = 0; 402 403#if !defined(WIN32) && !defined(MSDOS) 404 /* 405 * You can do "select()" and "poll()" on plain files on most 406 * platforms, and should be able to do so on pipes. 407 * 408 * You can't do "select()" on anything other than sockets in 409 * Windows, so, on Win32 systems, we don't have "selectable_fd". 410 */ 411 p->selectable_fd = fileno(fp); 412#endif 413 414 p->read_op = isng ? pcap_ng_offline_read : pcap_offline_read; 415 p->inject_op = sf_inject; 416 p->setfilter_op = install_bpf_program; 417 p->setdirection_op = sf_setdirection; 418 p->set_datalink_op = NULL; /* we don't support munging link-layer headers */ 419 p->getnonblock_op = sf_getnonblock; 420 p->setnonblock_op = sf_setnonblock; 421 p->stats_op = sf_stats; 422#ifdef WIN32 423 p->setbuff_op = sf_setbuff; 424 p->setmode_op = sf_setmode; 425 p->setmintocopy_op = sf_setmintocopy; 426#endif 427 428 /* 429 * For offline captures, the standard one-shot callback can 430 * be used for pcap_next()/pcap_next_ex(). 431 */ 432 p->oneshot_callback = pcap_oneshot; 433 434 p->cleanup_op = sf_cleanup; 435 p->activated = 1; 436 437 return (p); 438 bad: 439 fseeko(fp, offset, SEEK_SET); 440 if (p != NULL) 441 free(p); 442 return (NULL); 443} 444 445#ifdef WIN32 446static 447#endif 448pcap_t * 449pcap_fopen_offline(FILE *fp, char *errbuf) 450{ 451 return (pcap_fopen_offline_with_tstamp_precision(fp, 452 PCAP_TSTAMP_PRECISION_MICRO, errbuf)); 453} 454 455/* 456 * Read packets from a capture file, and call the callback for each 457 * packet. 458 * If cnt > 0, return after 'cnt' packets, otherwise continue until eof. 459 */ 460int 461pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 462{ 463 struct bpf_insn *fcode; 464 int status = 0; 465 int n = 0; 466 u_char *data; 467 468 while (status == 0) { 469 struct pcap_pkthdr h; 470 471 /* 472 * Has "pcap_breakloop()" been called? 473 * If so, return immediately - if we haven't read any 474 * packets, clear the flag and return -2 to indicate 475 * that we were told to break out of the loop, otherwise 476 * leave the flag set, so that the *next* call will break 477 * out of the loop without having read any packets, and 478 * return the number of packets we've processed so far. 479 */ 480 if (p->break_loop) { 481 if (n == 0) { 482 p->break_loop = 0; 483 return (-2); 484 } else 485 return (n); 486 } 487 488 status = p->next_packet_op(p, &h, &data); 489 if (status) { 490 if (status == 1) 491 return (0); 492 return (status); 493 } 494 495 if ((fcode = p->fcode.bf_insns) == NULL || 496 bpf_filter(fcode, data, h.len, h.caplen)) { 497 (*callback)(user, &h, data); 498 if (++n >= cnt && cnt > 0) 499 break; 500 } 501 } 502 /*XXX this breaks semantics tcpslice expects */ 503 return (n); 504} 505 506/* 507 * Read blocks from a capture file, and call the callback for each 508 * packet. 509 * If cnt > 0, return after 'cnt' packets, otherwise continue until eof. 510 */ 511int 512pcap_ng_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 513{ 514 struct bpf_insn *fcode; 515 int status = 0; 516 int n = 0; 517 u_char *data; 518 519 while (status == 0) { 520 struct pcap_pkthdr h; 521 522 /* 523 * Has "pcap_breakloop()" been called? 524 * If so, return immediately - if we haven't read any 525 * packets, clear the flag and return -2 to indicate 526 * that we were told to break out of the loop, otherwise 527 * leave the flag set, so that the *next* call will break 528 * out of the loop without having read any packets, and 529 * return the number of packets we've processed so far. 530 */ 531 if (p->break_loop) { 532 if (n == 0) { 533 p->break_loop = 0; 534 return (-2); 535 } else 536 return (n); 537 } 538 539 /* 540 * The begining of the block is always returned into p->buffer 541 * even when data is NULL (because it's not a data block) 542 */ 543 status = p->next_packet_op(p, &h, &data); 544 if (status) { 545 if (status == 1) 546 return (0); 547 return (status); 548 } 549 550 /* 551 * TBD 552 * Have one filter per link type 553 */ 554 if ((fcode = p->fcode.bf_insns) == NULL || 555 data == NULL || 556 bpf_filter(fcode, data, h.len, h.caplen)) { 557 (*callback)(user, &h, p->buffer); 558 if (++n >= cnt && cnt > 0) 559 break; 560 } 561 } 562 /*XXX this breaks semantics tcpslice expects */ 563 return (n); 564} 565 566