diff options
Diffstat (limited to 'wiretap/network_instruments.c')
-rw-r--r-- | wiretap/network_instruments.c | 126 |
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)) { |