Beispiel #1
0
/* Reads the next packet. */
static gboolean observer_read(wtap *wth, int *err, gchar **err_info,
    gint64 *data_offset)
{
    int header_bytes_consumed;
    int data_bytes_consumed;
    packet_entry_header packet_header;

    /* skip records other than data records */
    for (;;) {
        *data_offset = file_tell(wth->fh);

        /* process the packet header, including TLVs */
        header_bytes_consumed = read_packet_header(wth->fh, &wth->pseudo_header, &packet_header, err,
            err_info);
        if (header_bytes_consumed <= 0)
            return FALSE;    /* EOF or error */

        if (packet_header.packet_type == PACKET_TYPE_DATA_PACKET)
            break;

        /* skip to next packet */
        if (!skip_to_next_packet(wth, packet_header.offset_to_next_packet,
                header_bytes_consumed, err, err_info)) {
            return FALSE;    /* EOF or error */
        }
    }

    /* neglect frame markers for wiretap */
    if (packet_header.network_size < 4) {
        *err = WTAP_ERR_BAD_FILE;
        *err_info = g_strdup_printf("Observer: bad record: Packet length %u < 4",
            packet_header.network_size);
        return FALSE;
    }

    /* set the wiretap packet header fields */
    wth->phdr.presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
    wth->phdr.pkt_encap = observer_to_wtap_encap(packet_header.network_type);
    if(wth->file_encap == WTAP_ENCAP_FIBRE_CHANNEL_FC2_WITH_FRAME_DELIMS) {
        wth->phdr.len = packet_header.network_size;
        wth->phdr.caplen = packet_header.captured_size;
    } else {
        wth->phdr.len = packet_header.network_size - 4;
        wth->phdr.caplen = MIN(packet_header.captured_size, wth->phdr.len);
    }

    /* set the wiretap timestamp, assuming for the moment that Observer encoded it in GMT */
    wth->phdr.ts.secs = (time_t) ((packet_header.nano_seconds_since_2000 / 1000000000) + ansi_to_observer_epoch_offset);
    wth->phdr.ts.nsecs = (int) (packet_header.nano_seconds_since_2000 % 1000000000);

    /* adjust to local time, if necessary, also accounting for DST if the frame
       was captured while it was in effect */
    if (((observer_dump_private_state*)wth->priv)->time_format == TIME_INFO_LOCAL)
    {
        struct tm daylight_tm;
        struct tm standard_tm;
        time_t    dst_offset;

        /* the Observer timestamp was encoded as local time, so add a
           correction from local time to GMT */
        wth->phdr.ts.secs += gmt_to_localtime_offset;

        /* perform a DST adjustment if necessary */
        standard_tm = *localtime(&wth->phdr.ts.secs);
        if (standard_tm.tm_isdst > 0) {
            daylight_tm = standard_tm;
            standard_tm.tm_isdst = 0;
            dst_offset = mktime(&standard_tm) - mktime(&daylight_tm);
            wth->phdr.ts.secs -= dst_offset;
        }
    }

    /* update the pseudo header */
    switch (wth->file_encap) {
    case WTAP_ENCAP_ETHERNET:
        /* There is no FCS in the frame */
        wth->pseudo_header.eth.fcs_len = 0;
        break;
    case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
        /* Updated in read_packet_header */
        break;
    }

    /* set-up the packet buffer */
    buffer_assure_space(wth->frame_buffer, packet_header.captured_size);

    /* read the frame data */
    data_bytes_consumed = read_packet_data(wth->fh, packet_header.offset_to_frame,
            header_bytes_consumed, buffer_start_ptr(wth->frame_buffer),
            packet_header.captured_size, err, err_info);
    if (data_bytes_consumed < 0) {
        return FALSE;
    }

    /* skip over any extra bytes following the frame data */
    if (!skip_to_next_packet(wth, packet_header.offset_to_next_packet,
            header_bytes_consumed + data_bytes_consumed, err, err_info)) {
        return FALSE;
    }

    return TRUE;
}
Beispiel #2
0
int network_instruments_open(wtap *wth, int *err, gchar **err_info)
{
    int bytes_read;
    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;

    errno = WTAP_ERR_CANT_READ;
    offset = 0;

    /* read in the buffer file header */
    bytes_read = file_read(&file_header, sizeof file_header, wth->fh);
    if (bytes_read != sizeof file_header) {
        *err = file_error(wth->fh, err_info);
        if (*err != 0)
            return -1;
        return 0;
    }
    offset += bytes_read;
    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 0;
    }

    /* 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 */
        bytes_read = file_read(&tlvh, sizeof tlvh, wth->fh);
        if (bytes_read != sizeof tlvh) {
            *err = file_error(wth->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_TIME_INFO:
            bytes_read = file_read(&private_state->time_format, sizeof private_state->time_format, wth->fh);
            if (bytes_read != sizeof private_state->time_format) {
                *err = file_error(wth->fh, err_info);
                if(*err == 0)
                    *err = WTAP_ERR_SHORT_READ;
                return -1;
            }
            private_state->time_format = GUINT32_FROM_LE(private_state->time_format);
            offset += bytes_read;
            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 -1;
            }
            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 FALSE;
    }
    seek_increment = header_offset - offset;
    if (seek_increment > 0) {
        if (file_seek(wth->fh, seek_increment, SEEK_CUR, err) == -1)
            return -1;
    }

    /* pull off the packet header */
    bytes_read = file_read(&packet_header, sizeof packet_header, wth->fh);
    if (bytes_read != sizeof packet_header) {
        *err = file_error(wth->fh, err_info);
        if (*err != 0)
            return -1;
        return 0;
    }
    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_ENCAP;
        *err_info = g_strdup_printf("Observer: unsupported packet version %ul", packet_header.packet_magic);
        return -1;
    }

    /* check the data link type */
    if (observer_to_wtap_encap(packet_header.network_type) == WTAP_ENCAP_UNKNOWN) {
        *err = WTAP_ERR_UNSUPPORTED_ENCAP;
        *err_info = g_strdup_printf("Observer: network type %u unknown or unsupported", packet_header.network_type);
        return -1;
    }
    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->tsprecision = WTAP_FILE_TSPREC_NSEC;
    wth->file_type = WTAP_FILE_NETWORK_INSTRUMENTS;

    /* reset the pointer to the first packet */
    if (file_seek(wth->fh, header_offset, SEEK_SET, err) == -1)
        return -1;

    init_gmt_to_localtime_offset();

    return 1;
}
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;
}
static gboolean
process_packet_header(wtap *wth, packet_entry_header *packet_header,
    wtap_rec *rec, int *err, gchar **err_info)
{
    /* set the wiretap record metadata fields */
    rec->rec_type = REC_TYPE_PACKET;
    rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
    rec->rec_header.packet_header.pkt_encap = observer_to_wtap_encap(packet_header->network_type);
    if(wth->file_encap == WTAP_ENCAP_FIBRE_CHANNEL_FC2_WITH_FRAME_DELIMS) {
        rec->rec_header.packet_header.len = packet_header->network_size;
        rec->rec_header.packet_header.caplen = packet_header->captured_size;
    } else {
        /*
         * XXX - what are those 4 bytes?
         *
         * The comment in the code said "neglect frame markers for wiretap",
         * but in the captures I've seen, there's no actual data corresponding
         * to them that might be a "frame marker".
         *
         * Instead, the packets had a network_size 4 bytes larger than the
         * captured_size; does the network_size include the CRC, even
         * though it's not included in a capture?  If so, most other
         * network analyzers that have a "network size" and a "captured
         * size" don't include the CRC in the "network size" if they
         * don't include the CRC in a full-length captured packet; the
         * "captured size" is less than the "network size" only if a
         * user-specified "snapshot length" caused the packet to be
         * sliced at a particular point.
         *
         * That's the model that wiretap and Wireshark/TShark use, so
         * we implement that model here.
         */
        if (packet_header->network_size < 4) {
            *err = WTAP_ERR_BAD_FILE;
            *err_info = g_strdup_printf("Observer: bad record: Packet length %u < 4",
                                        packet_header->network_size);
            return FALSE;
        }

        rec->rec_header.packet_header.len = packet_header->network_size - 4;
        rec->rec_header.packet_header.caplen = MIN(packet_header->captured_size, rec->rec_header.packet_header.len);
    }
    /*
     * The maximum value of packet_header->captured_size is 65535, which
     * is less than WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need
     * to check it.
     */

    /* set the wiretap timestamp, assuming for the moment that Observer encoded it in GMT */
    rec->ts.secs = (time_t) ((packet_header->nano_seconds_since_2000 / 1000000000) + ansi_to_observer_epoch_offset);
    rec->ts.nsecs = (int) (packet_header->nano_seconds_since_2000 % 1000000000);

    /* adjust to local time, if necessary, also accounting for DST if the frame
       was captured while it was in effect */
    if (((observer_dump_private_state*)wth->priv)->time_format == TIME_INFO_LOCAL)
    {
        struct tm *tm;
        struct tm daylight_tm;
        struct tm standard_tm;
        time_t    dst_offset;

        /* the Observer timestamp was encoded as local time, so add a
           correction from local time to GMT */
        rec->ts.secs += gmt_to_localtime_offset;

        /* perform a DST adjustment if necessary */
        tm = localtime(&rec->ts.secs);
        if (tm != NULL) {
            standard_tm = *tm;
            if (standard_tm.tm_isdst > 0) {
                daylight_tm = standard_tm;
                standard_tm.tm_isdst = 0;
                dst_offset = mktime(&standard_tm) - mktime(&daylight_tm);
                 rec->ts.secs -= dst_offset;
            }
        }
    }

    return TRUE;
}
static gboolean
process_packet_header(wtap *wth, packet_entry_header *packet_header,
    struct wtap_pkthdr *phdr, int *err, gchar **err_info)
{
    /* set the wiretap packet header fields */
    phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
    phdr->pkt_encap = observer_to_wtap_encap(packet_header->network_type);
    if(wth->file_encap == WTAP_ENCAP_FIBRE_CHANNEL_FC2_WITH_FRAME_DELIMS) {
        phdr->len = packet_header->network_size;
        phdr->caplen = packet_header->captured_size;
    } else {
        /*
         * XXX - what are those 4 bytes?
         *
         * The comment in the code said "neglect frame markers for wiretap",
         * but in the captures I've seen, there's no actual data corresponding
         * to them that might be a "frame marker".
         *
         * Instead, the packets had a network_size 4 bytes larger than the
         * captured_size; does the network_size include the CRC, even
         * though it's not included in a capture?  If so, most other
         * network analyzers that have a "network size" and a "captured
         * size" don't include the CRC in the "network size" if they
         * don't include the CRC in a full-length captured packet; the
         * "captured size" is less than the "network size" only if a
         * user-specified "snapshot length" caused the packet to be
         * sliced at a particular point.
         *
         * That's the model that wiretap and Wireshark/TShark use, so
         * we implement that model here.
         */
        if (packet_header->network_size < 4) {
            *err = WTAP_ERR_BAD_FILE;
            *err_info = g_strdup_printf("Observer: bad record: Packet length %u < 4",
                                        packet_header->network_size);
            return FALSE;
        }

        phdr->len = packet_header->network_size - 4;
        phdr->caplen = MIN(packet_header->captured_size, phdr->len);
    }

