Ethereal-dev: Re: [ethereal-dev] Re: [ethereal-users] Ethereal crash reading tcpdump '-r' file
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Guy Harris <gharris@xxxxxxxxxxxx>
Date: Fri, 15 Sep 2000 00:50:25 -0700
On Thu, Sep 14, 2000 at 09:25:27AM -0700, Marc Solsona Palomar wrote: > Sorry guys for not replying before. yesterday was a bad day. First fo > all, you are right, the log I sent you was from a Nokia box. > I though that it was the standard tcpdump from FBSD3.4. My fault. I > really apperciate your efforts trying to help me. Thanks. Well, here's a patch to the 0.8.12 version of Ethereal that appears to allow it to read the one capture file you sent, as well as the samples of other non-standard tcpdump capture files I have. That will (unless it turns out to break other things) show up in the next release, but, as 0.8.12 just came out, the next release may not be for a while, so you may want to download the 0.8.12 source, apply the patch, and build it.
Index: wiretap/file.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/wiretap/file.c,v retrieving revision 1.60 diff -c -r1.60 wiretap/file.c *** wiretap/file.c 2000/08/11 13:32:36 1.60 --- wiretap/file.c 2000/09/15 07:46:43 *************** *** 267,272 **** --- 267,276 ---- { "modified libpcap (tcpdump)", "modlibpcap", libpcap_dump_can_write_encap, libpcap_dump_open }, + /* WTAP_FILE_PCAP_NOKIA */ + { "Nokia libpcap (tcpdump)", "nokialibpcap", + libpcap_dump_can_write_encap, libpcap_dump_open }, + /* WTAP_FILE_LANALYZER */ { "Novell LANalyzer", NULL, NULL, NULL }, Index: wiretap/libpcap.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/wiretap/libpcap.c,v retrieving revision 1.40 diff -c -r1.40 wiretap/libpcap.c *** wiretap/libpcap.c 2000/09/12 18:35:47 1.40 --- wiretap/libpcap.c 2000/09/15 07:46:46 *************** *** 38,44 **** --- 38,55 ---- #define BIT_SWAPPED_MAC_ADDRS #endif + + /* Try to read the first two records of the capture file. */ + typedef enum { + THIS_FORMAT, /* the reads succeeded, assume it's this format */ + BAD_READ, /* the file is probably not valid */ + OTHER_FORMAT /* the file may be valid, but not in this format */ + } libpcap_try_t; + static libpcap_try_t libpcap_try(wtap *wth, int *err); + static gboolean libpcap_read(wtap *wth, int *err, int *data_offset); + static int libpcap_read_header(wtap *wth, int *err, + struct pcaprec_ss990915_hdr *hdr, gboolean silent); static void adjust_header(wtap *wth, struct pcaprec_hdr *hdr); static void libpcap_close(wtap *wth); static gboolean libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, *************** *** 303,311 **** gboolean byte_swapped; gboolean modified; int file_encap; - struct pcaprec_modified_hdr first_rec_hdr; - struct pcaprec_modified_hdr second_rec_hdr; - int hdr_len; /* Read in the number that should be at the start of a "libpcap" file */ file_seek(wth->fh, 0, SEEK_SET); --- 314,319 ---- *************** *** 391,397 **** } /* This is a libpcap file */ - wth->file_type = modified ? WTAP_FILE_PCAP_SS991029 : WTAP_FILE_PCAP; wth->capture.pcap = g_malloc(sizeof(libpcap_t)); wth->capture.pcap->byte_swapped = byte_swapped; wth->capture.pcap->version_major = hdr.version_major; --- 399,404 ---- *************** *** 430,518 **** * 6.3, meaning that programs expecting the standard per- * packet header in captures with the modified magic number * can't read dumps from its tcpdump. */ ! hdr_len = modified ? sizeof (struct pcaprec_modified_hdr) : ! sizeof (struct pcaprec_hdr); ! bytes_read = file_read(&first_rec_hdr, 1, hdr_len, wth->fh); ! if (bytes_read != hdr_len) { ! *err = file_error(wth->fh); ! if (*err != 0) ! return -1; /* failed to read it */ /* ! * Short read - assume the file isn't modified, ! * and put the seek pointer back. The attempt ! * to read the first packet will presumably get ! * the same short read. */ ! goto give_up; ! } ! adjust_header(wth, &first_rec_hdr.hdr); ! if (first_rec_hdr.hdr.incl_len > WTAP_MAX_PACKET_SIZE) { /* ! * The first record is bogus, so this is probably ! * a corrupt file. Assume the file has the ! * expected header type, and put the seek pointer ! * back. The attempt to read the first packet will ! * probably get the same bogus length. */ ! goto give_up; } ! file_seek(wth->fh, ! wth->data_offset + hdr_len + first_rec_hdr.hdr.incl_len, SEEK_SET); ! bytes_read = file_read(&second_rec_hdr, 1, hdr_len, wth->fh); /* ! * OK, does the next packet's header look sane? */ ! if (bytes_read != hdr_len) { ! *err = file_error(wth->fh); ! if (*err != 0) ! return -1; /* failed to read it */ /* ! * Short read - assume the file has the expected ! * header type, and put the seek pointer back. The ! * attempt to read the second packet will presumably get ! * the same short read error. */ ! goto give_up; } ! adjust_header(wth, &second_rec_hdr.hdr); ! if (second_rec_hdr.hdr.incl_len > WTAP_MAX_PACKET_SIZE) { /* ! * Oh, dear. Maybe it's a Capture File ! * From Hell, and what looks like the ! * "header" of the next packet is actually ! * random junk from the middle of a packet. ! * Try treating it as having the other type for ! * the magic number it had; if that doesn't work, ! * it probably *is* a corrupt file. */ ! wth->file_type = modified ? WTAP_FILE_PCAP_SS990915 : ! WTAP_FILE_PCAP_SS990417; } - give_up: /* ! * Restore the seek pointer. */ ! file_seek(wth->fh, wth->data_offset, SEEK_SET); ! ! return 1; } /* Read the next packet */ static gboolean libpcap_read(wtap *wth, int *err, int *data_offset) { - guint packet_size; - int bytes_to_read, bytes_read; struct pcaprec_ss990915_hdr hdr; /* Read record header. */ errno = WTAP_ERR_CANT_READ; switch (wth->file_type) { --- 437,698 ---- * 6.3, meaning that programs expecting the standard per- * packet header in captures with the modified magic number * can't read dumps from its tcpdump. + * + * Oh, and if it has the standard magic number, it might, instead, + * be a Nokia libpcap file, so we may need to try that if + * neither normal nor ss990417 headers work. */ ! if (modified) { ! /* ! * Well, we have the magic number from Alexey's ! * later two patches. ! * ! * Try ss991029, the last of his patches, first. ! */ ! wth->file_type = WTAP_FILE_PCAP_SS991029; ! switch (libpcap_try(wth, err)) { ! ! case BAD_READ: ! /* ! * Well, we couldn't even read it. ! * Give up. ! */ ! return -1; ! ! case THIS_FORMAT: ! /* ! * Well, it looks as if it might be 991029. ! * Put the seek pointer back, and return success. ! */ ! file_seek(wth->fh, wth->data_offset, SEEK_SET); ! return 1; ! ! case OTHER_FORMAT: ! /* ! * Try the next format. ! */ ! break; ! } /* ! * Well, it's not completely unreadable, ! * but it's not ss991029. Try ss990915; ! * there are no other types to try after that, ! * so we put the seek pointer back and treat ! * it as 990915. */ ! wth->file_type = WTAP_FILE_PCAP_SS990915; ! file_seek(wth->fh, wth->data_offset, SEEK_SET); ! } else { ! /* ! * Well, we have the standard magic number. ! * ! * Try the standard format first. ! */ ! wth->file_type = WTAP_FILE_PCAP; ! switch (libpcap_try(wth, err)) { ! case BAD_READ: ! /* ! * Well, we couldn't even read it. ! * Give up. ! */ ! return -1; ! case THIS_FORMAT: ! /* ! * Well, it looks as if it might be a standard ! * libpcap file. ! * Put the seek pointer back, and return success. ! */ ! file_seek(wth->fh, wth->data_offset, SEEK_SET); ! return 1; ! ! case OTHER_FORMAT: ! /* ! * Try the next format. ! */ ! break; ! } ! ! /* ! * Well, it's not completely unreadable, but it's not ! * a standard file. Put the seek pointer back and try ! * ss990417. ! */ ! wth->file_type = WTAP_FILE_PCAP_SS990417; ! file_seek(wth->fh, wth->data_offset, SEEK_SET); ! switch (libpcap_try(wth, err)) { ! ! case BAD_READ: ! /* ! * Well, we couldn't even read it. ! * Give up. ! */ ! return -1; ! ! case THIS_FORMAT: ! /* ! * Well, it looks as if it might be ss990417. ! * Put the seek pointer back, and return success. ! */ ! file_seek(wth->fh, wth->data_offset, SEEK_SET); ! return 1; ! ! case OTHER_FORMAT: ! /* ! * Try the next format. ! */ ! break; ! } ! /* ! * Well, it's not completely unreadable, ! * but it's not a standard file *nor* is it ss990417. ! * Try it as a Nokia file; there are no other types ! * to try after that, so we put the seek pointer back ! * and treat it as a Nokia file. */ ! wth->file_type = WTAP_FILE_PCAP_NOKIA; ! file_seek(wth->fh, wth->data_offset, SEEK_SET); } ! return 1; ! } + /* Try to read the first two records of the capture file. */ + static libpcap_try_t libpcap_try(wtap *wth, int *err) + { /* ! * pcaprec_ss990915_hdr is the largest header type. */ ! struct pcaprec_ss990915_hdr first_rec_hdr, second_rec_hdr; + /* + * Attempt to read the first record's header. + */ + if (libpcap_read_header(wth, err, &first_rec_hdr, TRUE) == -1) { + if (*err == WTAP_ERR_SHORT_READ) { + /* + * Short read - assume the file is in this format. + * When our client tries to read the first packet + * they will presumably get the same short read. + */ + return THIS_FORMAT; + } + + if (*err == WTAP_ERR_BAD_RECORD) { + /* + * The first record is bogus, so this is probably + * a corrupt file. Assume the file is in this + * format. When our client tries to read the + * first packet they will presumably get the + * same bogus record. + */ + return THIS_FORMAT; + } + /* ! * Some other error, e.g. an I/O error; just give up. */ ! return BAD_READ; } + + /* + * Now skip over the first record's data, under the assumption + * that the header is sane. + */ + file_seek(wth->fh, first_rec_hdr.hdr.incl_len, SEEK_CUR); ! /* ! * Now attempt to read the second record's header. ! */ ! if (libpcap_read_header(wth, err, &second_rec_hdr, TRUE) == -1) { ! if (*err == WTAP_ERR_SHORT_READ) { ! /* ! * Short read - assume the file is in this format. ! * When our client tries to read the second packet ! * they will presumably get the same short read. ! */ ! return THIS_FORMAT; ! } ! ! if (*err == WTAP_ERR_BAD_RECORD) { ! /* ! * The second record is bogus; maybe it's a ! * Capture File From Hell, and what looks like ! * the "header" of the next packet is actually ! * random junk from the middle of a packet. ! * Try the next format; if we run out of formats, ! * it probably *is* a corrupt file. ! */ ! return OTHER_FORMAT; ! } ! /* ! * Some other error, e.g. an I/O error; just give up. */ ! return BAD_READ; } /* ! * OK, the first two records look OK; assume this is the ! * right format. */ ! return THIS_FORMAT; } /* Read the next packet */ static gboolean libpcap_read(wtap *wth, int *err, int *data_offset) { struct pcaprec_ss990915_hdr hdr; + guint packet_size; + int bytes_read; + + bytes_read = libpcap_read_header(wth, err, &hdr, FALSE); + if (bytes_read == -1) { + /* + * We failed to read the header. + */ + return FALSE; + } + + wth->data_offset += bytes_read; + packet_size = hdr.hdr.incl_len; + + buffer_assure_space(wth->frame_buffer, packet_size); + *data_offset = wth->data_offset; + errno = WTAP_ERR_CANT_READ; + bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), 1, + packet_size, wth->fh); + if (bytes_read != packet_size) { + *err = file_error(wth->fh); + if (*err == 0) + *err = WTAP_ERR_SHORT_READ; + return FALSE; + } + wth->data_offset += packet_size; + + wth->phdr.ts.tv_sec = hdr.hdr.ts_sec; + wth->phdr.ts.tv_usec = hdr.hdr.ts_usec; + wth->phdr.caplen = packet_size; + wth->phdr.len = hdr.hdr.orig_len; + wth->phdr.pkt_encap = wth->file_encap; + + return TRUE; + } + + /* Read the header of the next packet; if "silent" is TRUE, don't complain + to the console, as we're testing to see if the file appears to be of a + particular type. + + Return -1 on an error, or the number of bytes of header read on success. */ + static int libpcap_read_header(wtap *wth, int *err, + struct pcaprec_ss990915_hdr *hdr, gboolean silent) + { + int bytes_to_read, bytes_read; + /* Read record header. */ errno = WTAP_ERR_CANT_READ; switch (wth->file_type) { *************** *** 530,584 **** bytes_to_read = sizeof (struct pcaprec_ss990915_hdr); break; default: g_assert_not_reached(); bytes_to_read = 0; } ! bytes_read = file_read(&hdr, 1, bytes_to_read, wth->fh); if (bytes_read != bytes_to_read) { *err = file_error(wth->fh); if (*err == 0 && bytes_read != 0) { *err = WTAP_ERR_SHORT_READ; } ! return FALSE; } - wth->data_offset += bytes_read; ! adjust_header(wth, &hdr.hdr); ! packet_size = hdr.hdr.incl_len; ! if (packet_size > WTAP_MAX_PACKET_SIZE) { /* ! * Probably a corrupt capture file; don't blow up trying ! * to allocate space for an immensely-large packet. */ ! g_message("pcap: File has %u-byte packet, bigger than maximum of %u", ! packet_size, WTAP_MAX_PACKET_SIZE); *err = WTAP_ERR_BAD_RECORD; ! return FALSE; } - - buffer_assure_space(wth->frame_buffer, packet_size); - *data_offset = wth->data_offset; - errno = WTAP_ERR_CANT_READ; - bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), 1, - packet_size, wth->fh); ! if (bytes_read != packet_size) { ! *err = file_error(wth->fh); ! if (*err == 0) ! *err = WTAP_ERR_SHORT_READ; ! return FALSE; } - wth->data_offset += packet_size; - - wth->phdr.ts.tv_sec = hdr.hdr.ts_sec; - wth->phdr.ts.tv_usec = hdr.hdr.ts_usec; - wth->phdr.caplen = packet_size; - wth->phdr.len = hdr.hdr.orig_len; - wth->phdr.pkt_encap = wth->file_encap; ! return TRUE; } static void --- 710,769 ---- bytes_to_read = sizeof (struct pcaprec_ss990915_hdr); break; + case WTAP_FILE_PCAP_NOKIA: + bytes_to_read = sizeof (struct pcaprec_nokia_hdr); + break; + default: g_assert_not_reached(); bytes_to_read = 0; } ! bytes_read = file_read(hdr, 1, bytes_to_read, wth->fh); if (bytes_read != bytes_to_read) { *err = file_error(wth->fh); if (*err == 0 && bytes_read != 0) { *err = WTAP_ERR_SHORT_READ; } ! return -1; } ! adjust_header(wth, &hdr->hdr); ! if (hdr->hdr.incl_len > WTAP_MAX_PACKET_SIZE) { /* ! * Probably a corrupt capture file; return an error, ! * so that our caller doesn't blow up trying to allocate ! * space for an immensely-large packet, and so that ! * the code to try to guess what type of libpcap file ! * this is can tell when it's not the type we're guessing ! * it is. */ ! if (!silent) { ! g_message("pcap: File has %u-byte packet, bigger than maximum of %u", ! hdr->hdr.incl_len, WTAP_MAX_PACKET_SIZE); ! } *err = WTAP_ERR_BAD_RECORD; ! return -1; } ! if (hdr->hdr.orig_len > WTAP_MAX_PACKET_SIZE) { ! /* ! * Probably a corrupt capture file; return an error, ! * so that our caller doesn't blow up trying to ! * cope with a huge "real" packet length, and so that ! * the code to try to guess what type of libpcap file ! * this is can tell when it's not the type we're guessing ! * it is. ! */ ! if (!silent) { ! g_message("pcap: File has %u-byte packet, bigger than maximum of %u", ! hdr->hdr.orig_len, WTAP_MAX_PACKET_SIZE); ! } ! *err = WTAP_ERR_BAD_RECORD; ! return -1; } ! return bytes_read; } static void *************** *** 680,685 **** --- 865,871 ---- case WTAP_FILE_PCAP: case WTAP_FILE_PCAP_SS990417: /* modified, but with the old magic, sigh */ + case WTAP_FILE_PCAP_NOKIA: /* Nokia libpcap of some sort */ magic = PCAP_MAGIC; break; *************** *** 776,781 **** --- 962,976 ---- rec_hdr.cpu1 = 0; rec_hdr.cpu2 = 0; hdr_size = sizeof (struct pcaprec_ss990915_hdr); + break; + + case WTAP_FILE_PCAP_NOKIA: /* old magic, extra crap at the end */ + rec_hdr.ifindex = 0; + rec_hdr.protocol = 0; + rec_hdr.pkt_type = 0; + rec_hdr.cpu1 = 0; + rec_hdr.cpu2 = 0; + hdr_size = sizeof (struct pcaprec_nokia_hdr); break; default: Index: wiretap/libpcap.h =================================================================== RCS file: /usr/local/cvsroot/ethereal/wiretap/libpcap.h,v retrieving revision 1.9 diff -c -r1.9 wiretap/libpcap.h *** wiretap/libpcap.h 2000/08/11 13:32:35 1.9 --- wiretap/libpcap.h 2000/09/15 07:46:46 *************** *** 86,91 **** --- 86,97 ---- guint8 pad[3]; /* pad to a 4-byte boundary */ }; + /* "libpcap" record header for version used on some Nokia boxes (firewalls?) */ + struct pcaprec_nokia_hdr { + struct pcaprec_hdr hdr; /* the regular header */ + guint8 stuff[4]; /* mysterious stuff */ + }; + int libpcap_open(wtap *wth, int *err); gboolean libpcap_dump_open(wtap_dumper *wdh, int *err); int libpcap_dump_can_write_encap(int filetype, int encap); Index: wiretap/wtap.h =================================================================== RCS file: /usr/local/cvsroot/ethereal/wiretap/wtap.h,v retrieving revision 1.78 diff -c -r1.78 wiretap/wtap.h *** wiretap/wtap.h 2000/09/07 05:34:23 1.78 --- wiretap/wtap.h 2000/09/15 07:46:47 *************** *** 98,131 **** #define WTAP_NUM_ENCAP_TYPES 17 /* File types that can be read by wiretap. ! We may eventually support writing some or all of these file types, ! too, so we distinguish between different versions of them. */ #define WTAP_FILE_UNKNOWN 0 #define WTAP_FILE_WTAP 1 #define WTAP_FILE_PCAP 2 #define WTAP_FILE_PCAP_SS990417 3 #define WTAP_FILE_PCAP_SS990915 4 #define WTAP_FILE_PCAP_SS991029 5 ! #define WTAP_FILE_LANALYZER 6 ! #define WTAP_FILE_NGSNIFFER_UNCOMPRESSED 7 ! #define WTAP_FILE_NGSNIFFER_COMPRESSED 8 ! #define WTAP_FILE_SNOOP 9 ! #define WTAP_FILE_IPTRACE_1_0 10 ! #define WTAP_FILE_IPTRACE_2_0 11 ! #define WTAP_FILE_NETMON_1_x 12 ! #define WTAP_FILE_NETMON_2_x 13 ! #define WTAP_FILE_NETXRAY_1_0 14 ! #define WTAP_FILE_NETXRAY_1_1 15 ! #define WTAP_FILE_NETXRAY_2_00x 16 ! #define WTAP_FILE_RADCOM 17 ! #define WTAP_FILE_ASCEND 18 ! #define WTAP_FILE_NETTL 19 ! #define WTAP_FILE_TOSHIBA 20 ! #define WTAP_FILE_I4BTRACE 21 ! #define WTAP_FILE_CSIDS 22 /* last WTAP_FILE_ value + 1 */ ! #define WTAP_NUM_FILE_TYPES 23 /* * Maximum packet size we'll support. --- 98,132 ---- #define WTAP_NUM_ENCAP_TYPES 17 /* File types that can be read by wiretap. ! We support writing some many of these file types, too, so we ! distinguish between different versions of them. */ #define WTAP_FILE_UNKNOWN 0 #define WTAP_FILE_WTAP 1 #define WTAP_FILE_PCAP 2 #define WTAP_FILE_PCAP_SS990417 3 #define WTAP_FILE_PCAP_SS990915 4 #define WTAP_FILE_PCAP_SS991029 5 ! #define WTAP_FILE_PCAP_NOKIA 6 ! #define WTAP_FILE_LANALYZER 7 ! #define WTAP_FILE_NGSNIFFER_UNCOMPRESSED 8 ! #define WTAP_FILE_NGSNIFFER_COMPRESSED 9 ! #define WTAP_FILE_SNOOP 10 ! #define WTAP_FILE_IPTRACE_1_0 11 ! #define WTAP_FILE_IPTRACE_2_0 12 ! #define WTAP_FILE_NETMON_1_x 13 ! #define WTAP_FILE_NETMON_2_x 14 ! #define WTAP_FILE_NETXRAY_1_0 15 ! #define WTAP_FILE_NETXRAY_1_1 16 ! #define WTAP_FILE_NETXRAY_2_00x 17 ! #define WTAP_FILE_RADCOM 18 ! #define WTAP_FILE_ASCEND 19 ! #define WTAP_FILE_NETTL 20 ! #define WTAP_FILE_TOSHIBA 21 ! #define WTAP_FILE_I4BTRACE 22 ! #define WTAP_FILE_CSIDS 23 /* last WTAP_FILE_ value + 1 */ ! #define WTAP_NUM_FILE_TYPES 24 /* * Maximum packet size we'll support.
- Follow-Ups:
- References:
- Re: [ethereal-dev] Re: [ethereal-users] Ethereal crash reading tcpdump '-r' file (FreeBSD 3.4)
- From: Gilbert Ramirez
- Re: [ethereal-dev] Re: [ethereal-users] Ethereal crash reading tcpdump '-r' file (FreeBSD 3.4)
- From: Guy Harris
- Re: [ethereal-dev] Re: [ethereal-users] Ethereal crash reading tcpdump '-r' file (FreeBSD 3.4)
- From: Guy Harris
- Re: [ethereal-dev] Re: [ethereal-users] Ethereal crash reading tcpdump '-r' file (FreeBSD 3.4)
- From: Marc Solsona Palomar
- Re: [ethereal-dev] Re: [ethereal-users] Ethereal crash reading tcpdump '-r' file (FreeBSD 3.4)
- Prev by Date: Re: [ethereal-dev] ECN = Explicit Congestion Notification
- Next by Date: Re: [ethereal-dev] Ethereal and H.323 dissector possible license solution
- Previous by thread: Re: [ethereal-dev] Re: [ethereal-users] Ethereal crash reading tcpdump '-r' file (FreeBSD 3.4)
- Next by thread: Re: [ethereal-dev] Re: [ethereal-users] Ethereal crash reading tcpdump '-r' file (FreeBSD 3.4)
- Index(es):