#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. */
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 */
guint16 unknown5; /* 0x00 0x00 */
- guint8 count1; /* count1*4 bytes values after unknown8 */
+ guint8 count1; /* count1*4 bytes after unknown8 */
guint8 count2; /* count2*4 bytes after that */
guint16 unknown7; /* 0x01 0x10 */
guint32 unknown8; /* 0x00 0x00 0x00 0x00 or random numbers */
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;
* 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.
/*
* 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;
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) - 1;
- if (!wtap_read_bytes_or_eof(wth->fh, &capsa->record_offsets,
+ capsa->base_offset = file_tell(wth->fh);
+ if (!file_skip(wth->fh, 1, err))
+ return FALSE;
+
+ /*
+ * Now read the 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;
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;
}
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)
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:
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 = (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.
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:
+ */