diff options
Diffstat (limited to 'contrib/libpcap/savefile.c')
-rw-r--r-- | contrib/libpcap/savefile.c | 298 |
1 files changed, 249 insertions, 49 deletions
diff --git a/contrib/libpcap/savefile.c b/contrib/libpcap/savefile.c index cc307bd..0a739fa 100644 --- a/contrib/libpcap/savefile.c +++ b/contrib/libpcap/savefile.c @@ -30,7 +30,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.92.2.11 2004/03/11 23:46:14 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.126 2005/02/08 20:03:16 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -49,8 +49,27 @@ static const char rcsid[] _U_ = #include "os-proto.h" #endif -#define TCPDUMP_MAGIC 0xa1b2c3d4 -#define PATCHED_TCPDUMP_MAGIC 0xa1b2cd34 +/* + * Standard libpcap format. + */ +#define TCPDUMP_MAGIC 0xa1b2c3d4 + +/* + * Alexey Kuznetzov's modified libpcap format. + */ +#define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34 + +/* + * Reserved for Francisco Mesquita <francisco.mesquita@radiomovel.pt> + * for another modified format. + */ +#define FMESQUITA_TCPDUMP_MAGIC 0xa1b234cd + +/* + * Navtel Communcations' format, with nanosecond timestamps, + * as per a request from Dumas Hwang <dumas.hwang@navtelcom.com>. + */ +#define NAVTEL_TCPDUMP_MAGIC 0xa12b3c4d /* * We use the "receiver-makes-right" approach to byte order, @@ -76,6 +95,19 @@ static const char rcsid[] _U_ = #define SFERR_EOF 4 /* not really an error, just a status */ /* + * Setting O_BINARY on DOS/Windows is a bit tricky + */ +#if defined(WIN32) + #define SET_BINMODE(f) _setmode(fileno(f), O_BINARY) +#elif defined(MSDOS) + #if defined(__HIGHC__) + #define SET_BINMODE(f) setmode(f, O_BINARY) + #else + #define SET_BINMODE(f) setmode(fileno(f), O_BINARY) + #endif +#endif + +/* * We don't write DLT_* values to the capture file header, because * they're not the same on all platforms. * @@ -156,11 +188,6 @@ static const char rcsid[] _U_ = #define LINKTYPE_PPP_ETHER 51 /* NetBSD PPP-over-Ethernet */ -/* - * This isn't supported in libpcap 0.8[.x], but is supported in the - * current CVS version; we include it here to note that it's not available - * for anybody else to use. - */ #define LINKTYPE_SYMANTEC_FIREWALL 99 /* Symantec Enterprise Firewall */ #define LINKTYPE_ATM_RFC1483 100 /* LLC/SNAP-encapsulated ATM */ @@ -247,11 +274,6 @@ static const char rcsid[] _U_ = #define LINKTYPE_RAWSS7_MTP3 141 /* definitions */ #define LINKTYPE_RAWSS7_SCCP 142 -/* - * This isn't supported in libpcap 0.8[.x], but is supported in the - * current CVS version; we include it here to note that it's not available - * for anybody else to use. - */ #define LINKTYPE_DOCSIS 143 /* DOCSIS MAC frames */ #define LINKTYPE_LINUX_IRDA 144 /* Linux-IrDA */ @@ -325,6 +347,63 @@ static const char rcsid[] _U_ = */ #define LINKTYPE_JUNIPER_MONITOR 164 +/* + * Reserved for BACnet MS/TP. + */ +#define LINKTYPE_BACNET_MS_TP 165 + +/* + * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>. + * + * This is used in some OSes to allow a kernel socket filter to distinguish + * between incoming and outgoing packets, on a socket intended to + * supply pppd with outgoing packets so it can do dial-on-demand and + * hangup-on-lack-of-demand; incoming packets are filtered out so they + * don't cause pppd to hold the connection up (you don't want random + * input packets such as port scans, packets from old lost connections, + * etc. to force the connection to stay up). + * + * The first byte of the PPP header (0xff03) is modified to accomodate + * the direction - 0x00 = IN, 0x01 = OUT. + */ +#define LINKTYPE_PPP_PPPD 166 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler <hannes@juniper.net>. The DLT_s are used + * for passing on chassis-internal metainformation such as + * QOS profiles, cookies, etc.. + */ +#define LINKTYPE_JUNIPER_PPPOE 167 +#define LINKTYPE_JUNIPER_PPPOE_ATM 168 + +#define LINKTYPE_GPRS_LLC 169 /* GPRS LLC */ +#define LINKTYPE_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */ +#define LINKTYPE_GPF_F 171 /* GPF-T (ITU-T G.7041/Y.1303) */ + +/* + * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line + * monitoring equipment. + */ +#define LINKTYPE_GCOM_T1E1 172 +#define LINKTYPE_GCOM_SERIAL 173 + +/* + * Juniper-private data link type, as per request from + * Hannes Gredler <hannes@juniper.net>. The DLT_ is used + * for internal communication to Physical Interface Cards (PIC) + */ +#define LINKTYPE_JUNIPER_PIC_PEER 174 + +/* + * Link types requested by Gregor Maier <gregor@endace.com> of Endace + * Measurement Systems. They add an ERF header (see + * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of + * the link-layer header. + */ +#define LINKTYPE_ERF_ETH 175 /* Ethernet */ +#define LINKTYPE_ERF_POS 176 /* Packet-over-SONET */ + static struct linktype_map { int dlt; int linktype; @@ -483,8 +562,37 @@ static struct linktype_map { * LINKTYPE_* values, either). */ + /* Juniper-internal chassis encapsulation */ + { DLT_JUNIPER_MONITOR, LINKTYPE_JUNIPER_MONITOR }, + + /* BACnet MS/TP */ + { DLT_BACNET_MS_TP, LINKTYPE_BACNET_MS_TP }, + + /* PPP for pppd, with direction flag in the PPP header */ + { DLT_PPP_PPPD, LINKTYPE_PPP_PPPD}, + + /* Juniper-internal chassis encapsulation */ + { DLT_JUNIPER_PPPOE, LINKTYPE_JUNIPER_PPPOE }, + { DLT_JUNIPER_PPPOE_ATM,LINKTYPE_JUNIPER_PPPOE_ATM }, + + /* GPRS LLC */ + { DLT_GPRS_LLC, LINKTYPE_GPRS_LLC }, + + /* Transparent Generic Framing Procedure (ITU-T G.7041/Y.1303) */ + { DLT_GPF_T, LINKTYPE_GPF_T }, + + /* Framed Generic Framing Procedure (ITU-T G.7041/Y.1303) */ + { DLT_GPF_F, LINKTYPE_GPF_F }, + + { DLT_GCOM_T1E1, LINKTYPE_GCOM_T1E1 }, + { DLT_GCOM_SERIAL, LINKTYPE_GCOM_SERIAL }, + /* Juniper-internal chassis encapsulation */ - { DLT_JUNIPER_MONITOR, LINKTYPE_JUNIPER_MONITOR }, + { DLT_JUNIPER_PIC_PEER, LINKTYPE_JUNIPER_PIC_PEER }, + + /* Endace types */ + { DLT_ERF_ETH, LINKTYPE_ERF_ETH }, + { DLT_ERF_POS, LINKTYPE_ERF_POS }, { -1, -1 } }; @@ -584,6 +692,14 @@ sf_stats(pcap_t *p, struct pcap_stat *ps) return (-1); } +static int +sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_) +{ + strlcpy(p->errbuf, "Sending packets isn't supported on savefiles", + PCAP_ERRBUF_SIZE); + return (-1); +} + static void sf_close(pcap_t *p) { @@ -596,9 +712,37 @@ sf_close(pcap_t *p) pcap_t * pcap_open_offline(const char *fname, char *errbuf) { + FILE *fp; + pcap_t *p; + + if (fname[0] == '-' && fname[1] == '\0') + fp = stdin; + else { +#if !defined(WIN32) && !defined(MSDOS) + fp = fopen(fname, "r"); +#else + fp = fopen(fname, "rb"); +#endif + if (fp == NULL) { + snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, + pcap_strerror(errno)); + return (NULL); + } + } + p = pcap_fopen_offline(fp, errbuf); + if (p == NULL) { + if (fp != stdin) + fclose(fp); + } + return (p); +} + +pcap_t * +pcap_fopen_offline(FILE *fp, char *errbuf) +{ register pcap_t *p; - register FILE *fp; struct pcap_file_header hdr; + size_t amt_read; bpf_u_int32 magic; int linklen; @@ -610,29 +754,24 @@ pcap_open_offline(const char *fname, char *errbuf) memset((char *)p, 0, sizeof(*p)); - if (fname[0] == '-' && fname[1] == '\0') - fp = stdin; - else { -#ifndef WIN32 - fp = fopen(fname, "r"); -#else - fp = fopen(fname, "rb"); -#endif - if (fp == NULL) { - snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, + amt_read = fread((char *)&hdr, 1, sizeof(hdr), fp); + if (amt_read != sizeof(hdr)) { + if (ferror(fp)) { + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "error reading dump file: %s", pcap_strerror(errno)); - goto bad; + } else { + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "truncated dump file; tried to read %lu file header bytes, only got %lu", + (unsigned long)sizeof(hdr), + (unsigned long)amt_read); } - } - if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) { - snprintf(errbuf, PCAP_ERRBUF_SIZE, "fread: %s", - pcap_strerror(errno)); goto bad; } magic = hdr.magic; - if (magic != TCPDUMP_MAGIC && magic != PATCHED_TCPDUMP_MAGIC) { + if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) { magic = SWAPLONG(magic); - if (magic != TCPDUMP_MAGIC && magic != PATCHED_TCPDUMP_MAGIC) { + if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "bad dump file format"); goto bad; @@ -640,12 +779,23 @@ pcap_open_offline(const char *fname, char *errbuf) p->sf.swapped = 1; swap_hdr(&hdr); } - if (magic == PATCHED_TCPDUMP_MAGIC) { + if (magic == KUZNETZOV_TCPDUMP_MAGIC) { /* * XXX - the patch that's in some versions of libpcap - * changes the packet header but not the magic number; + * changes the packet header but not the magic number, + * 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 that. + * 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 @@ -694,8 +844,8 @@ pcap_open_offline(const char *fname, char *errbuf) p->sf.version_major = hdr.version_major; p->sf.version_minor = hdr.version_minor; #ifdef PCAP_FDDIPAD - /* XXX padding only needed for kernel fcode */ - pcap_fddipad = 0; + /* Padding only needed for live capture fcode */ + p->fddipad = 0; #endif /* @@ -728,7 +878,7 @@ pcap_open_offline(const char *fname, char *errbuf) break; } -#ifndef WIN32 +#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. @@ -740,6 +890,7 @@ pcap_open_offline(const char *fname, char *errbuf) #endif p->read_op = pcap_offline_read; + p->inject_op = sf_inject; p->setfilter_op = install_bpf_program; p->set_datalink_op = NULL; /* we don't support munging link-layer headers */ p->getnonblock_op = sf_getnonblock; @@ -747,10 +898,17 @@ pcap_open_offline(const char *fname, char *errbuf) p->stats_op = sf_stats; p->close_op = sf_close; +#if defined(WIN32) || defined(MSDOS) + /* + * If we're reading from the standard input, put it in binary + * mode, as savefiles are binary files. + */ + if (fp == stdin) + SET_BINMODE(fp); +#endif + return (p); bad: - if(fp) - fclose(fp); free(p); return (NULL); } @@ -906,7 +1064,7 @@ sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, u_int buflen) int pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { - struct bpf_insn *fcode = p->fcode.bf_insns; + struct bpf_insn *fcode; int status = 0; int n = 0; @@ -937,7 +1095,7 @@ pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) return (status); } - if (fcode == NULL || + 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) @@ -967,6 +1125,33 @@ pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) (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'. */ @@ -986,15 +1171,12 @@ pcap_dump_open(pcap_t *p, const char *fname) if (fname[0] == '-' && fname[1] == '\0') { f = stdout; -#ifdef WIN32 - _setmode(_fileno(f), _O_BINARY); -#endif + fname = "standard output"; } else { -#ifndef WIN32 +#if !defined(WIN32) && !defined(MSDOS) f = fopen(fname, "w"); #else f = fopen(fname, "wb"); - setbuf(f, NULL); /* XXX - why? */ #endif if (f == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", @@ -1002,8 +1184,26 @@ pcap_dump_open(pcap_t *p, const char *fname) return (NULL); } } - (void)sf_write_header(f, linktype, p->tzoff, p->snapshot); - return ((pcap_dumper_t *)f); + 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 * |