Return the same error for too-large packets as we do for other files.
[metze/wireshark/wip.git] / wiretap / capsa.c
index d02983ef0dded5c76cb360006394268a92fcb432..6f6ea15d30c0292edf7ffd0e3ffa94a9028de74d 100644 (file)
@@ -23,7 +23,6 @@
 #include <string.h>
 #include "wtap-int.h"
 #include "file_wrappers.h"
-#include <wsutil/buffer.h>
 #include "capsa.h"
 
 /*
  *
  *   a 4-byte magic number, with 'c', 'p', 's', 'e';
  *
- *   a 1-byte or 2-byte "format indicator" (version number?) - if it's
- *   1-byte, it's followed by 0x00;
+ *   either a 2-byte little-endian "format indicator" (version number?),
+ *   or a 1-byte major version number followed by a 1-byte minor version
+ *   number, or a 1-byte "format indicator" followed by something else
+ *   that's always been 0;
  *
  *   a 2-byte 0xe8 0x03 (1000 - a data rate?  megabits/second?)
  *
- *   a 2-byte 0x01 0x00;
+ *   4 bytes of 0x01 0x00 0x01 0x00;
  *
- *   a 2-byte 0x01 0x00;
- *
- *   a 4-byte little-endian file size;
- *
- *   a 4-byte 0x00 0x00 0x00 0x00;
+ *   either a 4-byte little-endian file size followed by 0x00 0x00 0x00 0x00
+ *   or an 8-byte little-endian file size;
  *
  *   a 4-byte little-endian packet count (in dns_error_of_udp, it exceeds?)
  *
  * Following that is a sequence of { record offset block, up to 200 records }
  * pairs.
  *
- * A record offset block has 4 bytes of unknown data, a sequence of 4-byte
- * little-endian record offsets, and other data making the block 808 bytes
- * long.  The record offsets are offsets, from the byte just *before* the
- * sequence of record offsets, of the records following the block.
+ * A record offset block has 1 byte with the value 0xfe, a sequence of
+ * up to 200 4-byte little-endian record offsets, and 4 or more bytes
+ * of unknown data, making the block 805 bytes long.
+ *
+ * The record offsets are offsets, from the beginning of the record offset
+ * block (i.e., from the 0xfe byte), of the records following the block.
  */
 
 /* Magic number in Capsa files. */
