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;
}
Example #2
0
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;
}