wtap_open_return_val network_instruments_open(wtap *wth, int *err, gchar **err_info) { int offset; capture_file_header file_header; guint i; tlv_header tlvh; int seek_increment; int header_offset; packet_entry_header packet_header; observer_dump_private_state * private_state = NULL; offset = 0; /* read in the buffer file header */ if (!wtap_read_bytes(wth->fh, &file_header, sizeof file_header, err, err_info)) { if (*err != WTAP_ERR_SHORT_READ) return WTAP_OPEN_ERROR; return WTAP_OPEN_NOT_MINE; } offset += (int)sizeof file_header; CAPTURE_FILE_HEADER_FROM_LE_IN_PLACE(file_header); /* check if version info is present */ if (memcmp(file_header.observer_version, network_instruments_magic, true_magic_length)!=0) { return WTAP_OPEN_NOT_MINE; } /* 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; /* read the TLV header */ if (!wtap_read_bytes(wth->fh, &tlvh, sizeof tlvh, err, err_info)) return WTAP_OPEN_ERROR; offset += (int)sizeof tlvh; TLV_HEADER_FROM_LE_IN_PLACE(tlvh); if (tlvh.length < sizeof tlvh) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("Observer: bad record (TLV length %u < %lu)", tlvh.length, (unsigned long)sizeof tlvh); return WTAP_OPEN_ERROR; } /* process (or skip over) the current TLV */ switch (tlvh.type) { case INFORMATION_TYPE_TIME_INFO: 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; break; default: seek_increment = tlvh.length - (int)sizeof tlvh; if (seek_increment > 0) { if (file_seek(wth->fh, seek_increment, SEEK_CUR, err) == -1) return WTAP_OPEN_ERROR; } offset += seek_increment; } } /* 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 (file_seek(wth->fh, seek_increment, SEEK_CUR, err) == -1) return WTAP_OPEN_ERROR; } /* pull off the packet header */ if (!wtap_read_bytes(wth->fh, &packet_header, sizeof packet_header, err, err_info)) return WTAP_OPEN_ERROR; PACKET_ENTRY_HEADER_FROM_LE_IN_PLACE(packet_header); /* check the packet's magic number */ if (packet_header.packet_magic != observer_packet_magic) { *err = WTAP_ERR_UNSUPPORTED; *err_info = g_strdup_printf("Observer: unsupported packet version %ul", packet_header.packet_magic); return WTAP_OPEN_ERROR; } /* check the data link type */ if (observer_to_wtap_encap(packet_header.network_type) == WTAP_ENCAP_UNKNOWN) { *err = WTAP_ERR_UNSUPPORTED; *err_info = g_strdup_printf("Observer: network type %u unknown or unsupported", packet_header.network_type); return WTAP_OPEN_ERROR; } wth->file_encap = observer_to_wtap_encap(packet_header.network_type); /* set up the rest of the capture parameters */ private_state->packet_count = 0; private_state->network_type = wtap_to_observer_encap(wth->file_encap); wth->subtype_read = observer_read; wth->subtype_seek_read = observer_seek_read; wth->subtype_close = NULL; wth->subtype_sequential_close = NULL; wth->snapshot_length = 0; /* not available in header */ wth->file_tsprec = WTAP_TSPREC_NSEC; wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_NETWORK_INSTRUMENTS; /* reset the pointer to the first packet */ if (file_seek(wth->fh, header_offset, SEEK_SET, err) == -1) return WTAP_OPEN_ERROR; init_gmt_to_localtime_offset(); return WTAP_OPEN_MINE; }
wtap_open_return_val network_instruments_open(wtap *wth, int *err, gchar **err_info) { guint offset; capture_file_header file_header; guint header_offset; guint i; tlv_header tlvh; guint seek_increment; packet_entry_header packet_header; observer_dump_private_state * private_state = NULL; offset = 0; /* read in the buffer file header */ if (!wtap_read_bytes(wth->fh, &file_header, sizeof file_header, err, err_info)) { if (*err != WTAP_ERR_SHORT_READ) return WTAP_OPEN_ERROR; return WTAP_OPEN_NOT_MINE; } offset += (guint)sizeof file_header; CAPTURE_FILE_HEADER_FROM_LE_IN_PLACE(file_header); /* check if version info is present */ if (memcmp(file_header.observer_version, network_instruments_magic, true_magic_length)!=0) { 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; /* process extra information */ for (i = 0; i < file_header.number_of_information_elements; i++) { 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 += (guint)sizeof tlvh; TLV_HEADER_FROM_LE_IN_PLACE(tlvh); if (tlvh.length < sizeof tlvh) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("Observer: bad record (TLV length %u < %lu)", tlvh.length, (unsigned long)sizeof tlvh); 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: 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 += (guint)sizeof private_state->time_format; break; default: 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 += tlv_data_length; } } /* get to the first packet */ seek_increment = header_offset - offset; if (seek_increment != 0) { if (!wtap_read_bytes(wth->fh, NULL, seek_increment, err, err_info)) return WTAP_OPEN_ERROR; } /* * 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 */ if (packet_header.packet_magic != observer_packet_magic) { *err = WTAP_ERR_UNSUPPORTED; *err_info = g_strdup_printf("Observer: unsupported packet version %ul", packet_header.packet_magic); return WTAP_OPEN_ERROR; } /* check the data link type */ if (observer_to_wtap_encap(packet_header.network_type) == WTAP_ENCAP_UNKNOWN) { *err = WTAP_ERR_UNSUPPORTED; *err_info = g_strdup_printf("Observer: network type %u unknown or unsupported", packet_header.network_type); return WTAP_OPEN_ERROR; } wth->file_encap = observer_to_wtap_encap(packet_header.network_type); /* set up the rest of the capture parameters */ private_state->packet_count = 0; private_state->network_type = wtap_to_observer_encap(wth->file_encap); wth->subtype_read = observer_read; wth->subtype_seek_read = observer_seek_read; wth->subtype_close = NULL; wth->subtype_sequential_close = NULL; wth->snapshot_length = 0; /* not available in header */ wth->file_tsprec = WTAP_TSPREC_NSEC; wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_NETWORK_INSTRUMENTS; /* reset the pointer to the first packet */ if (file_seek(wth->fh, header_offset, SEEK_SET, err) == -1) return WTAP_OPEN_ERROR; if (init_gmt_to_localtime_offset() != NULL) { *err = WTAP_ERR_INTERNAL; /* * XXX - we should return the error string, so the caller * can report the details of the internal error, but that * would require plugin file readers to do so for internal * errors as well, which could break binary compatibility; * we'll do that in the next release. */ return WTAP_OPEN_ERROR; } return WTAP_OPEN_MINE; }