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; }
/* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on failure. */ gboolean network_instruments_dump_open(wtap_dumper *wdh, int *err) { observer_dump_private_state * private_state = NULL; capture_file_header file_header; tlv_header comment_header; tlv_time_info time_header; char comment[64]; size_t comment_length; struct tm * current_time; time_t system_time; /* initialize the private state */ private_state = (observer_dump_private_state *) g_malloc(sizeof(observer_dump_private_state)); private_state->packet_count = 0; private_state->network_type = wtap_to_observer_encap(wdh->encap); private_state->time_format = TIME_INFO_GMT; /* populate the fields of wdh */ wdh->priv = (void *) private_state; wdh->subtype_write = observer_dump; /* 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; /* create the file comment TLV */ { time(&system_time); current_time = localtime(&system_time); memset(&comment, 0x00, sizeof(comment)); g_snprintf(comment, 64, "This capture was saved from Wireshark on %s", asctime(current_time)); comment_length = strlen(comment); comment_header.type = INFORMATION_TYPE_COMMENT; comment_header.length = (guint16) (sizeof(comment_header) + comment_length); /* 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; } /* create the timestamp encoding TLV */ { time_header.type = INFORMATION_TYPE_TIME_INFO; time_header.length = (guint16) (sizeof(time_header)); time_header.time_format = TIME_INFO_GMT; /* 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; } /* 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)) { return FALSE; } wdh->bytes_dumped += sizeof(file_header); /* write the comment TLV */ { TLV_HEADER_TO_LE_IN_PLACE(comment_header); if (!wtap_dump_file_write(wdh, &comment_header, sizeof(comment_header), err)) { return FALSE; } wdh->bytes_dumped += sizeof(comment_header); if (!wtap_dump_file_write(wdh, &comment, comment_length, err)) { return FALSE; } wdh->bytes_dumped += comment_length; } /* write the time info TLV */ { TLV_TIME_INFO_TO_LE_IN_PLACE(time_header); if (!wtap_dump_file_write(wdh, &time_header, sizeof(time_header), err)) { return FALSE; } wdh->bytes_dumped += sizeof(time_header); } init_gmt_to_localtime_offset(); return TRUE; }
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; }