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