static gboolean k12_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info) { k12_t *k12 = (k12_t *)wth->priv; guint8* buffer; gint len; gboolean status; K12_DBG(5,("k12_seek_read: ENTER")); if ( file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) { K12_DBG(5,("k12_seek_read: SEEK ERROR")); return FALSE; } len = get_record(k12, wth->random_fh, seek_off, TRUE, err, err_info); if (len < 0) { K12_DBG(5,("k12_seek_read: READ ERROR")); return FALSE; } else if (len < K12_RECORD_SRC_ID + 4) { /* Record not large enough to contain a src ID */ K12_DBG(5,("k12_seek_read: SHORT READ")); *err = WTAP_ERR_SHORT_READ; return FALSE; } buffer = k12->rand_read_buff; status = process_packet_data(rec, buf, buffer, (guint)len, k12, err, err_info); K12_DBG(5,("k12_seek_read: DONE OK")); return status; }
static gboolean k12_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) { k12_t *k12 = (k12_t *)wth->priv; k12_src_desc_t* src_desc; guint8* buffer; gint64 offset; gint len; guint32 type; guint32 src_id; offset = file_tell(wth->fh); /* ignore the record if it isn't a packet */ do { K12_DBG(5,("k12_read: offset=%i",offset)); *data_offset = offset; len = get_record(k12, wth->fh, offset, FALSE, err, err_info); if (len < 0) { /* read error */ return FALSE; } else if (len == 0) { /* EOF */ *err = 0; return FALSE; } else if (len < K12_RECORD_SRC_ID + 4) { /* Record not large enough to contain a src ID */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("data record length %d too short", len); return FALSE; } buffer = k12->seq_read_buff; type = pntoh32(buffer + K12_RECORD_TYPE); src_id = pntoh32(buffer + K12_RECORD_SRC_ID); if ( ! (src_desc = (k12_src_desc_t*)g_hash_table_lookup(k12->src_by_id,GUINT_TO_POINTER(src_id))) ) { /* * Some records from K15 files have a port ID of an undeclared * interface which happens to be the only one with the first byte changed. * It is still unknown how to recognize when this happens. * If the lookup of the interface record fails we'll mask it * and retry. */ src_desc = (k12_src_desc_t*)g_hash_table_lookup(k12->src_by_id,GUINT_TO_POINTER(src_id&K12_RECORD_SRC_ID_MASK)); } K12_DBG(5,("k12_read: record type=%x src_id=%x",type,src_id)); offset += len; } while ( ((type & K12_MASK_PACKET) != K12_REC_PACKET && (type & K12_MASK_PACKET) != K12_REC_D0020) || !src_id || !src_desc ); process_packet_data(&wth->phdr, wth->frame_buffer, buffer, len, k12); return TRUE; }
static void k12_close(wtap *wth) { k12_t *k12 = (k12_t *)wth->priv; destroy_k12_file_data(k12); wth->priv = NULL; /* destroy_k12_file_data freed it */ #ifdef DEBUG_K12 K12_DBG(5,("k12_close: CLOSED")); if (env_file) fclose(dbg_out); #endif }
static gboolean k12_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) { k12_t *k12 = (k12_t *)wth->priv; k12_src_desc_t* src_desc; guint8* buffer = NULL; gint64 offset; gint len; guint32 type; guint32 src_id; guint64 ts; guint32 extra_len; offset = wth->data_offset; /* ignore the record if it isn't a packet */ do { K12_DBG(5,("k12_read: offset=%i",offset)); *data_offset = offset; len = get_record(&buffer, wth->fh, offset, err, err_info); if (len < 0) { return FALSE; } else if (len == 0) { *err = 0; return FALSE; } type = pntohl(buffer + K12_RECORD_TYPE); src_id = pntohl(buffer + K12_RECORD_SRC_ID); if ( ! (src_desc = g_hash_table_lookup(k12->src_by_id,GUINT_TO_POINTER(src_id))) ) { /* * Some records from K15 files have a port ID of an undeclared * interface which happens to be the only one with the first byte changed. * It is still unknown how to recognize when this happens. * If the lookup of the interface record fails we'll mask it * and retry. */ src_desc = g_hash_table_lookup(k12->src_by_id,GUINT_TO_POINTER(src_id&K12_RECORD_SRC_ID_MASK)); } K12_DBG(5,("k12_read: record type=%x src_id=%x",type,src_id)); offset += len; } while ( ((type & K12_MASK_PACKET) != K12_REC_PACKET) || !src_id || !src_desc ); wth->data_offset = offset; wth->phdr.presence_flags = WTAP_HAS_TS; ts = pntohll(buffer + K12_PACKET_TIMESTAMP); wth->phdr.ts.secs = (guint32) ((ts / 2000000) + 631152000); wth->phdr.ts.nsecs = (guint32) ( (ts % 2000000) * 500 ); K12_DBG(3,("k12_read: PACKET RECORD type=%x src_id=%x secs=%u nsecs=%u",type,src_id, wth->phdr.ts.secs,wth->phdr.ts.nsecs)); wth->phdr.len = wth->phdr.caplen = pntohl(buffer + K12_RECORD_FRAME_LEN) & 0x00001FFF; extra_len = len - K12_PACKET_FRAME - wth->phdr.caplen; /* the frame */ buffer_assure_space(wth->frame_buffer, wth->phdr.caplen); memcpy(buffer_start_ptr(wth->frame_buffer), buffer + K12_PACKET_FRAME, wth->phdr.caplen); /* extra information need by some protocols */ buffer_assure_space(&(k12->extra_info), extra_len); memcpy(buffer_start_ptr(&(k12->extra_info)), buffer + K12_PACKET_FRAME + wth->phdr.caplen, extra_len); wth->pseudo_header.k12.extra_info = (void*)buffer_start_ptr(&(k12->extra_info)); wth->pseudo_header.k12.extra_length = extra_len; wth->pseudo_header.k12.input = src_id; K12_DBG(5,("k12_read: wth->pseudo_header.k12.input=%x wth->phdr.len=%i input_name='%s' stack_file='%s' type=%x", wth->pseudo_header.k12.input,wth->phdr.len,src_desc->input_name,src_desc->stack_file,src_desc->input_type));\ wth->pseudo_header.k12.input_name = src_desc->input_name; wth->pseudo_header.k12.stack_file = src_desc->stack_file; wth->pseudo_header.k12.input_type = src_desc->input_type; switch(src_desc->input_type) { case K12_PORT_ATMPVC: if ((long)(K12_PACKET_FRAME + wth->phdr.len + K12_PACKET_OFFSET_CID) < len) { wth->pseudo_header.k12.input_info.atm.vp = pntohs(buffer + (K12_PACKET_FRAME + wth->phdr.caplen + K12_PACKET_OFFSET_VP)); wth->pseudo_header.k12.input_info.atm.vc = pntohs(buffer + (K12_PACKET_FRAME + wth->phdr.caplen + K12_PACKET_OFFSET_VC)); wth->pseudo_header.k12.input_info.atm.cid = *((unsigned char*)(buffer + K12_PACKET_FRAME + wth->phdr.len + K12_PACKET_OFFSET_CID)); break; } /* Fall through */ default: memcpy(&(wth->pseudo_header.k12.input_info),&(src_desc->input_info),sizeof(src_desc->input_info)); break; } wth->pseudo_header.k12.stuff = k12; return TRUE; }
/* * 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(guint8** bufferp, FILE_T fh, gint64 file_offset, int *err, gchar **err_info) { static guint8* buffer = NULL; static guint buffer_len = 0x2000 ; 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 = g_malloc(0x2000); buffer_len = 0x2000; } *bufferp = buffer; 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 != 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 = pntohl(buffer); #ifdef DEBUG_K12 actual_len = left; #endif junky_offset -= 0x4; K12_DBG(5,("get_record: GET length=%u",left)); /* XXX - Is WTAP_MAX_PACKET_SIZE */ 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; } while (left > buffer_len) *bufferp = buffer = g_realloc(buffer,buffer_len*=2); writep = buffer + 4; left -= 4; 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_HEXDMP(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_HEXDMP(5,file_offset, "GOT record", buffer, actual_len); return bytes_read; }
wtap_open_return_val k12_open(wtap *wth, int *err, gchar **err_info) { k12_src_desc_t* rec; guint8 header_buffer[K12_FILE_HDR_LEN]; guint8* read_buffer; guint32 type; long offset; long len; guint port_type; guint32 rec_len; guint32 hwpart_len; guint32 name_len; guint32 stack_len; guint i; k12_t* file_data; #ifdef DEBUG_K12 gchar* env_level = getenv("K12_DEBUG_LEVEL"); env_file = getenv("K12_DEBUG_FILENAME"); if ( env_file ) { dbg_out = ws_fopen(env_file,"w"); if (dbg_out == NULL) { dbg_out = stderr; K12_DBG(1,("unable to open K12 DEBUG FILENAME for writing! Logging to standard error")); } } else dbg_out = stderr; if ( env_level ) debug_level = (unsigned int)strtoul(env_level,NULL,10); K12_DBG(1,("k12_open: ENTER debug_level=%u",debug_level)); #endif if ( !wtap_read_bytes(wth->fh,header_buffer,K12_FILE_HDR_LEN,err,err_info) ) { K12_DBG(1,("k12_open: FILE HEADER TOO SHORT OR READ ERROR")); if (*err != WTAP_ERR_SHORT_READ) { return WTAP_OPEN_ERROR; } return WTAP_OPEN_NOT_MINE; } if ( memcmp(header_buffer,k12_file_magic,8) != 0 ) { K12_DBG(1,("k12_open: BAD MAGIC")); return WTAP_OPEN_NOT_MINE; } offset = K12_FILE_HDR_LEN; file_data = new_k12_file_data(); file_data->file_len = pntoh32( header_buffer + 0x8); if (memiszero(header_buffer + 0x10, K12_FILE_HDR_LEN - 0x10)) { /* * The rest of the file header is all zeroes. That means * this is a file written by the old Wireshark code, and * a count of records in the file is at an offset of 0x0C. */ file_data->num_of_records = pntoh32( header_buffer + 0x0C ); } else { /* * There's at least one non-zero byte in the rest of the * header. The value 8192 is at 0xC (page size?), and * what appears to be the number of records in the file * is at an offset of 0x24 and at an offset of 0x2c. * * If the two values are not the same, we fail; if that's * the case, we need to see the file to figure out which * of those two values, if any, is the count. */ file_data->num_of_records = pntoh32( header_buffer + K12_FILE_HDR_RECORD_COUNT_1 ); if ( file_data->num_of_records != pntoh32( header_buffer + K12_FILE_HDR_RECORD_COUNT_2 ) ) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12: two different record counts, %u at 0x%02x and %u at 0x%02x", file_data->num_of_records, K12_FILE_HDR_RECORD_COUNT_1, pntoh32( header_buffer + K12_FILE_HDR_RECORD_COUNT_2 ), K12_FILE_HDR_RECORD_COUNT_2 ); return WTAP_OPEN_ERROR; } } K12_DBG(5,("k12_open: FILE_HEADER OK: offset=%x file_len=%i records=%i", offset, file_data->file_len, file_data->num_of_records )); do { if ( file_data->num_of_records == 0 ) { *err = WTAP_ERR_SHORT_READ; destroy_k12_file_data(file_data); return WTAP_OPEN_ERROR; } len = get_record(file_data, wth->fh, offset, FALSE, err, err_info); if ( len < 0 ) { K12_DBG(1,("k12_open: BAD HEADER RECORD",len)); destroy_k12_file_data(file_data); return WTAP_OPEN_ERROR; } if ( len == 0 ) { K12_DBG(1,("k12_open: BAD HEADER RECORD",len)); *err = WTAP_ERR_SHORT_READ; destroy_k12_file_data(file_data); return WTAP_OPEN_ERROR; } read_buffer = file_data->seq_read_buff; rec_len = pntoh32( read_buffer + K12_RECORD_LEN ); if (rec_len < K12_RECORD_TYPE + 4) { /* Record isn't long enough to have a type field */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: record length %u < %u", rec_len, K12_RECORD_TYPE + 4); return WTAP_OPEN_ERROR; } type = pntoh32( read_buffer + K12_RECORD_TYPE ); if ( (type & K12_MASK_PACKET) == K12_REC_PACKET || (type & K12_MASK_PACKET) == K12_REC_D0020) { /* * we are at the first packet record, rewind and leave. */ if (file_seek(wth->fh, offset, SEEK_SET, err) == -1) { destroy_k12_file_data(file_data); return WTAP_OPEN_ERROR; } K12_DBG(5,("k12_open: FIRST PACKET offset=%x",offset)); break; } switch (type) { case K12_REC_SRCDSC: case K12_REC_SRCDSC2: rec = g_new0(k12_src_desc_t,1); if (rec_len < K12_SRCDESC_HWPART) { /* * Record isn't long enough to have the fixed-length portion * of the source descriptor field. */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor record length %u < %u", rec_len, K12_SRCDESC_HWPART); destroy_k12_file_data(file_data); g_free(rec); return WTAP_OPEN_ERROR; } port_type = read_buffer[K12_SRCDESC_PORT_TYPE]; hwpart_len = pntoh16( read_buffer + K12_SRCDESC_HWPARTLEN ); name_len = pntoh16( read_buffer + K12_SRCDESC_NAMELEN ); stack_len = pntoh16( read_buffer + K12_SRCDESC_STACKLEN ); rec->input = pntoh32( read_buffer + K12_RECORD_SRC_ID ); K12_DBG(5,("k12_open: INTERFACE RECORD offset=%x interface=%x",offset,rec->input)); if (name_len == 0) { K12_DBG(5,("k12_open: failed (name_len == 0 in source description")); destroy_k12_file_data(file_data); g_free(rec); return WTAP_OPEN_NOT_MINE; } if (stack_len == 0) { K12_DBG(5,("k12_open: failed (stack_len == 0 in source description")); destroy_k12_file_data(file_data); g_free(rec); return WTAP_OPEN_NOT_MINE; } if (rec_len < K12_SRCDESC_HWPART + hwpart_len + name_len + stack_len) { /* * Record isn't long enough to have the full source descriptor * field, including the variable-length parts. */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor record length %u < %u (%u + %u + %u + %u)", rec_len, K12_SRCDESC_HWPART + hwpart_len + name_len + stack_len, K12_SRCDESC_HWPART, hwpart_len, name_len, stack_len); destroy_k12_file_data(file_data); g_free(rec); return WTAP_OPEN_ERROR; } if (hwpart_len) { if (hwpart_len < 4) { /* Hardware part isn't long enough to have a type field */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor hardware part length %u < 4", hwpart_len); destroy_k12_file_data(file_data); g_free(rec); return WTAP_OPEN_ERROR; } switch(( rec->input_type = pntoh32( read_buffer + K12_SRCDESC_HWPART + K12_SRCDESC_HWPARTTYPE ) )) { case K12_PORT_DS0S: /* This appears to be variable-length */ rec->input_info.ds0mask = 0x00000000; if (hwpart_len > K12_SRCDESC_DS0_MASK) { for (i = 0; i < hwpart_len - K12_SRCDESC_DS0_MASK; i++) { rec->input_info.ds0mask |= ( *(read_buffer + K12_SRCDESC_HWPART + K12_SRCDESC_DS0_MASK + i) == 0xff ) ? 1U<<(31-i) : 0x0; } } break; case K12_PORT_ATMPVC: if (hwpart_len < K12_SRCDESC_ATM_VCI + 2) { /* Hardware part isn't long enough to have ATM information */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor hardware part length %u < %u", hwpart_len, K12_SRCDESC_ATM_VCI + 2); destroy_k12_file_data(file_data); g_free(rec); return WTAP_OPEN_ERROR; } rec->input_info.atm.vp = pntoh16( read_buffer + K12_SRCDESC_HWPART + K12_SRCDESC_ATM_VPI ); rec->input_info.atm.vc = pntoh16( read_buffer + K12_SRCDESC_HWPART + K12_SRCDESC_ATM_VCI ); break; default: break; } } else { /* Record viewer generated files don't have this information */ if (port_type >= 0x14 && port_type <= 0x17) { /* For ATM2_E1DS1, ATM2_E3DS3, ATM2_STM1EL and ATM2_STM1OP */ rec->input_type = K12_PORT_ATMPVC; rec->input_info.atm.vp = 0; rec->input_info.atm.vc = 0; } } if (read_buffer[K12_SRCDESC_HWPART + hwpart_len + name_len - 1] != '\0') { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("k12_open: source descriptor record contains non-null-terminated link-layer name"); destroy_k12_file_data(file_data); g_free(rec); return WTAP_OPEN_ERROR; } if (read_buffer[K12_SRCDESC_HWPART + hwpart_len + name_len + stack_len - 1] != '\0') { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("k12_open: source descriptor record contains non-null-terminated stack path"); destroy_k12_file_data(file_data); g_free(rec); return WTAP_OPEN_ERROR; } rec->input_name = (gchar *)g_memdup(read_buffer + K12_SRCDESC_HWPART + hwpart_len, name_len); rec->stack_file = (gchar *)g_memdup(read_buffer + K12_SRCDESC_HWPART + hwpart_len + name_len, stack_len); ascii_strdown_inplace (rec->stack_file); g_hash_table_insert(file_data->src_by_id,GUINT_TO_POINTER(rec->input),rec); g_hash_table_insert(file_data->src_by_name,rec->stack_file,rec); break; case K12_REC_STK_FILE: K12_DBG(1,("k12_open: K12_REC_STK_FILE")); K12_DBG(1,("Field 1: 0x%08x",pntoh32( read_buffer + 0x08 ))); K12_DBG(1,("Field 2: 0x%08x",pntoh32( read_buffer + 0x0c ))); K12_ASCII_DUMP(1, read_buffer, rec_len, 16); break; default: K12_DBG(1,("k12_open: RECORD TYPE 0x%08x",type)); break; } offset += len; file_data->num_of_records--; } while(1); wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_K12; wth->file_encap = WTAP_ENCAP_K12; wth->snapshot_length = 0; wth->subtype_read = k12_read; wth->subtype_seek_read = k12_seek_read; wth->subtype_close = k12_close; wth->priv = (void *)file_data; wth->file_tsprec = WTAP_TSPREC_NSEC; return WTAP_OPEN_MINE; }
static gboolean process_packet_data(wtap_rec *rec, Buffer *target, guint8 *buffer, guint record_len, k12_t *k12, int *err, gchar **err_info) { guint32 type; guint buffer_offset; guint64 ts; guint32 length; guint32 extra_len; guint32 src_id; k12_src_desc_t* src_desc; type = pntoh32(buffer + K12_RECORD_TYPE); buffer_offset = (type == K12_REC_D0020) ? K12_PACKET_FRAME_D0020 : K12_PACKET_FRAME; if (buffer_offset > record_len) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12: Frame data offset %u > record length %u", buffer_offset, record_len); return FALSE; } length = pntoh32(buffer + K12_RECORD_FRAME_LEN) & 0x00001FFF; if (length > record_len - buffer_offset) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12: Frame length %u > record frame data %u", length, record_len - buffer_offset); return FALSE; } rec->rec_type = REC_TYPE_PACKET; rec->presence_flags = WTAP_HAS_TS; ts = pntoh64(buffer + K12_PACKET_TIMESTAMP); rec->ts.secs = (guint32) ((ts / 2000000) + 631152000); rec->ts.nsecs = (guint32) ( (ts % 2000000) * 500 ); rec->rec_header.packet_header.len = rec->rec_header.packet_header.caplen = length; ws_buffer_assure_space(target, length); memcpy(ws_buffer_start_ptr(target), buffer + buffer_offset, length); /* extra information need by some protocols */ extra_len = record_len - buffer_offset - length; ws_buffer_assure_space(&(k12->extra_info), extra_len); memcpy(ws_buffer_start_ptr(&(k12->extra_info)), buffer + buffer_offset + length, extra_len); rec->rec_header.packet_header.pseudo_header.k12.extra_info = (guint8*)ws_buffer_start_ptr(&(k12->extra_info)); rec->rec_header.packet_header.pseudo_header.k12.extra_length = extra_len; src_id = pntoh32(buffer + K12_RECORD_SRC_ID); K12_DBG(5,("process_packet_data: src_id=%.8x",src_id)); rec->rec_header.packet_header.pseudo_header.k12.input = src_id; if ( ! (src_desc = (k12_src_desc_t*)g_hash_table_lookup(k12->src_by_id,GUINT_TO_POINTER(src_id))) ) { /* * Some records from K15 files have a port ID of an undeclared * interface which happens to be the only one with the first byte changed. * It is still unknown how to recognize when this happens. * If the lookup of the interface record fails we'll mask it * and retry. */ src_desc = (k12_src_desc_t*)g_hash_table_lookup(k12->src_by_id,GUINT_TO_POINTER(src_id&K12_RECORD_SRC_ID_MASK)); } if (src_desc) { K12_DBG(5,("process_packet_data: input_name='%s' stack_file='%s' type=%x",src_desc->input_name,src_desc->stack_file,src_desc->input_type)); rec->rec_header.packet_header.pseudo_header.k12.input_name = src_desc->input_name; rec->rec_header.packet_header.pseudo_header.k12.stack_file = src_desc->stack_file; rec->rec_header.packet_header.pseudo_header.k12.input_type = src_desc->input_type; switch(src_desc->input_type) { case K12_PORT_ATMPVC: if (buffer_offset + length + K12_PACKET_OFFSET_CID < record_len) { rec->rec_header.packet_header.pseudo_header.k12.input_info.atm.vp = pntoh16(buffer + buffer_offset + length + K12_PACKET_OFFSET_VP); rec->rec_header.packet_header.pseudo_header.k12.input_info.atm.vc = pntoh16(buffer + buffer_offset + length + K12_PACKET_OFFSET_VC); rec->rec_header.packet_header.pseudo_header.k12.input_info.atm.cid = *((unsigned char*)(buffer + buffer_offset + length + K12_PACKET_OFFSET_CID)); break; } /* Fall through */ default: memcpy(&(rec->rec_header.packet_header.pseudo_header.k12.input_info),&(src_desc->input_info),sizeof(src_desc->input_info)); break; } } else { K12_DBG(5,("process_packet_data: NO SRC_RECORD FOUND")); memset(&(rec->rec_header.packet_header.pseudo_header.k12),0,sizeof(rec->rec_header.packet_header.pseudo_header.k12)); rec->rec_header.packet_header.pseudo_header.k12.input_name = "unknown port"; rec->rec_header.packet_header.pseudo_header.k12.stack_file = "unknown stack file"; } rec->rec_header.packet_header.pseudo_header.k12.input = src_id; rec->rec_header.packet_header.pseudo_header.k12.stuff = k12; return TRUE; }
/* * 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; }
int k12_open(wtap *wth, int *err, gchar **err_info) { k12_src_desc_t* rec; guint8 header_buffer[0x200]; guint8* read_buffer; guint32 type; long offset; long len; guint32 rec_len; guint32 extra_len; guint32 name_len; guint32 stack_len; guint i; k12_t* file_data; #ifdef DEBUG_K12 gchar* env_level = getenv("K12_DEBUG_LEVEL"); env_file = getenv("K12_DEBUG_FILENAME"); if ( env_file ) { dbg_out = ws_fopen(env_file,"w"); if (dbg_out == NULL) { dbg_out = stderr; K12_DBG(1,("unable to open K12 DEBUG FILENAME for writing! Logging to standard error")); } } else dbg_out = stderr; if ( env_level ) debug_level = (unsigned int)strtoul(env_level,NULL,10); K12_DBG(1,("k12_open: ENTER debug_level=%u",debug_level)); #endif if ( file_read(header_buffer,0x200,wth->fh) != 0x200 ) { K12_DBG(1,("k12_open: FILE HEADER TOO SHORT OR READ ERROR")); *err = file_error(wth->fh, err_info); if (*err != 0 && *err != WTAP_ERR_SHORT_READ) { return -1; } return 0; } else { if ( memcmp(header_buffer,k12_file_magic,8) != 0 ) { K12_DBG(1,("k12_open: BAD MAGIC")); return 0; } } offset = 0x200; file_data = new_k12_file_data(); file_data->file_len = pntoh32( header_buffer + 0x8); file_data->num_of_records = pntoh32( header_buffer + 0xC ); K12_DBG(5,("k12_open: FILE_HEADER OK: offset=%x file_len=%i records=%i", offset, file_data->file_len, file_data->num_of_records )); do { len = get_record(file_data, wth->fh, offset, FALSE, err, err_info); if ( len < 0 ) { K12_DBG(1,("k12_open: BAD HEADER RECORD",len)); destroy_k12_file_data(file_data); return -1; } if (len == 0) { K12_DBG(1,("k12_open: BAD HEADER RECORD",len)); *err = WTAP_ERR_SHORT_READ; destroy_k12_file_data(file_data); return -1; } if (len == 0) { K12_DBG(1,("k12_open: BAD HEADER RECORD",len)); *err = WTAP_ERR_SHORT_READ; destroy_k12_file_data(file_data); return -1; } read_buffer = file_data->seq_read_buff; rec_len = pntoh32( read_buffer + K12_RECORD_LEN ); if (rec_len < K12_RECORD_TYPE + 4) { /* Record isn't long enough to have a type field */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: record length %u < %u", rec_len, K12_RECORD_TYPE + 4); return -1; } type = pntoh32( read_buffer + K12_RECORD_TYPE ); if ( (type & K12_MASK_PACKET) == K12_REC_PACKET || (type & K12_MASK_PACKET) == K12_REC_D0020) { /* * we are at the first packet record, rewind and leave. */ if (file_seek(wth->fh, offset, SEEK_SET, err) == -1) { destroy_k12_file_data(file_data); return -1; } K12_DBG(5,("k12_open: FIRST PACKET offset=%x",offset)); break; } else if (type == K12_REC_SRCDSC || type == K12_REC_SRCDSC2 ) { rec = g_new0(k12_src_desc_t,1); if (rec_len < K12_SRCDESC_STACKLEN + 2) { /* Record isn't long enough to have a stack length field */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor record length %u < %u", rec_len, K12_SRCDESC_STACKLEN + 2); return -1; } extra_len = pntoh16( read_buffer + K12_SRCDESC_EXTRALEN ); name_len = pntoh16( read_buffer + K12_SRCDESC_NAMELEN ); stack_len = pntoh16( read_buffer + K12_SRCDESC_STACKLEN ); rec->input = pntoh32( read_buffer + K12_RECORD_SRC_ID ); K12_DBG(5,("k12_open: INTERFACE RECORD offset=%x interface=%x",offset,rec->input)); if (name_len == 0 || stack_len == 0 || 0x20 + extra_len + name_len + stack_len > rec_len ) { g_free(rec); K12_DBG(5,("k12_open: failed (name_len == 0 || stack_len == 0 " "|| 0x20 + extra_len + name_len + stack_len > rec_len) extra_len=%i name_len=%i stack_len=%i")); destroy_k12_file_data(file_data); return 0; } if (extra_len) { if (rec_len < K12_SRCDESC_EXTRATYPE + 4) { /* Record isn't long enough to have a source descriptor extra type field */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor record length %u < %u", rec_len, K12_SRCDESC_EXTRATYPE + 4); return -1; } switch(( rec->input_type = pntoh32( read_buffer + K12_SRCDESC_EXTRATYPE ) )) { case K12_PORT_DS0S: if (rec_len < K12_SRCDESC_DS0_MASK + 32) { /* Record isn't long enough to have a source descriptor extra type field */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor record length %u < %u", rec_len, K12_SRCDESC_DS0_MASK + 12); return -1; } rec->input_info.ds0mask = 0x00000000; for (i = 0; i < 32; i++) { rec->input_info.ds0mask |= ( *(read_buffer + K12_SRCDESC_DS0_MASK + i) == 0xff ) ? 0x1<<(31-i) : 0x0; } break; case K12_PORT_ATMPVC: if (rec_len < K12_SRCDESC_ATM_VCI + 2) { /* Record isn't long enough to have a source descriptor extra type field */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor record length %u < %u", rec_len, K12_SRCDESC_DS0_MASK + 12); return -1; } rec->input_info.atm.vp = pntoh16( read_buffer + K12_SRCDESC_ATM_VPI ); rec->input_info.atm.vc = pntoh16( read_buffer + K12_SRCDESC_ATM_VCI ); break; default: break; } } else { /* Record viewer generated files don't have this information */ if (rec_len < K12_SRCDESC_PORT_TYPE + 1) { /* Record isn't long enough to have a source descriptor extra type field */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor record length %u < %u", rec_len, K12_SRCDESC_DS0_MASK + 12); return -1; } if (read_buffer[K12_SRCDESC_PORT_TYPE] >= 0x14 && read_buffer[K12_SRCDESC_PORT_TYPE] <= 0x17) { /* For ATM2_E1DS1, ATM2_E3DS3, ATM2_STM1EL and ATM2_STM1OP */ rec->input_type = K12_PORT_ATMPVC; rec->input_info.atm.vp = 0; rec->input_info.atm.vc = 0; } } /* XXX - this is assumed, in a number of places (not just in the ascii_strdown_inplace() call below) to be null-terminated; is that guaranteed (even with a corrupt file)? Obviously not, as a corrupt file could contain anything here; the Tektronix document says the strings "must end with \0", but a bad file could fail to add the \0. */ if (rec_len < K12_SRCDESC_EXTRATYPE + extra_len + name_len + stack_len) { /* Record isn't long enough to have a source descriptor extra type field */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor record length %u < %u", rec_len, K12_SRCDESC_EXTRATYPE + extra_len + name_len + stack_len); return -1; } rec->input_name = (gchar *)g_memdup(read_buffer + K12_SRCDESC_EXTRATYPE + extra_len, name_len); rec->stack_file = (gchar *)g_memdup(read_buffer + K12_SRCDESC_EXTRATYPE + extra_len + name_len, stack_len); ascii_strdown_inplace (rec->stack_file); g_hash_table_insert(file_data->src_by_id,GUINT_TO_POINTER(rec->input),rec); g_hash_table_insert(file_data->src_by_name,rec->stack_file,rec); offset += len; continue; } else if (type == K12_REC_STK_FILE) { K12_DBG(1,("k12_open: K12_REC_STK_FILE")); K12_DBG(1,("Field 1: 0x%08x",pntoh32( read_buffer + 0x08 ))); K12_DBG(1,("Field 2: 0x%08x",pntoh32( read_buffer + 0x0c ))); K12_ASCII_DUMP(1, read_buffer, rec_len, 0x10); offset += len; continue; } else { K12_DBG(1,("k12_open: RECORD TYPE 0x%08x",type)); offset += len; continue; } } while(1); wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_K12; wth->file_encap = WTAP_ENCAP_K12; wth->snapshot_length = 0; wth->subtype_read = k12_read; wth->subtype_seek_read = k12_seek_read; wth->subtype_close = k12_close; wth->priv = (void *)file_data; wth->tsprecision = WTAP_FILE_TSPREC_NSEC; return 1; }
static void process_packet_data(struct wtap_pkthdr *phdr, Buffer *target, guint8 *buffer, gint len, k12_t *k12) { guint32 type; guint buffer_offset; guint64 ts; guint32 length; guint32 extra_len; guint32 src_id; k12_src_desc_t* src_desc; phdr->presence_flags = WTAP_HAS_TS; ts = pntoh64(buffer + K12_PACKET_TIMESTAMP); phdr->ts.secs = (guint32) ((ts / 2000000) + 631152000); phdr->ts.nsecs = (guint32) ( (ts % 2000000) * 500 ); length = pntoh32(buffer + K12_RECORD_FRAME_LEN) & 0x00001FFF; phdr->len = phdr->caplen = length; type = pntoh32(buffer + K12_RECORD_TYPE); buffer_offset = (type == K12_REC_D0020) ? K12_PACKET_FRAME_D0020 : K12_PACKET_FRAME; buffer_assure_space(target, length); memcpy(buffer_start_ptr(target), buffer + buffer_offset, length); /* extra information need by some protocols */ extra_len = len - buffer_offset - length; buffer_assure_space(&(k12->extra_info), extra_len); memcpy(buffer_start_ptr(&(k12->extra_info)), buffer + buffer_offset + length, extra_len); phdr->pseudo_header.k12.extra_info = (guint8*)buffer_start_ptr(&(k12->extra_info)); phdr->pseudo_header.k12.extra_length = extra_len; src_id = pntoh32(buffer + K12_RECORD_SRC_ID); K12_DBG(5,("process_packet_data: src_id=%.8x",src_id)); phdr->pseudo_header.k12.input = src_id; if ( ! (src_desc = (k12_src_desc_t*)g_hash_table_lookup(k12->src_by_id,GUINT_TO_POINTER(src_id))) ) { /* * Some records from K15 files have a port ID of an undeclared * interface which happens to be the only one with the first byte changed. * It is still unknown how to recognize when this happens. * If the lookup of the interface record fails we'll mask it * and retry. */ src_desc = (k12_src_desc_t*)g_hash_table_lookup(k12->src_by_id,GUINT_TO_POINTER(src_id&K12_RECORD_SRC_ID_MASK)); } if (src_desc) { K12_DBG(5,("process_packet_data: input_name='%s' stack_file='%s' type=%x",src_desc->input_name,src_desc->stack_file,src_desc->input_type)); phdr->pseudo_header.k12.input_name = src_desc->input_name; phdr->pseudo_header.k12.stack_file = src_desc->stack_file; phdr->pseudo_header.k12.input_type = src_desc->input_type; switch(src_desc->input_type) { case K12_PORT_ATMPVC: if ((long)(buffer_offset + length + K12_PACKET_OFFSET_CID) < len) { phdr->pseudo_header.k12.input_info.atm.vp = pntoh16(buffer + buffer_offset + length + K12_PACKET_OFFSET_VP); phdr->pseudo_header.k12.input_info.atm.vc = pntoh16(buffer + buffer_offset + length + K12_PACKET_OFFSET_VC); phdr->pseudo_header.k12.input_info.atm.cid = *((unsigned char*)(buffer + buffer_offset + length + K12_PACKET_OFFSET_CID)); break; } /* Fall through */ default: memcpy(&(phdr->pseudo_header.k12.input_info),&(src_desc->input_info),sizeof(src_desc->input_info)); break; } } else { K12_DBG(5,("process_packet_data: NO SRC_RECORD FOUND")); memset(&(phdr->pseudo_header.k12),0,sizeof(phdr->pseudo_header.k12)); phdr->pseudo_header.k12.input_name = "unknown port"; phdr->pseudo_header.k12.stack_file = "unknown stack file"; } phdr->pseudo_header.k12.input = src_id; phdr->pseudo_header.k12.stuff = k12; }
/* * 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; }
int k12_open(wtap *wth, int *err, gchar **err_info) { k12_src_desc_t* rec; guint8 header_buffer[0x200]; guint8* read_buffer; guint32 type; long offset; long len; guint port_type; guint32 rec_len; guint32 hwpart_len; guint32 name_len; guint32 stack_len; guint i; k12_t* file_data; #ifdef DEBUG_K12 gchar* env_level = getenv("K12_DEBUG_LEVEL"); env_file = getenv("K12_DEBUG_FILENAME"); if ( env_file ) { dbg_out = ws_fopen(env_file,"w"); if (dbg_out == NULL) { dbg_out = stderr; K12_DBG(1,("unable to open K12 DEBUG FILENAME for writing! Logging to standard error")); } } else dbg_out = stderr; if ( env_level ) debug_level = (unsigned int)strtoul(env_level,NULL,10); K12_DBG(1,("k12_open: ENTER debug_level=%u",debug_level)); #endif if ( file_read(header_buffer,0x200,wth->fh) != 0x200 ) { K12_DBG(1,("k12_open: FILE HEADER TOO SHORT OR READ ERROR")); *err = file_error(wth->fh, err_info); if (*err != 0 && *err != WTAP_ERR_SHORT_READ) { return -1; } return 0; } else { if ( memcmp(header_buffer,k12_file_magic,8) != 0 ) { K12_DBG(1,("k12_open: BAD MAGIC")); return 0; } } offset = 0x200; file_data = new_k12_file_data(); file_data->file_len = pntoh32( header_buffer + 0x8); file_data->num_of_records = pntoh32( header_buffer + 0xC ); K12_DBG(5,("k12_open: FILE_HEADER OK: offset=%x file_len=%i records=%i", offset, file_data->file_len, file_data->num_of_records )); do { len = get_record(file_data, wth->fh, offset, FALSE, err, err_info); if ( len < 0 ) { K12_DBG(1,("k12_open: BAD HEADER RECORD",len)); destroy_k12_file_data(file_data); return -1; } if (len == 0) { K12_DBG(1,("k12_open: BAD HEADER RECORD",len)); *err = WTAP_ERR_SHORT_READ; destroy_k12_file_data(file_data); return -1; } if (len == 0) { K12_DBG(1,("k12_open: BAD HEADER RECORD",len)); *err = WTAP_ERR_SHORT_READ; destroy_k12_file_data(file_data); return -1; } read_buffer = file_data->seq_read_buff; rec_len = pntoh32( read_buffer + K12_RECORD_LEN ); if (rec_len < K12_RECORD_TYPE + 4) { /* Record isn't long enough to have a type field */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: record length %u < %u", rec_len, K12_RECORD_TYPE + 4); return -1; } type = pntoh32( read_buffer + K12_RECORD_TYPE ); if ( (type & K12_MASK_PACKET) == K12_REC_PACKET || (type & K12_MASK_PACKET) == K12_REC_D0020) { /* * we are at the first packet record, rewind and leave. */ if (file_seek(wth->fh, offset, SEEK_SET, err) == -1) { destroy_k12_file_data(file_data); return -1; } K12_DBG(5,("k12_open: FIRST PACKET offset=%x",offset)); break; } else if (type == K12_REC_SRCDSC || type == K12_REC_SRCDSC2 ) { rec = g_new0(k12_src_desc_t,1); if (rec_len < K12_SRCDESC_HWPART) { /* * Record isn't long enough to have the fixed-length portion * of the source descriptor field. */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor record length %u < %u", rec_len, K12_SRCDESC_HWPART); destroy_k12_file_data(file_data); g_free(rec); return -1; } port_type = read_buffer[K12_SRCDESC_PORT_TYPE]; hwpart_len = pntoh16( read_buffer + K12_SRCDESC_HWPARTLEN ); name_len = pntoh16( read_buffer + K12_SRCDESC_NAMELEN ); stack_len = pntoh16( read_buffer + K12_SRCDESC_STACKLEN ); rec->input = pntoh32( read_buffer + K12_RECORD_SRC_ID ); K12_DBG(5,("k12_open: INTERFACE RECORD offset=%x interface=%x",offset,rec->input)); if (name_len == 0) { K12_DBG(5,("k12_open: failed (name_len == 0 in source description")); destroy_k12_file_data(file_data); g_free(rec); return 0; } if (stack_len == 0) { K12_DBG(5,("k12_open: failed (stack_len == 0 in source description")); destroy_k12_file_data(file_data); g_free(rec); return 0; } if (rec_len < K12_SRCDESC_HWPART + hwpart_len + name_len + stack_len) { /* * Record isn't long enough to have the full source descriptor * field, including the variable-length parts. */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor record length %u < %u (%u + %u + %u + %u)", rec_len, K12_SRCDESC_HWPART + hwpart_len + name_len + stack_len, K12_SRCDESC_HWPART, hwpart_len, name_len, stack_len); destroy_k12_file_data(file_data); g_free(rec); return -1; } if (hwpart_len) { if (hwpart_len < 4) { /* Hardware part isn't long enough to have a type field */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor hardware part length %u < 4", hwpart_len); destroy_k12_file_data(file_data); g_free(rec); return -1; } switch(( rec->input_type = pntoh32( read_buffer + K12_SRCDESC_HWPART + K12_SRCDESC_HWPARTTYPE ) )) { case K12_PORT_DS0S: /* This appears to be variable-length */ rec->input_info.ds0mask = 0x00000000; if (hwpart_len > K12_SRCDESC_DS0_MASK) { for (i = 0; i < hwpart_len - K12_SRCDESC_DS0_MASK; i++) { rec->input_info.ds0mask |= ( *(read_buffer + K12_SRCDESC_HWPART + K12_SRCDESC_DS0_MASK + i) == 0xff ) ? 0x1<<(31-i) : 0x0; } } break; case K12_PORT_ATMPVC: if (hwpart_len < K12_SRCDESC_ATM_VCI + 2) { /* Hardware part isn't long enough to have ATM information */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("k12_open: source descriptor hardware part length %u < %u", hwpart_len, K12_SRCDESC_ATM_VCI + 2); destroy_k12_file_data(file_data); g_free(rec); return -1; } rec->input_info.atm.vp = pntoh16( read_buffer + K12_SRCDESC_HWPART + K12_SRCDESC_ATM_VPI ); rec->input_info.atm.vc = pntoh16( read_buffer + K12_SRCDESC_HWPART + K12_SRCDESC_ATM_VCI ); break; default: break; } } else { /* Record viewer generated files don't have this information */ if (port_type >= 0x14 && port_type <= 0x17) { /* For ATM2_E1DS1, ATM2_E3DS3, ATM2_STM1EL and ATM2_STM1OP */ rec->input_type = K12_PORT_ATMPVC; rec->input_info.atm.vp = 0; rec->input_info.atm.vc = 0; } } if (read_buffer[K12_SRCDESC_HWPART + hwpart_len + name_len - 1] != '\0') { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("k12_open: source descriptor record contains non-null-terminated link-layer name"); destroy_k12_file_data(file_data); g_free(rec); return -1; } if (read_buffer[K12_SRCDESC_HWPART + hwpart_len + name_len + stack_len - 1] != '\0') { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("k12_open: source descriptor record contains non-null-terminated stack path"); destroy_k12_file_data(file_data); g_free(rec); return -1; } rec->input_name = (gchar *)g_memdup(read_buffer + K12_SRCDESC_HWPART + hwpart_len, name_len); rec->stack_file = (gchar *)g_memdup(read_buffer + K12_SRCDESC_HWPART + hwpart_len + name_len, stack_len); ascii_strdown_inplace (rec->stack_file); g_hash_table_insert(file_data->src_by_id,GUINT_TO_POINTER(rec->input),rec); g_hash_table_insert(file_data->src_by_name,rec->stack_file,rec); offset += len; continue; } else if (type == K12_REC_STK_FILE) { K12_DBG(1,("k12_open: K12_REC_STK_FILE")); K12_DBG(1,("Field 1: 0x%08x",pntoh32( read_buffer + 0x08 ))); K12_DBG(1,("Field 2: 0x%08x",pntoh32( read_buffer + 0x0c ))); K12_ASCII_DUMP(1, read_buffer, rec_len, 0x10); offset += len; continue; } else { K12_DBG(1,("k12_open: RECORD TYPE 0x%08x",type)); offset += len; continue; } } while(1); wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_K12; wth->file_encap = WTAP_ENCAP_K12; wth->snapshot_length = 0; wth->subtype_read = k12_read; wth->subtype_seek_read = k12_seek_read; wth->subtype_close = k12_close; wth->priv = (void *)file_data; wth->tsprecision = WTAP_FILE_TSPREC_NSEC; return 1; }