aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap/network_instruments.c
diff options
context:
space:
mode:
Diffstat (limited to 'wiretap/network_instruments.c')
-rw-r--r--wiretap/network_instruments.c126
1 files changed, 93 insertions, 33 deletions
diff --git a/wiretap/network_instruments.c b/wiretap/network_instruments.c
index 45cfc06b1c..e4ad8b94fc 100644
--- a/wiretap/network_instruments.c
+++ b/wiretap/network_instruments.c
@@ -118,12 +118,12 @@ static gint wtap_to_observer_encap(int wtap_encap);
wtap_open_return_val network_instruments_open(wtap *wth, int *err, gchar **err_info)
{
- int offset;
+ guint offset;
capture_file_header file_header;
+ guint header_offset;
guint i;
tlv_header tlvh;
- int seek_increment;
- int header_offset;
+ guint seek_increment;
packet_entry_header packet_header;
observer_dump_private_state * private_state = NULL;
@@ -136,7 +136,7 @@ wtap_open_return_val network_instruments_open(wtap *wth, int *err, gchar **err_i
return WTAP_OPEN_ERROR;
return WTAP_OPEN_NOT_MINE;
}
- offset += (int)sizeof file_header;
+ offset += (guint)sizeof file_header;
CAPTURE_FILE_HEADER_FROM_LE_IN_PLACE(file_header);
/* check if version info is present */
@@ -144,25 +144,46 @@ wtap_open_return_val network_instruments_open(wtap *wth, int *err, gchar **err_i
return WTAP_OPEN_NOT_MINE;
}
+ /* get the location of the first packet */
+ /* v15 and newer uses high byte offset, in previous versions it will be 0 */
+ header_offset = file_header.offset_to_first_packet + ((guint)(file_header.offset_to_first_packet_high_byte)<<16);
+
+ if (offset > header_offset) {
+ /*
+ * The packet data begins before the file header ends.
+ */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("Observer: The first packet begins in the middle of the file header");
+ return WTAP_OPEN_ERROR;
+ }
+
/* initialize the private state */
private_state = (observer_dump_private_state *) g_malloc(sizeof(observer_dump_private_state));
private_state->time_format = TIME_INFO_LOCAL;
wth->priv = (void *) private_state;
- /* get the location of the first packet */
- /* v15 and newer uses high byte offset, in previous versions it will be 0 */
- header_offset = file_header.offset_to_first_packet + ((int)(file_header.offset_to_first_packet_high_byte)<<16);
-
/* process extra information */
for (i = 0; i < file_header.number_of_information_elements; i++) {
- /* for safety break if we've reached the first packet */
- if (offset >= header_offset)
- break;
+ guint tlv_data_length;
+
+ /*
+ * Make sure reading the TLV header won't put us in the middle
+ * of the packet data.
+ */
+ if (offset + (guint)sizeof tlvh > header_offset) {
+ /*
+ * We're at or past the point where the packet data begins,
+ * but we have the IE header to read.
+ */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("Observer: TLVs run into the first packet data");
+ return WTAP_OPEN_ERROR;
+ }
/* read the TLV header */
if (!wtap_read_bytes(wth->fh, &tlvh, sizeof tlvh, err, err_info))
return WTAP_OPEN_ERROR;
- offset += (int)sizeof tlvh;
+ offset += (guint)sizeof tlvh;
TLV_HEADER_FROM_LE_IN_PLACE(tlvh);
if (tlvh.length < sizeof tlvh) {
@@ -172,44 +193,80 @@ wtap_open_return_val network_instruments_open(wtap *wth, int *err, gchar **err_i
return WTAP_OPEN_ERROR;
}
+ tlv_data_length = tlvh.length - (guint)sizeof tlvh;
+ /*
+ * Make sure reading the TLV data won't put us in the middle
+ * of the packet data.
+ */
+ if (offset + tlv_data_length > header_offset) {
+ /*
+ * We're at or past the point where the packet data begins,
+ * but we have the IE data to read.
+ */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("Observer: TLVs run into the first packet data");
+ return WTAP_OPEN_ERROR;
+ }
+
+
/* process (or skip over) the current TLV */
switch (tlvh.type) {
case INFORMATION_TYPE_TIME_INFO:
- /* XXX - what if tlvh.length != sizeof sizeof private_state->time_format? */
+ if (tlvh.length != sizeof tlvh + sizeof private_state->time_format) {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("Observer: bad record (time information TLV length %u != %lu)",
+ tlvh.length,
+ (unsigned long)(sizeof tlvh + sizeof private_state->time_format));
+ return WTAP_OPEN_ERROR;
+ }
if (!wtap_read_bytes(wth->fh, &private_state->time_format,
sizeof private_state->time_format,
err, err_info))
return WTAP_OPEN_ERROR;
private_state->time_format = GUINT32_FROM_LE(private_state->time_format);
- offset += (int)sizeof private_state->time_format;
+ offset += (guint)sizeof private_state->time_format;
break;
default:
- seek_increment = tlvh.length - (int)sizeof tlvh;
- if (seek_increment > 0) {
- if (!wtap_read_bytes(wth->fh, NULL, seek_increment, err, err_info))
+ tlv_data_length = tlvh.length - (guint)sizeof tlvh;
+ if (tlv_data_length > 0) {
+ if (!wtap_read_bytes(wth->fh, NULL, tlv_data_length, err, err_info))
return WTAP_OPEN_ERROR;
}
- offset += seek_increment;
+ offset += tlv_data_length;
}
}
/* get to the first packet */
- if (header_offset < offset) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup_printf("Observer: bad record (offset to first packet %d < %d)",
- header_offset, offset);
- return WTAP_OPEN_ERROR;
- }
seek_increment = header_offset - offset;
- if (seek_increment > 0) {
+ if (seek_increment != 0) {
if (!wtap_read_bytes(wth->fh, NULL, seek_increment, err, err_info))
return WTAP_OPEN_ERROR;
}
- /* pull off the packet header */
- if (!wtap_read_bytes(wth->fh, &packet_header, sizeof packet_header,
- err, err_info))
+ /*
+ * We assume that all packets in a file have the same network type,
+ * whether they're data or expert information packets, and thus
+ * we can attempt to determine the network type by reading the
+ * first packet.
+ *
+ * If that's *not* the case, we need to use WTAP_ENCAP_PER_PACKET.
+ *
+ * Read the packet header. Don't assume there *is* a packet;
+ * if there isn't, report that as a bad file. (If we use
+ * WTAP_ENCAP_PER_PACKET, we don't need to handle that case, as
+ * we don't need to read the first packet.
+ */
+ if (!wtap_read_bytes_or_eof(wth->fh, &packet_header, sizeof packet_header,
+ err, err_info)) {
+ if (*err == 0) {
+ /*
+ * EOF, so there *are* no records.
+ */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("Observer: No records in the file, so we can't determine the link-layer type");
+ }
return WTAP_OPEN_ERROR;
+ }
PACKET_ENTRY_HEADER_FROM_LE_IN_PLACE(packet_header);
/* check the packet's magic number */
@@ -603,7 +660,7 @@ gboolean network_instruments_dump_open(wtap_dumper *wdh, int *err)
{
observer_dump_private_state * private_state = NULL;
capture_file_header file_header;
-
+ guint header_offset;
tlv_header comment_header;
tlv_time_info time_header;
char comment[64];
@@ -624,8 +681,7 @@ gboolean network_instruments_dump_open(wtap_dumper *wdh, int *err)
/* initialize the file header */
memset(&file_header, 0x00, sizeof(file_header));
g_strlcpy(file_header.observer_version, network_instruments_magic, 31);
- file_header.offset_to_first_packet = (guint16)sizeof(file_header);
- file_header.offset_to_first_packet_high_byte = 0;
+ header_offset = (guint16)sizeof(file_header);
/* create the file comment TLV */
{
@@ -643,7 +699,7 @@ gboolean network_instruments_dump_open(wtap_dumper *wdh, int *err)
/* update the file header to account for the comment TLV */
file_header.number_of_information_elements++;
- file_header.offset_to_first_packet += comment_header.length;
+ header_offset += comment_header.length;
}
/* create the timestamp encoding TLV */
@@ -654,9 +710,13 @@ gboolean network_instruments_dump_open(wtap_dumper *wdh, int *err)
/* update the file header to account for the timestamp encoding TLV */
file_header.number_of_information_elements++;
- file_header.offset_to_first_packet += time_header.length;
+ header_offset += time_header.length;
}
+ /* Store the offset to the first packet */
+ file_header.offset_to_first_packet_high_byte = (header_offset >> 16);
+ file_header.offset_to_first_packet = (header_offset & 0xFFFF);
+
/* write the file header, swapping any multibyte fields first */
CAPTURE_FILE_HEADER_TO_LE_IN_PLACE(file_header);
if (!wtap_dump_file_write(wdh, &file_header, sizeof(file_header), err)) {