    /* set the wiretap timestamp, assuming for the moment that Observer encoded it in GMT */
    phdr->ts.secs = (time_t) ((packet_header->nano_seconds_since_2000 / 1000000000) + ansi_to_observer_epoch_offset);
    phdr->ts.nsecs = (int) (packet_header->nano_seconds_since_2000 % 1000000000);

    /* adjust to local time, if necessary, also accounting for DST if the frame
       was captured while it was in effect */
    if (((observer_dump_private_state*)wth->priv)->time_format == TIME_INFO_LOCAL)
    {
        struct tm daylight_tm;
        struct tm standard_tm;
        time_t    dst_offset;

        /* the Observer timestamp was encoded as local time, so add a
           correction from local time to GMT */
        phdr->ts.secs += gmt_to_localtime_offset;

        /* perform a DST adjustment if necessary */
        standard_tm = *localtime(&phdr->ts.secs);
        if (standard_tm.tm_isdst > 0) {
            daylight_tm = standard_tm;
            standard_tm.tm_isdst = 0;
            dst_offset = mktime(&standard_tm) - mktime(&daylight_tm);
            phdr->ts.secs -= dst_offset;
        }
    }

    /* update the pseudo header */
    switch (wth->file_encap) {
    case WTAP_ENCAP_ETHERNET:
        /* There is no FCS in the frame */
        phdr->pseudo_header.eth.fcs_len = 0;
        break;
    case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
        /* Updated in read_packet_header */
        break;
    }

    return TRUE;
}