Exemplo n.º 1
0
/*
 * get_record: Get the next record into a buffer
 *   Every 8192 bytes 16 bytes are inserted in the file,
 *   even in the middle of a record.
 *   This reads the next record without the eventual 16 bytes.
 *   returns the length of the record + the stuffing (if any)
 *
 *   Returns number of bytes read on success, 0 on EOF, -1 on error;
 *   if -1 is returned, *err is set to the error indication and, for
 *   errors where that's appropriate, *err_info is set to an additional
 *   error string.
 *
 * XXX: works at most with 8191 bytes per record
 */
static gint get_record(k12_t *file_data, FILE_T fh, gint64 file_offset,
                       gboolean is_random, int *err, gchar **err_info) {
    guint8 *buffer = is_random ? file_data->rand_read_buff : file_data->seq_read_buff;
    guint buffer_len = is_random ? file_data->rand_read_buff_len : file_data->seq_read_buff_len;
    guint total_read = 0;
    guint left;
    guint8* writep;
#ifdef DEBUG_K12
    guint actual_len;
#endif

    /*
     * Where the next unknown 16 bytes are stuffed to the file.
     * Following the file header, they appear every 8192 bytes,
     * starting right after the file header, so if the file offset
     * relative to the file header is a multiple of 8192, the
     * 16-byte blob is there.
     */
    guint junky_offset = 8192 - (gint) ( (file_offset - K12_FILE_HDR_LEN) % 8192 );

    K12_DBG(6,("get_record: ENTER: junky_offset=%" G_GINT64_MODIFIER "d, file_offset=%" G_GINT64_MODIFIER "d",junky_offset,file_offset));

    /* no buffer is given, lets create it */
    if (buffer == NULL) {
        buffer = (guint8*)g_malloc(8192);
        buffer_len = 8192;
        if (is_random) {
            file_data->rand_read_buff = buffer;
            file_data->rand_read_buff_len = buffer_len;
        } else {
            file_data->seq_read_buff = buffer;
            file_data->seq_read_buff_len = buffer_len;
        }
    }

    if ( junky_offset == 8192 ) {
        /*
         * We're at the beginning of one of the 16-byte blobs,
         * so we first need to skip the blob.
         *
         * XXX - what if the blob is in the middle of the record
         * length?  If the record length is always a multiple of
         * 4 bytes, that won't happen.
         */
        if ( ! wtap_read_bytes( fh, NULL, K12_FILE_BLOB_LEN, err, err_info ) )
            return -1;
        total_read += K12_FILE_BLOB_LEN;
    }

    /*
     * Read the record length.
     */
    if ( !wtap_read_bytes( fh, buffer, 4, err, err_info ) )
        return -1;
    total_read += 4;

    left = pntoh32(buffer + K12_RECORD_LEN);
#ifdef DEBUG_K12
    actual_len = left;
#endif
    junky_offset -= 4;

    K12_DBG(5,("get_record: GET length=%u",left));

    /*
     * Record length must be at least large enough for the length
     * and type, hence 8 bytes.
     *
     * XXX - is WTAP_MAX_PACKET_SIZE_STANDARD the right check for a maximum
     * record size?  Should we report this error differently?
     */
    if (left < 8) {
        *err = WTAP_ERR_BAD_FILE;
        *err_info = g_strdup_printf("k12: Record length %u is less than 8 bytes long",left);
        return -1;
    }
    if (left > WTAP_MAX_PACKET_SIZE_STANDARD) {
        *err = WTAP_ERR_BAD_FILE;
        *err_info = g_strdup_printf("k12: Record length %u is greater than the maximum %u",left,WTAP_MAX_PACKET_SIZE_STANDARD);
        return -1;
    }

    /*
     * XXX - calculate the lowest power of 2 >= left, rather than just
     * looping.
     */
    while (left > buffer_len) {
        buffer = (guint8*)g_realloc(buffer,buffer_len*=2);
        if (is_random) {
            file_data->rand_read_buff = buffer;
            file_data->rand_read_buff_len = buffer_len;
        } else {
            file_data->seq_read_buff = buffer;
            file_data->seq_read_buff_len = buffer_len;
        }
    }

    writep = buffer + 4;
    left -= 4;

    /* Read the rest of the record. */
    do {
        K12_DBG(6,("get_record: looping left=%d junky_offset=%" G_GINT64_MODIFIER "d",left,junky_offset));

        if (junky_offset > left) {
            /*
             * The next 16-byte blob is past the end of this record.
             * Just read the rest of the record.
             */
            if ( !wtap_read_bytes( fh, writep, left, err, err_info ) )
                return -1;
            total_read += left;
            break;
        } else {
            /*
             * The next 16-byte blob is part of this record.
             * Read up to the blob.
             */
            if ( !wtap_read_bytes( fh, writep, junky_offset, err, err_info ) )
                return -1;

            total_read += junky_offset;
            writep += junky_offset;

            /*
             * Skip the blob.
             */
            if ( !wtap_read_bytes( fh, NULL, K12_FILE_BLOB_LEN, err, err_info ) )
                return -1;
            total_read += K12_FILE_BLOB_LEN;

            left -= junky_offset;
            junky_offset = 8192;
        }

    } while(left);

    K12_HEX_ASCII_DUMP(5,file_offset, "GOT record", buffer, actual_len);
    return total_read;
}
Exemplo n.º 2
0
/*
 * get_record: Get the next record into a buffer
 *   Every about 0x2000 bytes 0x10 bytes are inserted in the file,
 *   even in the middle of a record.
 *   This reads the next record without the eventual 0x10 bytes.
 *   returns the length of the record + the stuffing (if any)
 *
 *   Returns number of bytes read on success, 0 on EOF, -1 on error;
 *   if -1 is returned, *err is set to the error indication and, for
 *   errors where that's appropriate, *err_info is set to an additional
 *   error string.
 *
 * XXX: works at most with 0x1FFF bytes per record
 */
