Ethereal-dev: Re: [Ethereal-dev] Re: New dissectors: H.223 and friends
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Richard van der Hoff <richardv@xxxxxxxxxxxxx>
Date: Tue, 11 Oct 2005 13:42:41 +0100
Richard van der Hoff wrote:
Right, here's another rework of the iax desegmentation logic, which fixes bug 515 and its dupes.I'll work on a fix for the existing logic.
Cheers Richard -- Richard van der Hoff <richardv@xxxxxxxxxxxxx> Systems Analyst Tel: +44 (0) 845 666 7778 http://www.mxtelecom.com
Index: epan/dissectors/packet-iax2.c =================================================================== RCS file: /cvs/ethereal/epan/dissectors/packet-iax2.c,v retrieving revision 1.1.1.6 diff -u -r1.1.1.6 packet-iax2.c --- epan/dissectors/packet-iax2.c 7 Oct 2005 12:37:30 -0000 1.1.1.6 +++ epan/dissectors/packet-iax2.c 11 Oct 2005 12:38:01 -0000 @@ -55,6 +55,7 @@ #define IAX_MAX_TRANSFERS 2 /* #define DEBUG_HASHING */ +/* #define DEBUG_DESEGMENT */ /* Ethereal ID of the IAX2 protocol */ static int proto_iax2 = -1; @@ -462,7 +463,7 @@ v1->port == v2->port && v1->callno== v2->callno); #ifdef DEBUG_HASHING - g_message( "+++ Comparing for equality: %s, %s: %u",key_to_str(v1), key_to_str(v2), result); + g_debug( "+++ Comparing for equality: %s, %s: %u",key_to_str(v1), key_to_str(v2), result); #endif return result; @@ -483,7 +484,7 @@ hash_val += (guint)(key->callno); #ifdef DEBUG_HASHING - g_message( "+++ Hashing key: %s, result %#x", key_to_str(key), hash_val ); + g_debug( "+++ Hashing key: %s, result %#x", key_to_str(key), hash_val ); #endif return (guint) hash_val; @@ -524,7 +525,7 @@ g_hash_table_insert(iax_circuit_hashtab, new_key, circuit_id_p); #ifdef DEBUG_HASHING - g_message("Created new circuit id %u for node %s", *circuit_id_p, key_to_str(new_key)); + g_debug("Created new circuit id %u for node %s", *circuit_id_p, key_to_str(new_key)); #endif } @@ -535,9 +536,9 @@ /* ************************************************************************* */ typedef struct { - guint32 current_frag_id; + guint32 current_frag_id; /* invalid unless current_frag_bytes > 0 */ guint32 current_frag_bytes; - gboolean in_frag; + guint32 current_frag_minlen; } iax_call_dirdata; /* This is our per-call data structure, which is attached to both the @@ -573,7 +574,6 @@ GHashTable *fid_table; GHashTable *fragment_table; - GHashTable *totlen_table; iax_call_dirdata dirdata[2]; } iax_call_data; @@ -672,7 +672,7 @@ if( !dst_circuit ) { #ifdef DEBUG_HASHING - g_message( "++ destination circuit not found, must have missed NEW packet" ); + g_debug( "++ destination circuit not found, must have missed NEW packet" ); #endif if( reversed_p ) *reversed_p = FALSE; @@ -680,7 +680,7 @@ } #ifdef DEBUG_HASHING - g_message( "++ found destination circuit" ); + g_debug( "++ found destination circuit" ); #endif iax_call = (iax_call_data *)circuit_get_proto_data(dst_circuit,proto_iax2); @@ -691,7 +691,7 @@ if( is_forward_circuit(dst_circuit_id, iax_call )) { #ifdef DEBUG_HASHING - g_message( "++ destination circuit matches forward_circuit_id of call, " + g_debug( "++ destination circuit matches forward_circuit_id of call, " "therefore packet is reversed" ); #endif @@ -702,13 +702,13 @@ doesn't have a reverse circuit associated with it. create one now. */ #ifdef DEBUG_HASHING - g_message( "++ reverse_circuit_id of call is zero, need to create a " + g_debug( "++ reverse_circuit_id of call is zero, need to create a " "new reverse circuit for this call" ); #endif iax2_new_circuit_for_call( src_circuit_id, framenum, iax_call, TRUE ); #ifdef DEBUG_HASHING - g_message( "++ done" ); + g_debug( "++ done" ); #endif } else if( !is_reverse_circuit(src_circuit_id, iax_call )) { g_warning( "IAX Packet %u from circuit ids %u->%u " @@ -721,7 +721,7 @@ } } else if ( is_reverse_circuit(dst_circuit_id, iax_call)) { #ifdef DEBUG_HASHING - g_message( "++ destination circuit matches reverse_circuit_id of call, " + g_debug( "++ destination circuit matches reverse_circuit_id of call, " "therefore packet is forward" ); #endif @@ -759,7 +759,7 @@ guint src_circuit_id; #ifdef DEBUG_HASHING - g_message( "++ iax_lookup_circuit_details: Looking up circuit for frame %u, " + g_debug( "++ iax_lookup_circuit_details: Looking up circuit for frame %u, " "from {%s:%u:%u} to {%s:%u:%u}", pinfo->fd->num, address_to_str(&pinfo->src),pinfo->srcport,scallno, address_to_str(&pinfo->dst),pinfo->destport,dcallno); @@ -775,7 +775,7 @@ if( dcallno != 0 ) { guint dst_circuit_id; #ifdef DEBUG_HASHING - g_message( "++ dcallno non-zero, looking up destination circuit" ); + g_debug( "++ dcallno non-zero, looking up destination circuit" ); #endif dst_circuit_id = iax_circuit_lookup(&pinfo->dst,pinfo->ptype, @@ -821,15 +821,22 @@ #ifdef DEBUG_HASHING if( iax_call ) { - g_message( "++ Found call for packet: id %u, reversed=%c", iax_call->iax_forward_circuit_ids[0], reversed?'1':'0' ); + g_debug( "++ Found call for packet: id %u, reversed=%c", iax_call->forward_circuit_ids[0], reversed?'1':'0' ); } else { - g_message( "++ Call not found. Must have missed the NEW packet?" ); + g_debug( "++ Call not found. Must have missed the NEW packet?" ); } #endif return iax_call; } +/* initialise the per-direction parts of an iax_call_data structure */ +static void init_dir_data(iax_call_dirdata *dirdata) +{ + dirdata -> current_frag_bytes=0; + dirdata -> current_frag_minlen=0; +} + /* handles a NEW packet by creating a new iax call and forward circuit. the reverse circuit is not created until the ACK is received and @@ -842,7 +849,7 @@ static const nstime_t millisecond = {0, 1000000}; #ifdef DEBUG_HASHING - g_message( "+ new_circuit: Handling NEW packet, frame %u", pinfo->fd->num ); + g_debug( "+ new_circuit: Handling NEW packet, frame %u", pinfo->fd->num ); #endif circuit_id = iax_circuit_lookup(&pinfo->src,pinfo->ptype, @@ -858,9 +865,9 @@ call -> start_time = pinfo->fd->abs_ts; nstime_delta(&call -> start_time, &call -> start_time, &millisecond); call -> fid_table = g_hash_table_new(g_direct_hash, g_direct_equal); - call -> totlen_table = g_hash_table_new(g_direct_hash, g_direct_equal); - call -> dirdata[0].in_frag=FALSE; - call -> dirdata[1].in_frag=FALSE; + init_dir_data(&call->dirdata[0]); + init_dir_data(&call->dirdata[1]); + call->fragment_table = NULL; fragment_table_init(&(call->fragment_table)); iax2_new_circuit_for_call(circuit_id,pinfo->fd->num,call,FALSE); @@ -1325,7 +1332,7 @@ ie_data.peer_callno); #if 0 - g_message("found transfer request for call %u->%u, to new id %u", + g_debug("found transfer request for call %u->%u, to new id %u", iax_call->forward_circuit_ids[0], iax_call->reverse_circuit_ids[0], tx_circuit); @@ -1496,8 +1503,10 @@ iax_packet -> codec = codec = uncompress_subclass(csub); if( packet_type_tree ) { + proto_item *item; proto_tree_add_item (packet_type_tree, hf_iax2_voice_csub, tvb, offset+9, 1, FALSE); - proto_tree_add_uint (packet_type_tree, hf_iax2_voice_codec, tvb, offset+9, 1, codec); + item = proto_tree_add_uint (packet_type_tree, hf_iax2_voice_codec, tvb, offset+9, 1, codec); + PROTO_ITEM_SET_GENERATED(item); } offset += 10; @@ -1519,9 +1528,11 @@ iax_packet -> codec = codec = uncompress_subclass((guint8) (csub & ~40)); if( packet_type_tree ) { + proto_item *item; proto_tree_add_item (packet_type_tree, hf_iax2_video_csub, tvb, offset+9, 1, FALSE); proto_tree_add_item (packet_type_tree, hf_iax2_marker, tvb, offset+9, 1, FALSE); - proto_tree_add_uint (packet_type_tree, hf_iax2_video_codec, tvb, offset+9, 1, codec); + item = proto_tree_add_uint (packet_type_tree, hf_iax2_video_codec, tvb, offset+9, 1, codec); + PROTO_ITEM_SET_GENERATED(item); } offset += 10; @@ -1686,7 +1697,7 @@ iax_call_data *iax_call = iax_packet -> call_data; #ifdef DEBUG_DESEGMENT - g_message("calling process_iax_pdu; len = %u\n", tvb_reported_length(tvb)); + g_debug("calling process_iax_pdu; len = %u", tvb_reported_length(tvb)); #endif if( !video && iax_call && iax_call->subdissector ) { @@ -1699,7 +1710,7 @@ } #ifdef DEBUG_DESEGMENT - g_message("called process_iax_pdu; pinfo->desegment_len=%u; pinfo->desegment_offset=%u\n", + g_debug("called process_iax_pdu; pinfo->desegment_len=%u; pinfo->desegment_offset=%u", pinfo->desegment_len, pinfo->desegment_offset); #endif } @@ -1710,44 +1721,47 @@ iax_call_data *iax_call = iax_packet -> call_data; iax_call_dirdata *dirdata; - gpointer unused,value; - guint32 frag_len,tot_len,frag_offset,nbytes,deseg_offset; + gpointer value; + guint32 frag_offset; fragment_data *fd_head; - gboolean complete = FALSE, called_dissector = FALSE, must_desegment = FALSE; + gboolean must_desegment = FALSE; + DISSECTOR_ASSERT(iax_call); + + pinfo->can_desegment = 2; pinfo->desegment_offset = 0; pinfo->desegment_len = 0; - deseg_offset = 0; #ifdef DEBUG_DESEGMENT - g_message("dissecting packet %u\n", pinfo->fd->num); + g_debug("dissecting packet %u", pinfo->fd->num); #endif - if( iax_call ) - dirdata = &(iax_call->dirdata[!!(iax_packet->reversed)]); - else { - /* no call info for this frame; perhaps we missed the NEW packet */ - dirdata = NULL; - } + dirdata = &(iax_call->dirdata[!!(iax_packet->reversed)]); - if(iax_call && - ((!pinfo->fd->flags.visited && dirdata->in_frag) || - g_hash_table_lookup_extended(iax_call->fid_table, - GUINT_TO_POINTER(pinfo->fd->num), &unused, &value) ) ) { - guint32 fid = 0; - + if((!pinfo->fd->flags.visited && dirdata->current_frag_bytes > 0) || + (value = g_hash_table_lookup(iax_call->fid_table, + GUINT_TO_POINTER(pinfo->fd->num))) != NULL ) { /* then we are continuing an already-started pdu */ - frag_len = tvb_reported_length( tvb ); + guint32 fid; + guint32 frag_len = tvb_reported_length( tvb ); + gboolean complete; + +#ifdef DEBUG_DESEGMENT + g_debug("visited: %i; c_f_b: %u; hash: %u->%u", pinfo->fd->flags.visited?1:0, + dirdata->current_frag_bytes, pinfo->fd->num, fid); +#endif + if(!pinfo->fd->flags.visited) { + guint32 tot_len; fid = dirdata->current_frag_id; - tot_len = GPOINTER_TO_UINT(g_hash_table_lookup(iax_call->totlen_table, GUINT_TO_POINTER(fid))); + tot_len = dirdata->current_frag_minlen; g_hash_table_insert( iax_call->fid_table, GUINT_TO_POINTER(pinfo->fd->num), GUINT_TO_POINTER(fid) ); frag_offset = dirdata->current_frag_bytes; dirdata->current_frag_bytes += frag_len; complete = dirdata->current_frag_bytes > tot_len; #ifdef DEBUG_DESEGMENT - g_message("in_frag: %i; hash: %u->%u; frag_offset: %u; c_f_b: %u\n", dirdata->in_frag, - pinfo->fd->num, fid, frag_offset, dirdata->current_frag_bytes ); + g_debug("hash: %u->%u; frag_offset: %u; c_f_b: %u; totlen: %u", + pinfo->fd->num, fid, frag_offset, dirdata->current_frag_bytes, tot_len ); #endif } else { fid = GPOINTER_TO_UINT(value); @@ -1761,19 +1775,14 @@ iax_call->fragment_table, frag_offset, frag_len, !complete ); - - if(pinfo->fd->flags.visited) - complete = (fd_head && (pinfo->fd->num == fd_head->reassembled_in)); - - if(complete) { + + if(fd_head && (pinfo->fd->num == fd_head->reassembled_in)) { gint32 old_len; tvbuff_t *next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen); tvb_set_child_real_data_tvbuff(tvb, next_tvb); add_new_data_source(pinfo, next_tvb, "Reassembled IAX2"); - pinfo->can_desegment = 2; process_iax_pdu(next_tvb,pinfo,tree,video,iax_packet); - called_dissector = TRUE; /* calculate the amount of data which was available to the higher-level dissector before we added this segment; if the returned offset is @@ -1783,29 +1792,32 @@ old_len = (gint32)(tvb_reported_length(next_tvb) - tvb_reported_length(tvb)); if( pinfo->desegment_len && pinfo->desegment_offset < old_len ) { - /* - * oops, it wasn't actually complete - */ + /* oops, it wasn't actually complete */ fragment_set_partial_reassembly(pinfo, fid, iax_call->fragment_table); - g_hash_table_insert(iax_call->totlen_table, GUINT_TO_POINTER(fid), - GUINT_TO_POINTER(tvb_reported_length(next_tvb) + pinfo->desegment_len) ); + dirdata->current_frag_minlen = fd_head->datalen + pinfo->desegment_len; } else { - proto_item *iax_tree_item, *frag_tree_item; - nbytes = tvb_reported_length( tvb ); + /* we successfully dissected some data; create the proto tree items for + * the fragments, and flag any remaining data for desegmentation */ + + proto_item *iax_tree_item, *frag_tree_item; + /* this nargery is to insert the fragment tree into the main tree + * between the IAX protocol entry and the subdissector entry */ show_fragment_tree(fd_head, &iax2_fragment_items, tree, pinfo, next_tvb, &frag_tree_item); - iax_tree_item = proto_tree_get_parent( iax2_tree ); - if(iax_tree_item) - iax_tree_item = proto_item_get_parent( iax_tree_item ); + iax_tree_item = proto_item_get_parent( proto_tree_get_parent( iax2_tree )); if( frag_tree_item && iax_tree_item ) proto_tree_move_item( tree, iax_tree_item, frag_tree_item ); - dirdata->in_frag = FALSE; + + dirdata->current_frag_minlen = dirdata->current_frag_id = dirdata->current_frag_bytes = 0; + if( pinfo->desegment_len ) { /* there's a bit of data left to desegment */ must_desegment = TRUE; - /* make desegment_offset relative to our tvb */ - deseg_offset = pinfo->desegment_offset - (tvb_reported_length( next_tvb ) - tvb_reported_length( tvb )); + pinfo->desegment_offset -= old_len; } + + /* don't add a 'reassembled in' item for this pdu */ + fd_head = NULL; } } } else { @@ -1813,53 +1825,42 @@ contain a continuation of a higher-level PDU. Call the normal subdissector. */ - if(iax_call) - pinfo->can_desegment = 2; - else - pinfo->can_desegment = 0; process_iax_pdu(tvb,pinfo,tree,video,iax_packet); - called_dissector = TRUE; - if(pinfo->desegment_len) { /* the higher-level dissector has asked for some more data - ie, the end of this segment does not coincide with the end of a higher-level PDU. */ must_desegment = TRUE; - deseg_offset = pinfo->desegment_offset; } + fd_head = NULL; } /* must_desegment is set if the end of this segment (or the whole of it) * contained the start of a higher-level PDU; we must add whatever is left of - * this segment (after deseg_offset) to a fragment table for disassembly. */ - if(iax_call && must_desegment) { - guint32 fid = pinfo->fd->num; - if(pinfo->fd->flags.visited) { - fd_head = fragment_get( pinfo, fid, iax_call->fragment_table ); - } else { - frag_len = tvb_reported_length_remaining(tvb,deseg_offset); + * this segment (after pinfo->desegment_offset) to a fragment table for disassembly. */ + if(must_desegment) { + guint32 fid = pinfo->fd->num; /* a new fragment id */ + guint32 deseg_offset = pinfo->desegment_offset; + guint32 frag_len = tvb_reported_length_remaining(tvb,deseg_offset); dirdata->current_frag_id = fid; dirdata->current_frag_bytes = frag_len; - dirdata->in_frag = TRUE; - complete = FALSE; + dirdata->current_frag_minlen = frag_len + pinfo->desegment_len; fd_head = fragment_add(tvb, deseg_offset, pinfo, fid, iax_call->fragment_table, - 0, frag_len, !complete ); - g_hash_table_insert(iax_call->totlen_table, GUINT_TO_POINTER(fid), - GUINT_TO_POINTER( frag_len + pinfo->desegment_len) ); + 0, frag_len, TRUE ); #ifdef DEBUG_DESEGMENT - g_message("Start offset of undissected bytes: %u; " + g_debug("Start offset of undissected bytes: %u; " "Bytes remaining in this segment: %u; min required bytes: %u\n", deseg_offset, frag_len, frag_len + pinfo->desegment_len); #endif - } } - if( !called_dissector || pinfo->desegment_len != 0 ) { - if( fd_head != NULL ) { + /* add a 'reassembled in' item if necessary */ + if( fd_head != NULL ) { + guint32 deseg_offset = pinfo->desegment_offset; if( fd_head->reassembled_in != 0 && !(fd_head->flags & FD_PARTIAL_REASSEMBLY) ) { proto_item *iax_tree_item; @@ -1872,7 +1873,6 @@ proto_tree_add_text( tree, tvb, deseg_offset, -1, "IAX2 fragment, unfinished"); } - } if( pinfo->desegment_offset == 0 ) { if (check_col(pinfo->cinfo, COL_PROTOCOL)){ @@ -1882,7 +1882,6 @@ col_set_str(pinfo->cinfo, COL_INFO, "[IAX2 segment of a reassembled PDU]"); } } - nbytes = tvb_reported_length_remaining( tvb, deseg_offset ); } pinfo->can_desegment = 0; @@ -1932,8 +1931,12 @@ proto_tree_add_text( iax2_tree, sub_tvb, 0, -1, "IAX2 payload (%u byte%s)", nbytes, plurality( nbytes, "", "s" )); + /* pass the rest of the block to a subdissector */ - desegment_iax( sub_tvb, pinfo, iax2_tree, tree, video, iax_packet ); + if(iax_packet->call_data) + desegment_iax( sub_tvb, pinfo, iax2_tree, tree, video, iax_packet ); + else + process_iax_pdu(sub_tvb,pinfo,tree,video,iax_packet); } /*
- Follow-Ups:
- SV: [Ethereal-dev] Re: New dissectors: H.223 and friends
- From: Anders Broman
- SV: [Ethereal-dev] Re: New dissectors: H.223 and friends
- References:
- [Ethereal-dev] Re: New dissectors: H.223 and friends
- From: Richard van der Hoff
- Re: [Ethereal-dev] Re: New dissectors: H.223 and friends
- From: Guy Harris
- Re: [Ethereal-dev] Re: New dissectors: H.223 and friends
- From: Richard van der Hoff
- Re: [Ethereal-dev] Re: New dissectors: H.223 and friends
- From: Richard van der Hoff
- [Ethereal-dev] Re: New dissectors: H.223 and friends
- Prev by Date: [Ethereal-dev] patch: console log level preference
- Next by Date: [Ethereal-dev] Pipes and Ethereal
- Previous by thread: Re: [Ethereal-dev] Re: New dissectors: H.223 and friends
- Next by thread: SV: [Ethereal-dev] Re: New dissectors: H.223 and friends
- Index(es):