static int read_packet_header(wtap *wth, FILE_T fh, union wtap_pseudo_header *pseudo_header, packet_entry_header *packet_header, int *err, gchar **err_info) { int offset; guint i; tlv_header tlvh; int seek_increment; tlv_wireless_info wireless_header; offset = 0; /* pull off the packet header */ if (!wtap_read_bytes_or_eof(fh, packet_header, sizeof *packet_header, err, err_info)) { if (*err != 0) return -1; return 0; /* EOF */ } offset += (int)sizeof *packet_header; PACKET_ENTRY_HEADER_FROM_LE_IN_PLACE(*packet_header); /* check the packet's magic number */ if (packet_header->packet_magic != observer_packet_magic) { /* * Some files are zero-padded at the end. There is no warning of this * in the previous packet header information, such as setting * offset_to_next_packet to zero. So detect this situation by treating * an all-zero header as a sentinel. Return EOF when it is encountered, * rather than treat it as a bad record. */ for (i = 0; i < sizeof *packet_header; i++) { if (((guint8*) packet_header)[i] != 0) break; } if (i == sizeof *packet_header) { *err = 0; return 0; /* EOF */ } *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("Observer: bad record: Invalid magic number 0x%08x", packet_header->packet_magic); return -1; } /* initialize the pseudo header */ switch (wth->file_encap) { case WTAP_ENCAP_ETHERNET: /* There is no FCS in the frame */ pseudo_header->eth.fcs_len = 0; break; case WTAP_ENCAP_IEEE_802_11_WITH_RADIO: memset(&pseudo_header->ieee_802_11, 0, sizeof(pseudo_header->ieee_802_11)); pseudo_header->ieee_802_11.fcs_len = 0; pseudo_header->ieee_802_11.decrypted = FALSE; pseudo_header->ieee_802_11.datapad = FALSE; pseudo_header->ieee_802_11.phy = PHDR_802_11_PHY_UNKNOWN; /* Updated below */ break; } /* process extra information */ for (i = 0; i < packet_header->number_of_information_elements; i++) { /* read the TLV header */ if (!wtap_read_bytes(fh, &tlvh, sizeof tlvh, err, err_info)) return -1; 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 -1; } /* process (or skip over) the current TLV */ switch (tlvh.type) { case INFORMATION_TYPE_WIRELESS: if (!wtap_read_bytes(fh, &wireless_header, sizeof wireless_header, err, err_info)) return -1; /* set decryption status */ /* XXX - what other bits are there in conditions? */ pseudo_header->ieee_802_11.decrypted = (wireless_header.conditions & WIRELESS_WEP_SUCCESS) != 0; pseudo_header->ieee_802_11.has_channel = TRUE; pseudo_header->ieee_802_11.channel = wireless_header.frequency; pseudo_header->ieee_802_11.has_data_rate = TRUE; pseudo_header->ieee_802_11.data_rate = wireless_header.rate; pseudo_header->ieee_802_11.has_signal_percent = TRUE; pseudo_header->ieee_802_11.signal_percent = wireless_header.strengthPercent; offset += (int)sizeof wireless_header; break; default: /* skip the TLV data */ seek_increment = tlvh.length - (int)sizeof tlvh; if (seek_increment > 0) { if (file_seek(fh, seek_increment, SEEK_CUR, err) == -1) return -1; } offset += seek_increment; } } return offset; }
static int read_packet_header(FILE_T fh, union wtap_pseudo_header *pseudo_header, packet_entry_header *packet_header, int *err, gchar **err_info) { int offset; int bytes_read; guint i; tlv_header tlvh; int seek_increment; tlv_wireless_info wireless_header; offset = 0; /* pull off the packet header */ bytes_read = file_read(packet_header, sizeof *packet_header, fh); if (bytes_read != sizeof *packet_header) { *err = file_error(fh, err_info); if (*err != 0) return -1; return 0; /* EOF */ } offset += bytes_read; PACKET_ENTRY_HEADER_FROM_LE_IN_PLACE(*packet_header); /* check the packet's magic number */ if (packet_header->packet_magic != observer_packet_magic) { /* * Some files are zero-padded at the end. There is no warning of this * in the previous packet header information, such as setting * offset_to_next_packet to zero. So detect this situation by treating * an all-zero header as a sentinel. Return EOF when it is encountered, * rather than treat it as a bad record. */ for (i = 0; i < sizeof *packet_header; i++) { if (((guint8*) packet_header)[i] != 0) break; } if (i == sizeof *packet_header) { *err = 0; return 0; /* EOF */ } *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("Observer: bad record: Invalid magic number 0x%08x", packet_header->packet_magic); return -1; } /* process extra information */ for (i = 0; i < packet_header->number_of_information_elements; i++) { /* read the TLV header */ bytes_read = file_read(&tlvh, sizeof tlvh, fh); if (bytes_read != sizeof tlvh) { *err = file_error(fh, err_info); if (*err == 0) *err = WTAP_ERR_SHORT_READ; return -1; } offset += bytes_read; 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 -1; } /* process (or skip over) the current TLV */ switch (tlvh.type) { case INFORMATION_TYPE_WIRELESS: bytes_read = file_read(&wireless_header, sizeof wireless_header, fh); if (bytes_read != sizeof wireless_header) { *err = file_error(fh, err_info); if(*err == 0) *err = WTAP_ERR_SHORT_READ; return -1; } /* update the pseudo header */ pseudo_header->ieee_802_11.fcs_len = 0; /* set decryption status */ pseudo_header->ieee_802_11.decrypted = (wireless_header.conditions & WIRELESS_WEP_SUCCESS) != 0; pseudo_header->ieee_802_11.channel = wireless_header.frequency; pseudo_header->ieee_802_11.data_rate = wireless_header.rate; pseudo_header->ieee_802_11.signal_level = wireless_header.strengthPercent; offset += bytes_read; break; default: /* skip the TLV data */ seek_increment = tlvh.length - (int)sizeof tlvh; if (seek_increment > 0) { if (file_seek(fh, seek_increment, SEEK_CUR, err) == -1) return -1; } offset += seek_increment; } } return offset; }
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; }