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