📄 savefile.c.orig
字号:
* and some other versions with this magic number have * some extra debugging information in the packet header; * we'd have to use some hacks^H^H^H^H^Hheuristics to * detect those variants. * * Ethereal does that, but it does so by trying to read * the first two packets of the file with each of the * record header formats. That currently means it seeks * backwards and retries the reads, which doesn't work * on pipes. We want to be able to read from a pipe, so * that strategy won't work; we'd have to buffer some * data ourselves and read from that buffer in order to * make that work. */ p->sf.hdrsize = sizeof(struct pcap_sf_patched_pkthdr); } else p->sf.hdrsize = sizeof(struct pcap_sf_pkthdr); if (hdr.version_major < PCAP_VERSION_MAJOR) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "archaic file format"); goto bad; } p->tzoff = hdr.thiszone; p->snapshot = hdr.snaplen; p->linktype = linktype_to_dlt(hdr.linktype); p->sf.rfile = fp;#ifndef WIN32 p->bufsize = hdr.snaplen;#else /* Allocate the space for pcap_pkthdr as well. It will be used by pcap_read_ex */ p->bufsize = hdr.snaplen+sizeof(struct pcap_pkthdr);#endif /* Align link header as required for proper data alignment */ /* XXX should handle all types */ switch (p->linktype) { case DLT_EN10MB: linklen = 14; break; case DLT_FDDI: linklen = 13 + 8; /* fddi_header + llc */ break; case DLT_NULL: default: linklen = 0; break; } if (p->bufsize < 0) p->bufsize = BPF_MAXBUFSIZE; p->sf.base = (u_char *)malloc(p->bufsize + BPF_ALIGNMENT); if (p->sf.base == NULL) { strlcpy(errbuf, "out of swap", PCAP_ERRBUF_SIZE); goto bad; } p->buffer = p->sf.base + BPF_ALIGNMENT - (linklen % BPF_ALIGNMENT); p->sf.version_major = hdr.version_major; p->sf.version_minor = hdr.version_minor;#ifdef PCAP_FDDIPAD /* Padding only needed for live capture fcode */ p->fddipad = 0;#endif /* * We interchanged the caplen and len fields at version 2.3, * in order to match the bpf header layout. But unfortunately * some files were written with version 2.3 in their headers * but without the interchanged fields. * * In addition, DG/UX tcpdump writes out files with a version * number of 543.0, and with the caplen and len fields in the * pre-2.3 order. */ switch (hdr.version_major) { case 2: if (hdr.version_minor < 3) p->sf.lengths_swapped = SWAPPED; else if (hdr.version_minor == 3) p->sf.lengths_swapped = MAYBE_SWAPPED; else p->sf.lengths_swapped = NOT_SWAPPED; break; case 543: p->sf.lengths_swapped = SWAPPED; break; default: p->sf.lengths_swapped = NOT_SWAPPED; break; }#if !defined(WIN32) && !defined(MSDOS) /* * You can do "select()" and "poll()" on plain files on most * platforms, and should be able to do so on pipes. * * You can't do "select()" on anything other than sockets in * Windows, so, on Win32 systems, we don't have "selectable_fd". */ p->selectable_fd = fileno(fp);#endif p->read_op = pcap_offline_read; p->inject_op = sf_inject; p->setfilter_op = install_bpf_program; p->setdirection_op = sf_setdirection; p->set_datalink_op = NULL; /* we don't support munging link-layer headers */ p->getnonblock_op = sf_getnonblock; p->setnonblock_op = sf_setnonblock; p->stats_op = sf_stats; p->close_op = sf_close; return (p); bad: free(p); return (NULL);}/* * Read sf_readfile and return the next packet. Return the header in hdr * and the contents in buf. Return 0 on success, SFERR_EOF if there were * no more packets, and SFERR_TRUNC if a partial packet was encountered. */static intsf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, u_int buflen){ struct pcap_sf_patched_pkthdr sf_hdr; FILE *fp = p->sf.rfile; size_t amt_read; bpf_u_int32 t; /* * Read the packet header; the structure we use as a buffer * is the longer structure for files generated by the patched * libpcap, but if the file has the magic number for an * unpatched libpcap we only read as many bytes as the regular * header has. */ amt_read = fread(&sf_hdr, 1, p->sf.hdrsize, fp); if (amt_read != p->sf.hdrsize) { if (ferror(fp)) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "error reading dump file: %s", pcap_strerror(errno)); return (-1); } else { if (amt_read != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "truncated dump file; tried to read %d header bytes, only got %lu", p->sf.hdrsize, (unsigned long)amt_read); return (-1); } /* EOF */ return (1); } } if (p->sf.swapped) { /* these were written in opposite byte order */ hdr->caplen = SWAPLONG(sf_hdr.caplen); hdr->len = SWAPLONG(sf_hdr.len); hdr->ts.tv_sec = SWAPLONG(sf_hdr.ts.tv_sec); hdr->ts.tv_usec = SWAPLONG(sf_hdr.ts.tv_usec); } else { hdr->caplen = sf_hdr.caplen; hdr->len = sf_hdr.len; hdr->ts.tv_sec = sf_hdr.ts.tv_sec; hdr->ts.tv_usec = sf_hdr.ts.tv_usec; } /* Swap the caplen and len fields, if necessary. */ switch (p->sf.lengths_swapped) { case NOT_SWAPPED: break; case MAYBE_SWAPPED: if (hdr->caplen <= hdr->len) { /* * The captured length is <= the actual length, * so presumably they weren't swapped. */ break; } /* FALLTHROUGH */ case SWAPPED: t = hdr->caplen; hdr->caplen = hdr->len; hdr->len = t; break; } if (hdr->caplen > buflen) { /* * This can happen due to Solaris 2.3 systems tripping * over the BUFMOD problem and not setting the snapshot * correctly in the savefile header. If the caplen isn't * grossly wrong, try to salvage. */ static u_char *tp = NULL; static size_t tsize = 0; if (hdr->caplen > 65535) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "bogus savefile header"); return (-1); } if (tsize < hdr->caplen) { tsize = ((hdr->caplen + 1023) / 1024) * 1024; if (tp != NULL) free((u_char *)tp); tp = (u_char *)malloc(tsize); if (tp == NULL) { tsize = 0; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BUFMOD hack malloc"); return (-1); } } amt_read = fread((char *)tp, 1, hdr->caplen, fp); if (amt_read != hdr->caplen) { if (ferror(fp)) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "error reading dump file: %s", pcap_strerror(errno)); } else { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "truncated dump file; tried to read %u captured bytes, only got %lu", hdr->caplen, (unsigned long)amt_read); } return (-1); } /* * We can only keep up to buflen bytes. Since caplen > buflen * is exactly how we got here, we know we can only keep the * first buflen bytes and must drop the remainder. Adjust * caplen accordingly, so we don't get confused later as * to how many bytes we have to play with. */ hdr->caplen = buflen; memcpy((char *)buf, (char *)tp, buflen); } else { /* read the packet itself */ amt_read = fread((char *)buf, 1, hdr->caplen, fp); if (amt_read != hdr->caplen) { if (ferror(fp)) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "error reading dump file: %s", pcap_strerror(errno)); } else { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "truncated dump file; tried to read %u captured bytes, only got %lu", hdr->caplen, (unsigned long)amt_read); } return (-1); } } return (0);}/* * Print out packets stored in the file initialized by sf_read_init(). * If cnt > 0, return after 'cnt' packets, otherwise continue until eof. */intpcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user){ struct bpf_insn *fcode; int status = 0; int n = 0; while (status == 0) { struct pcap_pkthdr h; /* * Has "pcap_breakloop()" been called? * If so, return immediately - if we haven't read any * packets, clear the flag and return -2 to indicate * that we were told to break out of the loop, otherwise * leave the flag set, so that the *next* call will break * out of the loop without having read any packets, and * return the number of packets we've processed so far. */ if (p->break_loop) { if (n == 0) { p->break_loop = 0; return (-2); } else return (n); } status = sf_next_packet(p, &h, p->buffer, p->bufsize); if (status) { if (status == 1) return (0); return (status); } if ((fcode = p->fcode.bf_insns) == NULL || bpf_filter(fcode, p->buffer, h.len, h.caplen)) { (*callback)(user, &h, p->buffer); if (++n >= cnt && cnt > 0) break; } } /*XXX this breaks semantics tcpslice expects */ return (n);}/* * Output a packet to the initialized dump file. */voidpcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp){ register FILE *f; struct pcap_sf_pkthdr sf_hdr; f = (FILE *)user; sf_hdr.ts.tv_sec = h->ts.tv_sec; sf_hdr.ts.tv_usec = h->ts.tv_usec; sf_hdr.caplen = h->caplen; sf_hdr.len = h->len; /* XXX we should check the return status */ (void)fwrite(&sf_hdr, sizeof(sf_hdr), 1, f); (void)fwrite((char *)sp, h->caplen, 1, f);}static pcap_dumper_t *pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname){#if defined(WIN32) || defined(MSDOS) /* * If we're writing to the standard output, put it in binary * mode, as savefiles are binary files. * * Otherwise, we turn off buffering. * XXX - why? And why not on the standard output? */ if (f == stdout) SET_BINMODE(f); else setbuf(f, NULL);#endif if (sf_write_header(f, linktype, p->tzoff, p->snapshot) == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s", fname, pcap_strerror(errno)); if (f != stdout) (void)fclose(f); return (NULL); } return ((pcap_dumper_t *)f);}/* * Initialize so that sf_write() will output to the file named 'fname'. */pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname){ FILE *f; int linktype; linktype = dlt_to_linktype(p->linktype); if (linktype == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: link-layer type %d isn't supported in savefiles", fname, linktype); return (NULL); } if (fname[0] == '-' && fname[1] == '\0') { f = stdout; fname = "standard output"; } else {#if !defined(WIN32) && !defined(MSDOS) f = fopen(fname, "w");#else f = fopen(fname, "wb");#endif if (f == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, pcap_strerror(errno)); return (NULL); } } return (pcap_setup_dump(p, linktype, f, fname));}/* * Initialize so that sf_write() will output to the given stream. */pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *f){ int linktype; linktype = dlt_to_linktype(p->linktype); if (linktype == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "stream: link-layer type %d isn't supported in savefiles", linktype); return (NULL); } return (pcap_setup_dump(p, linktype, f, "stream"));}FILE *pcap_dump_file(pcap_dumper_t *p){ return ((FILE *)p);}longpcap_dump_ftell(pcap_dumper_t *p){ return (ftell((FILE *)p));}intpcap_dump_flush(pcap_dumper_t *p){ if (fflush((FILE *)p) == EOF) return (-1); else return (0);}voidpcap_dump_close(pcap_dumper_t *p){#ifdef notyet if (ferror((FILE *)p)) return-an-error; /* XXX should check return from fclose() too */#endif (void)fclose((FILE *)p);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -