diff options
Diffstat (limited to 'wiretap/libpcap.c')
-rw-r--r-- | wiretap/libpcap.c | 256 |
1 files changed, 153 insertions, 103 deletions
diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c index e59115f925..25ed5466ed 100644 --- a/wiretap/libpcap.c +++ b/wiretap/libpcap.c @@ -1,6 +1,6 @@ /* libpcap.c * - * $Id: libpcap.c,v 1.35 2000/05/19 23:06:53 gram Exp $ + * $Id: libpcap.c,v 1.36 2000/07/26 06:04:32 guy Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@xiexie.org> @@ -84,6 +84,20 @@ struct pcaprec_modified_hdr { packet came in. */ guint16 protocol; /* Ethernet packet type */ guint8 pkt_type; /* broadcast/multicast/etc. indication */ + guint8 pad; /* pad to a 4-byte boundary */ +}; + +/* "libpcap" record header for Alexey's patched version in its ss990915 + incarnation; this version shows up in SuSE Linux 6.3. */ +struct pcaprec_ss990915_hdr { + struct pcaprec_hdr hdr; /* the regular header */ + guint32 ifindex; /* index, in *capturing* machine's list of + interfaces, of the interface on which this + packet came in. */ + guint16 protocol; /* Ethernet packet type */ + guint8 pkt_type; /* broadcast/multicast/etc. indication */ + guint8 cpu1, cpu2; /* SMP debugging gunk? */ + guint8 pad[3]; /* pad to a 4-byte boundary */ }; static int libpcap_read(wtap *wth, int *err); @@ -169,8 +183,9 @@ int libpcap_open(wtap *wth, int *err) struct pcap_hdr hdr; gboolean byte_swapped; gboolean modified; - struct pcaprec_hdr first_rec_hdr; - struct pcaprec_hdr second_rec_hdr; + 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); @@ -188,28 +203,31 @@ int libpcap_open(wtap *wth, int *err) switch (magic) { case PCAP_MAGIC: - /* Host that wrote it has our byte order. */ + /* Host that wrote it has our byte order, and was running + a program using either standard or ss990417 libpcap. */ byte_swapped = FALSE; modified = FALSE; break; case PCAP_MODIFIED_MAGIC: - /* Host that wrote it has our byte order, but was running - a program using the patched "libpcap". */ + /* Host that wrote it has our byte order, and was running + a program using either ss990915 or ss991029 libpcap. */ byte_swapped = FALSE; modified = TRUE; break; case PCAP_SWAPPED_MAGIC: - /* Host that wrote it has a byte order opposite to ours. */ + /* Host that wrote it has a byte order opposite to ours, + and was running a program using either standard or + ss990417 libpcap. */ byte_swapped = TRUE; modified = FALSE; break; case PCAP_SWAPPED_MODIFIED_MAGIC: /* Host that wrote it out has a byte order opposite to - ours, and was running a program using the patched - "libpcap". */ + ours, and was running a program using either ss990915 + or ss991029 libpcap. */ byte_swapped = TRUE; modified = TRUE; break; @@ -253,10 +271,9 @@ int libpcap_open(wtap *wth, int *err) } /* This is a libpcap file */ - wth->file_type = modified ? WTAP_FILE_PCAP_MODIFIED : WTAP_FILE_PCAP; + 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->modified = modified; wth->capture.pcap->version_major = hdr.version_major; wth->capture.pcap->version_minor = hdr.version_minor; wth->subtype_read = libpcap_read; @@ -266,101 +283,106 @@ int libpcap_open(wtap *wth, int *err) wth->snapshot_length = hdr.snaplen; /* - * Is this a capture file with the non-modified magic number? + * Yes. Let's look at the header for the first record, + * and see if, interpreting it as a standard header (if the + * magic number was standard) or a modified header (if the + * magic number was modified), the position where it says the + * header for the *second* record is contains a corrupted header. + * + * If so, then: + * + * If this file had the standard magic number, it may be + * an ss990417 capture file - in that version of Alexey's + * patch, the packet header format was changed but the + * magic number wasn't, and, alas, Red Hat appear to have + * picked up that version of the patch for RH 6.1, meaning + * RH 6.1 has a tcpdump that writes out files that can't + * be read by any software that expects non-modified headers + * if the magic number isn't the modified magic number (e.g., + * any normal version of tcpdump, and Ethereal if we don't + * do this gross heuristic). + * + * If this file had the modified magic number, it may be + * an ss990915 capture file - in that version of Alexey's + * patch, the magic number was changed, but the record + * header had some extra fields, and, alas, SuSE appear + * to have picked up that version of the patch for SuSE + * 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. */ - if (!wth->capture.pcap->modified) { + 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 */ + /* - * Yes. Let's look at the header for the first record, - * and see if, interpreting it as a non-modified header, - * the position where it says the header for the - * *second* record is contains a corrupted header. - * - * If so, this may be a modified capture file with a - * non-modified magic number - in some versions of - * Alexey's patches, the packet header format was - * changed but the magic number wasn't, and, alas, - * Red Hat appear to have picked up one of those - * patches for RH 6.1, meaning RH 6.1 has a "tcpdump" - * that writes out files that can't be read by any software - * that expects non-modified headers if the magic number isn't - * the modified magic number (e.g., any normal version of - * "tcpdump", and Ethereal if we don't do this gross - * heuristic). + * 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. */ - bytes_read = file_read(&first_rec_hdr, 1, - sizeof first_rec_hdr, wth->fh); - if (bytes_read != sizeof first_rec_hdr) { - *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); - - if (first_rec_hdr.incl_len > WTAP_MAX_PACKET_SIZE) { - /* - * The first record is bogus, so this is probably - * a corrupt file. Assume the file isn't modified, - * and put the seek pointer back. The attempt - * to read the first packet will probably get - * the same bogus length. - */ - goto give_up; - } + goto give_up; + } - file_seek(wth->fh, - wth->data_offset + sizeof first_rec_hdr + first_rec_hdr.incl_len, - SEEK_SET); - bytes_read = file_read(&second_rec_hdr, 1, - sizeof second_rec_hdr, wth->fh); + adjust_header(wth, &first_rec_hdr.hdr); + if (first_rec_hdr.hdr.incl_len > WTAP_MAX_PACKET_SIZE) { /* - * OK, does the next packet's header look sane? + * 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. */ - if (bytes_read != sizeof second_rec_hdr) { - *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 second packet will presumably get - * the same short read error. - */ - goto give_up; - } + goto give_up; + } - adjust_header(wth, &second_rec_hdr); - if (second_rec_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 a modified file; - * if that doesn't work, it probably *is* - * a corrupt file. - */ - wth->file_type = WTAP_FILE_PCAP_RH_6_1; - wth->capture.pcap->modified = TRUE; - } + 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 */ - give_up: /* - * Restore the seek pointer. + * 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. */ - file_seek(wth->fh, wth->data_offset, SEEK_SET); + 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; } @@ -369,13 +391,30 @@ static int libpcap_read(wtap *wth, int *err) { guint packet_size; int bytes_to_read, bytes_read; - struct pcaprec_modified_hdr hdr; + struct pcaprec_ss990915_hdr hdr; int data_offset; /* Read record header. */ errno = WTAP_ERR_CANT_READ; - bytes_to_read = wth->capture.pcap->modified ? - sizeof hdr : sizeof hdr.hdr; + switch (wth->file_type) { + + case WTAP_FILE_PCAP: + bytes_to_read = sizeof (struct pcaprec_hdr); + break; + + case WTAP_FILE_PCAP_SS990417: + case WTAP_FILE_PCAP_SS991029: + bytes_to_read = sizeof (struct pcaprec_modified_hdr); + break; + + case WTAP_FILE_PCAP_SS990915: + 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); @@ -518,11 +557,12 @@ gboolean libpcap_dump_open(wtap_dumper *wdh, int *err) switch (wdh->file_type) { case WTAP_FILE_PCAP: - case WTAP_FILE_PCAP_RH_6_1: /* modified, but with the old magic, sigh */ + case WTAP_FILE_PCAP_SS990417: /* modified, but with the old magic, sigh */ magic = PCAP_MAGIC; break; - case WTAP_FILE_PCAP_MODIFIED: + case WTAP_FILE_PCAP_SS990915: /* new magic, extra crap */ + case WTAP_FILE_PCAP_SS991029: magic = PCAP_MODIFIED_MAGIC; break; @@ -566,7 +606,7 @@ gboolean libpcap_dump_open(wtap_dumper *wdh, int *err) static gboolean libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, const union wtap_pseudo_header *pseudo_header, const u_char *pd, int *err) { - struct pcaprec_modified_hdr rec_hdr; + struct pcaprec_ss990915_hdr rec_hdr; int hdr_size; int nwritten; @@ -577,11 +617,11 @@ static gboolean libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, switch (wdh->file_type) { case WTAP_FILE_PCAP: - hdr_size = sizeof rec_hdr.hdr; + hdr_size = sizeof (struct pcaprec_hdr); break; - case WTAP_FILE_PCAP_RH_6_1: /* modified, but with the old magic, sigh */ - case WTAP_FILE_PCAP_MODIFIED: + case WTAP_FILE_PCAP_SS990417: /* modified, but with the old magic, sigh */ + case WTAP_FILE_PCAP_SS991029: /* XXX - what should we supply here? Alexey's "libpcap" looks up the interface in the system's @@ -604,12 +644,22 @@ static gboolean libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, rec_hdr.ifindex = 0; rec_hdr.protocol = 0; rec_hdr.pkt_type = 0; - hdr_size = sizeof rec_hdr; + hdr_size = sizeof (struct pcaprec_modified_hdr); + break; + + case WTAP_FILE_PCAP_SS990915: /* new 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_ss990915_hdr); break; default: /* We should never get here - our open routine should only get called for the types above. */ + g_assert_not_reached(); *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE; return FALSE; } |