diff options
Diffstat (limited to 'wiretap/network_instruments.c')
-rw-r--r-- | wiretap/network_instruments.c | 269 |
1 files changed, 154 insertions, 115 deletions
diff --git a/wiretap/network_instruments.c b/wiretap/network_instruments.c index 726c1b7d05..c6c19bec36 100644 --- a/wiretap/network_instruments.c +++ b/wiretap/network_instruments.c @@ -42,10 +42,6 @@ static const int observer_encap[] = { }; #define NUM_OBSERVER_ENCAPS (sizeof observer_encap / sizeof observer_encap[0]) -#define OBSERVER_UNDEFINED 0xFF -#define OBSERVER_ETHERNET 0x00 -#define OBSERVER_TOKENRING 0x01 -#define OBSERVER_FDDI 0x02 static const int from_wtap_encap[] = { OBSERVER_UNDEFINED, OBSERVER_ETHERNET, @@ -55,9 +51,6 @@ static const int from_wtap_encap[] = { #define CAPTUREFILE_HEADER_SIZE sizeof(capture_file_header) -#define INFORMATION_TYPE_ALIAS_LIST 0x01 -#define INFORMATION_TYPE_COMMENT 0x02 - /* * The time in Observer files is in nanoseconds since midnight, January 1, * 2000, 00:00:00 local time. @@ -95,12 +88,17 @@ static void init_time_offset(void) } } -static gboolean fill_time_struct(guint64 ns_since2000, observer_time* time_conversion); static gboolean observer_read(wtap *wth, int *err, gchar **err_info, long *data_offset); static gboolean observer_seek_read(wtap *wth, long seek_off, union wtap_pseudo_header *pseudo_header, guchar *pd, int length, int *err, gchar **err_info); +static int read_packet_header(FILE_T fh, packet_entry_header *packet_header, + int *err, gchar **err_info); +static gboolean read_packet_data(FILE_T fh, int offset_to_frame, int offset, + guint8 *pd, int length, int *err, char **err_info); +static gboolean skip_to_next_packet(wtap *wth, int offset, + int offset_to_next_packet, int *err, char **err_info); static gboolean observer_dump_close(wtap_dumper *wdh, int *err); static gboolean observer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err); @@ -165,7 +163,7 @@ int network_instruments_open(wtap *wth, int *err, gchar **err_info) /* Check the data link type. */ if (packet_header.network_type >= NUM_OBSERVER_ENCAPS) { *err = WTAP_ERR_UNSUPPORTED_ENCAP; - *err_info = g_strdup_printf("observer: network type %u unknown or unsupported", packet_header.network_type); + *err_info = g_strdup_printf("Observer: network type %u unknown or unsupported", packet_header.network_type); return -1; } wth->file_encap = observer_encap[packet_header.network_type]; @@ -198,13 +196,8 @@ int network_instruments_open(wtap *wth, int *err, gchar **err_info) static gboolean observer_read(wtap *wth, int *err, gchar **err_info, long *data_offset) { - int bytes_read; - long seek_increment; - long seconds, useconds; - + int offset; packet_entry_header packet_header; - - observer_time packet_time; /* * Skip records other than data records. @@ -212,87 +205,57 @@ static gboolean observer_read(wtap *wth, int *err, gchar **err_info, for (;;) { *data_offset = wth->data_offset; - /* pull off the packet header */ - bytes_read = file_read(&packet_header, sizeof packet_header, 1, wth->fh); - if (bytes_read != sizeof packet_header) { - *err = file_error(wth->fh); - if (*err != 0) - return -1; - return 0; - } - wth->data_offset += bytes_read; + /* process the packet header, including TLVs */ + offset = read_packet_header(wth->fh, &packet_header, err, + err_info); + if (offset <= 0) + return FALSE; /* EOF or error */ - /* check the packet's magic number; the magic number is all 8's, - so the byte order doesn't matter */ - if (packet_header.packet_magic != observer_packet_magic) { - *err = WTAP_ERR_BAD_RECORD; - *err_info = g_strdup_printf("Observer: bad record: Invalid magic number 0x%08x", - GUINT32_FROM_LE(packet_header.packet_magic)); - return FALSE; - } + wth->data_offset += offset; - /* check the packet's record type, and skip non-data - packets */ - if (packet_header.packet_type == TYPE_DATA_PACKET) + if (packet_header.packet_type == PACKET_TYPE_DATA_PACKET) break; /* skip to next packet */ packet_header.offset_to_next_packet = GUINT16_FROM_LE(packet_header.offset_to_next_packet); - if (packet_header.offset_to_next_packet < sizeof(packet_header)) { - *err = WTAP_ERR_BAD_RECORD; - *err_info = g_strdup_printf("Observer: bad record (offset to next packet %u < %lu)", - packet_header.offset_to_next_packet, - (unsigned long)sizeof(packet_header)); - return FALSE; - } - seek_increment = packet_header.offset_to_next_packet - sizeof(packet_header); - if(seek_increment>0) { - if (file_seek(wth->fh, seek_increment, SEEK_CUR, err) == -1) - return FALSE; - } - wth->data_offset += seek_increment; + if (!skip_to_next_packet(wth, offset, + packet_header.offset_to_next_packet, err, err_info)) + return FALSE; /* EOF or error */ } - /* convert from observer time to wiretap time */ - packet_header.nano_seconds_since_2000 = - GUINT64_FROM_LE(packet_header.nano_seconds_since_2000); - fill_time_struct(packet_header.nano_seconds_since_2000, &packet_time); - useconds = (long)(packet_time.useconds_from_1970 - ((guint64)packet_time.seconds_from_1970)*1000000); - seconds = (long)packet_time.seconds_from_1970; - /* set-up the packet header */ packet_header.network_size = GUINT16_FROM_LE(packet_header.network_size); + /* neglect frame markers for wiretap */ + if (packet_header.network_size < 4) { + *err = WTAP_ERR_BAD_RECORD; + *err_info = g_strdup_printf("Observer: bad record: Packet length %u < 4", + packet_header.network_size); + return FALSE; + } + packet_header.network_size -= 4; packet_header.captured_size = GUINT16_FROM_LE(packet_header.captured_size); wth->phdr.pkt_encap = observer_encap[packet_header.network_type]; - wth->phdr.len = packet_header.network_size-4; /* neglect frame markers for wiretap */ + wth->phdr.len = packet_header.network_size; wth->phdr.caplen = MIN(packet_header.captured_size, wth->phdr.len); - wth->phdr.ts.secs = seconds; - wth->phdr.ts.nsecs = useconds * 1000; - - /* get to the frame data */ - packet_header.offset_to_frame = - GUINT16_FROM_LE(packet_header.offset_to_frame); - if (packet_header.offset_to_frame < sizeof(packet_header)) { - *err = WTAP_ERR_BAD_RECORD; - *err_info = g_strdup_printf("Observer: bad record (offset to frame %u < %lu)", - packet_header.offset_to_frame, - (unsigned long)sizeof(packet_header)); - return FALSE; - } - seek_increment = packet_header.offset_to_frame - sizeof(packet_header); - if(seek_increment>0) { - if (file_seek(wth->fh, seek_increment, SEEK_CUR, err) == -1) - return FALSE; - } - wth->data_offset += seek_increment; + packet_header.nano_seconds_since_2000 = + GUINT64_FROM_LE(packet_header.nano_seconds_since_2000); + wth->phdr.ts.secs = + (time_t) (packet_header.nano_seconds_since_2000/1000000000 + seconds1970to2000); + wth->phdr.ts.nsecs = packet_header.nano_seconds_since_2000%1000000000; /* set-up the packet buffer */ buffer_assure_space(wth->frame_buffer, packet_header.captured_size); - wtap_file_read_expected_bytes(buffer_start_ptr(wth->frame_buffer), packet_header.captured_size, wth->fh, err); + + /* read data */ + if (!read_packet_data(wth->fh, packet_header.offset_to_frame, offset, + buffer_start_ptr(wth->frame_buffer), packet_header.captured_size, + err, err_info)) + return FALSE; wth->data_offset += packet_header.captured_size; + offset += packet_header.captured_size; /* update the pseudo header */ switch (wth->file_encap) { @@ -312,66 +275,142 @@ static gboolean observer_seek_read(wtap *wth, long seek_off, int *err, gchar **err_info) { packet_entry_header packet_header; - long seek_increment; - int bytes_read; + int offset; if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) return FALSE; + /* process the packet header, including TLVs */ + offset = read_packet_header(wth->random_fh, &packet_header, err, + err_info); + if (offset <= 0) + return FALSE; /* EOF or error */ + + /* read data */ + if (!read_packet_data(wth->random_fh, packet_header.offset_to_frame, + offset, pd, length, err, err_info)) + return FALSE; + + /* update 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; + } + + return TRUE; +} + +static int +read_packet_header(FILE_T fh, packet_entry_header *packet_header, int *err, + gchar **err_info) +{ + int offset; + int bytes_read; + guint i; + tlv_header tlvh; + int seek_increment; + + offset = 0; + /* pull off the packet header */ - bytes_read = file_read(&packet_header, sizeof packet_header, 1, wth->random_fh); - if (bytes_read != sizeof packet_header) { - *err = file_error(wth->fh); + bytes_read = file_read(packet_header, sizeof *packet_header, 1, fh); + if (bytes_read != sizeof *packet_header) { + *err = file_error(fh); if (*err != 0) return -1; - return 0; + return 0; /* EOF */ } + offset += bytes_read; - /* check the packets magic number */ - if (packet_header.packet_magic != observer_packet_magic) { + /* check the packet's magic number; the magic number is all 8's, + so the byte order doesn't matter */ + if (packet_header->packet_magic != observer_packet_magic) { *err = WTAP_ERR_BAD_RECORD; - *err_info = g_strdup("Observer: bad magic number for record in observer_seek_read"); - return FALSE; + *err_info = g_strdup_printf("Observer: bad record: Invalid magic number 0x%08x", + GUINT32_FROM_LE(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, 1, fh); + if (bytes_read != sizeof tlvh) { + *err = file_error(fh); + if (*err == 0) + *err = WTAP_ERR_SHORT_READ; + return -1; + } + offset += bytes_read; - /* get the frame offset */ - packet_header.offset_to_frame = - GUINT16_FROM_LE(packet_header.offset_to_frame); - seek_increment = packet_header.offset_to_frame - sizeof(packet_header); - if(seek_increment>0) { - if (file_seek(wth->random_fh, seek_increment, SEEK_CUR, err) == -1) - return FALSE; - } + tlvh.length = GUINT16_FROM_LE(tlvh.length); + if (tlvh.length < sizeof tlvh) { + *err = WTAP_ERR_BAD_RECORD; + *err_info = g_strdup_printf("Observer: bad record (TLV length %u < %lu)", + tlvh.length, (unsigned long)sizeof tlvh); + return -1; + } - /* read in the packet */ - bytes_read = file_read(pd, 1, length, wth->random_fh); - if (bytes_read != length) { - *err = file_error(wth->fh); - return FALSE; + /* skip the TLV data */ + seek_increment = tlvh.length - sizeof tlvh; + if(seek_increment>0) { + if (file_seek(fh, seek_increment, SEEK_CUR, err) == -1) + return -1; + } + offset += seek_increment; } - /* update the pseudo header */ - switch (wth->file_encap) { + packet_header->offset_to_frame = + GUINT16_FROM_LE(packet_header->offset_to_frame); - case WTAP_ENCAP_ETHERNET: - /* There is no FCS in the frame */ - pseudo_header->eth.fcs_len = 0; - break; + return offset; +} + +static gboolean +read_packet_data(FILE_T fh, int offset_to_frame, int offset, guint8 *pd, + int length, int *err, char **err_info) +{ + int seek_increment; + + /* get to the packet data */ + if (offset_to_frame < offset) { + *err = WTAP_ERR_BAD_RECORD; + *err_info = g_strdup_printf("Observer: bad record (offset to frame %d < %d)", + offset_to_frame, offset); + return FALSE; + } + seek_increment = offset_to_frame - offset; + if(seek_increment>0) { + if (file_seek(fh, seek_increment, SEEK_CUR, err) == -1) + return FALSE; } + /* read in the packet */ + wtap_file_read_expected_bytes(pd, length, fh, err); return TRUE; } -gboolean fill_time_struct(guint64 ns_since2000, observer_time* time_conversion) +static gboolean +skip_to_next_packet(wtap *wth, int offset, int offset_to_next_packet, int *err, + char **err_info) { - time_conversion->ns_since2000 = ns_since2000; - time_conversion->us_since2000 = ns_since2000/1000; - time_conversion->sec_since2000 = ns_since2000/1000000000; - - time_conversion->seconds_from_1970 = (time_t) (seconds1970to2000 + time_conversion->sec_since2000); - time_conversion->useconds_from_1970 = ((guint64)seconds1970to2000*1000000)+time_conversion->us_since2000; + int seek_increment; + if (offset_to_next_packet < offset) { + *err = WTAP_ERR_BAD_RECORD; + *err_info = g_strdup_printf("Observer: bad record (offset to next packet %d < %d)", + offset_to_next_packet, offset); + return FALSE; + } + seek_increment = offset_to_next_packet - offset; + if(seek_increment>0) { + if (file_seek(wth->fh, seek_increment, SEEK_CUR, err) == -1) + return FALSE; + } + wth->data_offset += seek_increment; return TRUE; } @@ -425,7 +464,7 @@ gboolean network_instruments_dump_open(wtap_dumper *wdh, gboolean cant_seek, int memset(&file_header, 0x00, sizeof(capture_file_header)); strcpy(file_header.observer_version, network_instruments_magic); file_header.offset_to_first_packet = sizeof(capture_file_header) + sizeof(tlv_header) + strlen(comment); - file_header.extra_information_present = 0x01; /* actually the number of information elements */ + file_header.number_of_information_elements = 1; if(!fwrite(&file_header, sizeof(capture_file_header), 1, wdh->fh)) { *err = errno; return FALSE; @@ -477,8 +516,8 @@ static gboolean observer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, packet_header.offset_to_next_packet = GUINT16_TO_LE(sizeof(packet_entry_header) + phdr->caplen); packet_header.network_type = niobserver->network_type; packet_header.flags = 0x00; - packet_header.extra_information = 0x00; - packet_header.packet_type = 0x00; + packet_header.number_of_information_elements = 0; + packet_header.packet_type = PACKET_TYPE_DATA_PACKET; packet_header.packet_number = GUINT64_TO_LE(niobserver->packet_count); packet_header.original_packet_number = GUINT64_TO_LE(niobserver->packet_count); niobserver->packet_count++; |