aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2010-07-18 19:41:11 +0000
committerGuy Harris <guy@alum.mit.edu>2010-07-18 19:41:11 +0000
commit6cb47bde7a4ed676ec1631f467e5734f4a259810 (patch)
tree72e79dd9d5111121f90d76f6c3e5f3357d2546bc /wiretap
parent6722384a7dce8e95abf339e0b5402c96e9418cba (diff)
Initial support for the trailer information in versions 2.1 and later of
the NetMon file format. Currently, we just use the network type field, and we ignore all the special record types and don't try to handle any of the other special network types. We also catch bogus frame tables where the record is bigger than the frame table says it is. svn path=/trunk/; revision=33572
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/netmon.c154
1 files changed, 135 insertions, 19 deletions
diff --git a/wiretap/netmon.c b/wiretap/netmon.c
index d255b16bac..082731794e 100644
--- a/wiretap/netmon.c
+++ b/wiretap/netmon.c
@@ -95,6 +95,30 @@ struct netmonrec_2_x_hdr {
};
/*
+ * Network Monitor 2.1 and later record trailers; documented in the Network
+ * Monitor 3.x help files, for 3.3 and later, although they don't clearly
+ * state how the trailer format changes from version to version.
+ *
+ * Some fields are multi-byte integers, but they're not aligned on their
+ * natural boundaries.
+ */
+struct netmonrec_2_1_trlr {
+ guint8 network[2]; /* network type for this packet */
+};
+
+struct netmonrec_2_2_trlr {
+ guint8 network[2]; /* network type for this packet */
+ guint8 process_info_index[4]; /* index into the process info table */
+};
+
+struct netmonrec_2_3_trlr {
+ guint8 network[2]; /* network type for this packet */
+ guint8 process_info_index[4]; /* index into the process info table */
+ guint8 utc_timestamp[8]; /* packet time stamp, as .1 us units since January 1, 1601, 00:00:00 UTC */
+ guint8 timezone_index; /* index of time zone information */
+};
+
+/*
* The link-layer header on ATM packets.
*/
struct netmon_atm_hdr {
@@ -108,11 +132,39 @@ typedef struct {
time_t start_secs;
guint32 start_usecs;
guint8 version_major;
+ guint8 version_minor;
guint32 *frame_table;
guint32 frame_table_size;
guint current_frame;
} netmon_t;
+static const int netmon_encap[] = {
+ WTAP_ENCAP_UNKNOWN,
+ WTAP_ENCAP_ETHERNET,
+ WTAP_ENCAP_TOKEN_RING,
+ WTAP_ENCAP_FDDI_BITSWAPPED,
+ WTAP_ENCAP_ATM_PDUS, /* NDIS WAN - this is what's used for ATM */
+ WTAP_ENCAP_UNKNOWN, /* NDIS LocalTalk */
+ WTAP_ENCAP_UNKNOWN, /* NDIS "DIX" - should not occur */
+ WTAP_ENCAP_UNKNOWN, /* NDIS ARCNET raw */
+ WTAP_ENCAP_UNKNOWN, /* NDIS ARCNET 878.2 */
+ WTAP_ENCAP_UNKNOWN, /* NDIS ATM (no, this is NOT used for ATM) */
+ WTAP_ENCAP_UNKNOWN, /* NDIS Wireless WAN */
+ WTAP_ENCAP_UNKNOWN /* NDIS IrDA */
+};
+#define NUM_NETMON_ENCAPS (sizeof netmon_encap / sizeof netmon_encap[0])
+
+/*
+ * Special link-layer types.
+ */
+#define NETMON_NET_LINUX_SLL 0xE071
+#define NETMON_NET_NETEVENT 0xFFE0
+#define NETMON_NET_NETWORK_INFO_EX 0xFFFB
+#define NETMON_NET_PAYLOAD_HEADER 0xFFFC
+#define NETMON_NET_NETWORK_INFO 0xFFFD
+#define NETMON_NET_DNS_CACHE 0xFFFE
+#define NETMON_NET_NETMON_FILTER 0xFFFF
+
static gboolean netmon_read(wtap *wth, int *err, gchar **err_info,
gint64 *data_offset);
static gboolean netmon_seek_read(wtap *wth, gint64 seek_off,
@@ -133,21 +185,6 @@ int netmon_open(wtap *wth, int *err, gchar **err_info)
char magic[sizeof netmon_1_x_magic];
struct netmon_hdr hdr;
int file_type;
- static const int netmon_encap[] = {
- WTAP_ENCAP_UNKNOWN,
- WTAP_ENCAP_ETHERNET,
- WTAP_ENCAP_TOKEN_RING,
- WTAP_ENCAP_FDDI_BITSWAPPED,
- WTAP_ENCAP_ATM_PDUS, /* NDIS WAN - this is what's used for ATM */
- WTAP_ENCAP_UNKNOWN, /* NDIS LocalTalk */
- WTAP_ENCAP_UNKNOWN, /* NDIS "DIX" - should not occur */
- WTAP_ENCAP_UNKNOWN, /* NDIS ARCNET raw */
- WTAP_ENCAP_UNKNOWN, /* NDIS ARCNET 878.2 */
- WTAP_ENCAP_UNKNOWN, /* NDIS ATM (no, this is NOT used for ATM) */
- WTAP_ENCAP_UNKNOWN, /* NDIS Wireless WAN */
- WTAP_ENCAP_UNKNOWN /* NDIS IrDA */
- };
- #define NUM_NETMON_ENCAPS (sizeof netmon_encap / sizeof netmon_encap[0])
struct tm tm;
int frame_table_offset;
guint32 frame_table_length;
@@ -219,10 +256,8 @@ int netmon_open(wtap *wth, int *err, gchar **err_info)
/* NetMon capture file formats v2.1+ use per-packet encapsulation types. NetMon 3 sets the value in
* the header to 1 (Ethernet) for backwards compability. */
- /* XXX - It would be better if we could set this to WTAP_ENCAP_PER_PACKET and show a message for
- * that, but the wtap_read() routine asserts on that value to catch errors. */
if((hdr.ver_major == 2 && hdr.ver_minor >= 1) || hdr.ver_major > 2)
- wth->file_encap = WTAP_ENCAP_UNKNOWN;
+ wth->file_encap = WTAP_ENCAP_PER_PACKET;
else
wth->file_encap = netmon_encap[hdr.network];
@@ -256,6 +291,7 @@ int netmon_open(wtap *wth, int *err, gchar **err_info)
netmon->start_usecs = pletohs(&hdr.ts_msec)*1000;
netmon->version_major = hdr.ver_major;
+ netmon->version_minor = hdr.ver_minor;
/*
* Get the offset of the frame index table.
@@ -334,13 +370,21 @@ static gboolean netmon_read(wtap *wth, int *err, gchar **err_info,
struct netmonrec_1_x_hdr hdr_1_x;
struct netmonrec_2_x_hdr hdr_2_x;
} hdr;
+ union {
+ struct netmonrec_2_1_trlr trlr_2_1;
+ struct netmonrec_2_2_trlr trlr_2_2;
+ struct netmonrec_2_3_trlr trlr_2_3;
+ } trlr;
int hdr_size = 0;
+ int trlr_size = 0;
int rec_offset;
guint8 *data_ptr;
time_t secs;
guint32 usecs;
double t;
+ guint16 network;
+again:
/* Have we reached the end of the packet data? */
if (netmon->current_frame >= netmon->frame_table_size) {
/* Yes. We won't need the frame table any more;
@@ -354,9 +398,17 @@ static gboolean netmon_read(wtap *wth, int *err, gchar **err_info,
/* Seek to the beginning of the current record, if we're
not there already (seeking to the current position
may still cause a seek and a read of the underlying file,
- so we don't want to do it unconditionally). */
+ so we don't want to do it unconditionally).
+
+ If the beginning of the current record is *before* the
+ current position, that's an error. */
rec_offset = netmon->frame_table[netmon->current_frame];
if (wth->data_offset != rec_offset) {
+ if (rec_offset < wth->data_offset) {
+ *err = WTAP_ERR_BAD_RECORD;
+ *err_info = g_strdup("netmon: Record offset is in the middle of an earlier record");
+ return FALSE;
+ }
wth->data_offset = rec_offset;
if (file_seek(wth->fh, wth->data_offset, SEEK_SET, err) == -1)
return FALSE;
@@ -485,6 +537,70 @@ static gboolean netmon_read(wtap *wth, int *err, gchar **err_info,
&wth->pseudo_header);
}
+ /*
+ * For version 2.1 and later, there's additional information
+ * after the frame data.
+ */
+ if ((netmon->version_major == 2 && netmon->version_minor >= 1) ||
+ netmon->version_major > 2) {
+ if (netmon->version_major > 2) {
+ /*
+ * Asssume 2.3 format, for now.
+ */
+ trlr_size = sizeof (struct netmonrec_2_3_trlr);
+ } else {
+ switch (netmon->version_minor) {
+
+ case 1:
+ trlr_size = sizeof (struct netmonrec_2_1_trlr);
+ break;
+
+ case 2:
+ trlr_size = sizeof (struct netmonrec_2_2_trlr);
+ break;
+
+ default:
+ trlr_size = sizeof (struct netmonrec_2_3_trlr);
+ break;
+ }
+ }
+ errno = WTAP_ERR_CANT_READ;
+
+ bytes_read = file_read(&trlr, 1, trlr_size, wth->fh);
+ if (bytes_read != trlr_size) {
+ *err = file_error(wth->fh);
+ if (*err == 0 && bytes_read != 0) {
+ *err = WTAP_ERR_SHORT_READ;
+ }
+ return FALSE;
+ }
+ wth->data_offset += trlr_size;
+
+ network = pletohs(trlr.trlr_2_1.network);
+ if (network >= NUM_NETMON_ENCAPS
+ || netmon_encap[network] == WTAP_ENCAP_UNKNOWN) {
+ switch (network) {
+
+ case NETMON_NET_NETEVENT:
+ case NETMON_NET_NETWORK_INFO_EX:
+ case NETMON_NET_PAYLOAD_HEADER:
+ case NETMON_NET_NETWORK_INFO:
+ case NETMON_NET_DNS_CACHE:
+ case NETMON_NET_NETMON_FILTER:
+ /*
+ * Just ignore those record types, for
+ * now. Read the next record.
+ */
+ goto again;
+ }
+ *err = WTAP_ERR_UNSUPPORTED_ENCAP;
+ *err_info = g_strdup_printf("netmon: network type %u unknown or unsupported",
+ network);
+ return FALSE;
+ }
+ wth->phdr.pkt_encap = netmon_encap[network];
+ }
+
return TRUE;
}