static gint get_record(k12_t *file_data, FILE_T fh, gint64 file_offset,
                       gboolean is_random, int *err, gchar **err_info) {
    guint8 *buffer = is_random ? file_data->rand_read_buff : file_data->seq_read_buff;
    guint buffer_len = is_random ? file_data->rand_read_buff_len : file_data->seq_read_buff_len;
    guint bytes_read;
    guint last_read;
    guint left;
    guint8 junk[0x14];
    guint8* writep;
#ifdef DEBUG_K12
    guint actual_len;
#endif

    /* where the next unknown 0x10 bytes are stuffed to the file */
    guint junky_offset = 0x2000 - (gint) ( (file_offset - 0x200) % 0x2000 );

    K12_DBG(6,("get_record: ENTER: junky_offset=%" G_GINT64_MODIFIER "d, file_offset=%" G_GINT64_MODIFIER "d",junky_offset,file_offset));

    /* no buffer is given, lets create it */
    if (buffer == NULL) {
        buffer = (guint8*)g_malloc(0x2000);
        buffer_len = 0x2000;
        if (is_random) {
            file_data->rand_read_buff = buffer;
            file_data->rand_read_buff_len = buffer_len;
        } else {
            file_data->seq_read_buff = buffer;
            file_data->seq_read_buff_len = buffer_len;
        }
    }

    /* Get the record length. */
    if ( junky_offset == 0x2000 ) {
        /* the length of the record is 0x10 bytes ahead from we are reading */
        bytes_read = file_read(junk,0x14,fh);

        if (bytes_read == 2 && junk[0] == 0xff && junk[1] == 0xff) {
            K12_DBG(1,("get_record: EOF"));
            return 0;
        } else if ( bytes_read < 0x14 ) {
            K12_DBG(1,("get_record: SHORT READ OR ERROR"));
            *err = file_error(fh, err_info);
            if (*err == 0) {
                *err = WTAP_ERR_SHORT_READ;
            }
            return -1;
        }

        memcpy(buffer,&(junk[0x10]),4);
    } else {
        /* the length of the record is right where we are reading */
        bytes_read = file_read(buffer, 0x4, fh);

        if (bytes_read == 2 && buffer[0] == 0xff && buffer[1] == 0xff) {
            K12_DBG(1,("get_record: EOF"));
            return 0;
        } else if (bytes_read == 4 && buffer[0] == 0xff && buffer[1] == 0xff
                   && buffer[2] == 0x00 && buffer[3] == 0x00) {
            /*
             * In at least one k18 RF5 file, there appears to be a "record"
             * with a length value of 0xffff0000, followed by a bunch of
             * data that doesn't appear to be records, including a long
             * list of numbers.
             *
             * We treat a length value of 0xffff0000 as an end-of-file
             * indication.
             *
             * XXX - is this a length indication, or will it appear
             * at the beginning of an 8KB block, so that we should
             * check for it above?
             */
            K12_DBG(1,("get_record: EOF"));
            return 0;
        } else if ( bytes_read != 0x4 ) {
            K12_DBG(1,("get_record: SHORT READ OR ERROR"));
            *err = file_error(fh, err_info);
            if (*err == 0) {
                *err = WTAP_ERR_SHORT_READ;
            }
            return -1;
        }
    }

    left = pntoh32(buffer + K12_RECORD_LEN);
#ifdef DEBUG_K12
    actual_len = left;
#endif
    junky_offset -= 0x4;

    K12_DBG(5,("get_record: GET length=%u",left));

    /*
     * Record length must be at least large enough for the length,
     * hence 4 bytes.
     *
     * XXX - Is WTAP_MAX_PACKET_SIZE the right check for a maximum
     * record size?  Should we report this error differently?
     */
    if (left < 4 || left > WTAP_MAX_PACKET_SIZE) {
        K12_DBG(1,("get_record: Invalid GET length=%u",left));
        *err = WTAP_ERR_BAD_FILE;
        *err_info = g_strdup_printf("get_record: Invalid GET length=%u",left);
        return -1;
    }

    /*
     * XXX - calculate the lowest power of 2 >= left, rather than just
     * looping.
     */
    while (left > buffer_len) {
        buffer = (guint8*)g_realloc(buffer,buffer_len*=2);
        if (is_random) {
            file_data->rand_read_buff = buffer;
            file_data->rand_read_buff_len = buffer_len;
        } else {
            file_data->seq_read_buff = buffer;
            file_data->seq_read_buff_len = buffer_len;
        }
    }

    writep = buffer + 4;
    left -= 4;

    /* Read the rest of the record. */
    do {
        K12_DBG(6,("get_record: looping left=%d junky_offset=%" G_GINT64_MODIFIER "d",left,junky_offset));

        if (junky_offset > left) {
            bytes_read += last_read = file_read(writep, left, fh);

            if ( last_read != left ) {
                K12_DBG(1,("get_record: SHORT READ OR ERROR"));
                *err = file_error(fh, err_info);
                if (*err == 0) {
                    *err = WTAP_ERR_SHORT_READ;
                }
                return -1;
            } else {
                K12_HEX_ASCII_DUMP(5,file_offset, "GOT record", buffer, actual_len);
                return bytes_read;
            }
        } else {
            bytes_read += last_read = file_read(writep, junky_offset, fh);

            if ( last_read != junky_offset ) {
                K12_DBG(1,("get_record: SHORT READ OR ERROR, read=%d expected=%d",last_read, junky_offset));
                *err = file_error(fh, err_info);
                if (*err == 0) {
                    *err = WTAP_ERR_SHORT_READ;
                }
                return -1;
            }

            writep += last_read;

            bytes_read += last_read = file_read(junk, 0x10, fh);

            if ( last_read != 0x10 ) {
                K12_DBG(1,("get_record: SHORT READ OR ERROR"));
                *err = file_error(fh, err_info);
                if (*err == 0) {
                    *err = WTAP_ERR_SHORT_READ;
                }
                return -1;
            }

            left -= junky_offset;
            junky_offset = 0x2000;
        }

    } while(left);

    K12_HEX_ASCII_DUMP(5,file_offset, "GOT record", buffer, actual_len);
    return bytes_read;
}