@@ -83,8 +83,8 @@ static const char capsa_magic[] = {
 struct capsarec_hdr {
        guint32 unknown1;       /* low-order 32 bits of a number? */
        guint32 unknown2;       /* 0x00 0x00 0x00 0x00 */
-       guint32 timestamplo;    /* low-order 32 bits of a time stamp, in microseconds */
-       guint32 timestamphi;    /* high-order 32 bits of a time stamp, in microseconds */
+       guint32 timestamplo;    /* low-order 32 bits of the time stamp, in microseconds since January 1, 1970, 00:00:00 UTC */
+       guint32 timestamphi;    /* high-order 32 bits of the time stamp, in microseconds since January 1, 1970, 00:00:00 UTC */
        guint16 rec_len;        /* length of record */
        guint16 incl_len;       /* number of octets captured in file */
        guint16 orig_len;       /* actual length of packet */
@@ -104,14 +104,14 @@ struct pbrec_hdr {
        guint16 unknown2;
        guint16 unknown3;
        guint32 unknown4;
-       guint32 timestamplo;    /* low-order 32 bits of a time stamp, in microseconds */
-       guint32 timestamphi;    /* high-order 32 bits of a time stamp, in microseconds */
+       guint32 timestamplo;    /* low-order 32 bits of the time stamp, in microseconds since January 1, 1970, 00:00:00 UTC */
+       guint32 timestamphi;    /* high-order 32 bits of the time stamp, in microseconds since January 1, 1970, 00:00:00 UTC */
        guint32 unknown5;
        guint32 unknown6;
 };
 
 typedef struct {
-       guint8 format_indicator;
+       guint16 format_indicator;
        guint32 number_of_frames;
        guint32 frame_count;
        gint64 base_offset;
@@ -174,25 +174,27 @@ wtap_open_return_val capsa_open(wtap *wth, int *err, gchar **err_info)
         * Link speed, in megabytes/second?
         */
        if (!file_skip(wth->fh, 2, err))
-               return FALSE;
+               return WTAP_OPEN_ERROR;
 
        /*
-        * Flags of some sort?
+        * Flags of some sort?  Four 1-byte numbers, two of which are 1
+        * and two of which are zero?  Two 2-byte numbers or flag fields,
+        * both of which are 1?
         */
        if (!file_skip(wth->fh, 4, err))
-               return FALSE;
+               return WTAP_OPEN_ERROR;
 
        /*
-        * File size.
+        * File size, in bytes.
         */
        if (!file_skip(wth->fh, 4, err))
-               return FALSE;
+               return WTAP_OPEN_ERROR;
 
        /*
-        * Zeroes?
+        * Zeroes?  Or upper 4 bytes of file size?
         */
        if (!file_skip(wth->fh, 4, err))
-               return FALSE;
+               return WTAP_OPEN_ERROR;
 
        /*
         * Count of packets.
@@ -205,7 +207,7 @@ wtap_open_return_val capsa_open(wtap *wth, int *err, gchar **err_info)
        /*
         * Skip past what we think is file header.
         */
-       if (!file_seek(wth->fh, 0x44f0, SEEK_SET, err))
+       if (!file_seek(wth->fh, 0x44ef, SEEK_SET, err))
                return WTAP_OPEN_ERROR;
 
        wth->file_type_subtype = file_type_subtype;
@@ -245,16 +247,23 @@ static gboolean capsa_read(wtap *wth, int *err, gchar **err_info,
        if (frame_within_block == 0) {
                /*
                 * Here's a record offset block.
-                * Offsets in the block are relative to the offset
-                * after those 4 bytes, minus 1(!).
+                * Get the offset of the block, and then skip the
+                * first byte.
+                */
+               capsa->base_offset = file_tell(wth->fh);
+               if (!file_skip(wth->fh, 1, err))
+                       return FALSE;
+
+               /*
+                * Now read the record offsets.
                 */
-               capsa->base_offset = file_tell(wth->fh) - 1;
-               if (!wtap_read_bytes_or_eof(wth->fh, &capsa->record_offsets,
+               if (!wtap_read_bytes(wth->fh, &capsa->record_offsets,
                    sizeof capsa->record_offsets, err, err_info))
                        return FALSE;
 
                /*
-                * Skip the last 4 bytes; it's some unknown data.
+                * And finish processing all 805 bytes by skipping
+                * the last 4 bytes.
                 */
                if (!file_skip(wth->fh, 4, err))
                        return FALSE;
@@ -280,17 +289,6 @@ static gboolean capsa_read(wtap *wth, int *err, gchar **err_info,
 
        capsa->frame_count++;
 
-       /*
-        * Is this the last record within a group?
-        */
-       if (frame_within_block == N_RECORDS_PER_GROUP - 1) {
-               /*
-                * Skip 1 extra byte.
-                */
-               if (!file_skip(wth->fh, 1, err))
-                       return FALSE;
-       }
-
        return TRUE;
 }
 
@@ -309,14 +307,6 @@ capsa_seek_read(wtap *wth, gint64 seek_off,
        return TRUE;
 }
 
-/*
- * Number of seconds between the UN*X epoch (January 1, 1970, 00:00:00 GMT)
- * and the Windows NT epoch (January 1, 1601, 00:00:00 "GMT").
- *
- * XXX - this is not the correct time origin.
- */
-#define TIME_FIXUP_CONSTANT G_GUINT64_CONSTANT(11644473600)
-
 static int
 capsa_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
     Buffer *buf, int *err, gchar **err_info)
@@ -364,6 +354,15 @@ capsa_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
                packet_size = GUINT16_FROM_LE(pbrec_hdr.incl_len);
                header_size = sizeof pbrec_hdr;
                timestamp = (((guint64)GUINT32_FROM_LE(pbrec_hdr.timestamphi))<<32) + GUINT32_FROM_LE(pbrec_hdr.timestamplo);
+               /*
+                * XXX - from the results of some conversions between
+                * Capsa format and pcap by Colasoft Packet Builder,
+                * I do not trust its conversion of time stamps (at
+                * least one of Colasoft's sample files, when
+                * converted to pcap format, has, as its time stamps,
+                * time stamps on the day after the conversion was
+                * done, which seems like more than just coincidence).
+                */
                break;
 
        default:
@@ -417,12 +416,11 @@ capsa_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
        phdr->pseudo_header.eth.fcs_len = 0;
 
        phdr->rec_type = REC_TYPE_PACKET;
-       phdr->presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_TS;
-       timestamp -= TIME_FIXUP_CONSTANT;
-       phdr->ts.secs = timestamp / 1000000;
-       phdr->ts.nsecs = ((int)(timestamp % 1000000))*1000;
        phdr->caplen = packet_size;
        phdr->len = orig_size;
+       phdr->presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_TS;
+       phdr->ts.secs = (time_t)(timestamp / 1000000);
+       phdr->ts.nsecs = ((int)(timestamp % 1000000))*1000;
 
        /*
         * Read the packet data.
@@ -432,3 +430,16 @@ capsa_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
 
        return rec_size - (header_size + packet_size);
 }
+
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */