diff options
-rw-r--r-- | epan/dissectors/packet-dcerpc.c | 78 | ||||
-rw-r--r-- | epan/reassemble.c | 21 | ||||
-rw-r--r-- | epan/reassemble.h | 4 |
3 files changed, 35 insertions, 68 deletions
diff --git a/epan/dissectors/packet-dcerpc.c b/epan/dissectors/packet-dcerpc.c index 494d5944ae..846e721381 100644 --- a/epan/dissectors/packet-dcerpc.c +++ b/epan/dissectors/packet-dcerpc.c @@ -519,19 +519,24 @@ get_next_di(void) static gboolean dcerpc_cn_desegment = TRUE; /* reassemble DCE/RPC fragments */ -/* reassembly of dcerpc fragments will not work for the case where ONE frame +/* reassembly of cl dcerpc fragments will not work for the case where ONE frame might contain multiple dcerpc fragments for different PDUs. this case would be so unusual/weird so if you got captures like that: too bad + + reassembly of co dcerpc fragments will not work for the case where TCP/SMB frames + are coming in out of sequence, but that will hurt in a lot of other places as well. */ static gboolean dcerpc_reassemble = FALSE; +static GHashTable *dcerpc_co_fragment_table = NULL; static GHashTable *dcerpc_co_reassemble_table = NULL; static GHashTable *dcerpc_cl_reassemble_table = NULL; static void dcerpc_reassemble_init(void) { - fragment_table_init(&dcerpc_co_reassemble_table); + fragment_table_init(&dcerpc_co_fragment_table); + reassembled_table_init(&dcerpc_co_reassemble_table); dcerpc_fragment_table_init(&dcerpc_cl_reassemble_table); } @@ -2956,7 +2961,7 @@ dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo, gint length, reported_length; gboolean save_fragmented; fragment_data *fd_head=NULL; - guint32 tot_len; + tvbuff_t *auth_tvb, *payload_tvb, *decrypted_tvb; proto_item *pi; proto_item *parent_pi; @@ -3075,7 +3080,7 @@ dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo, then exit */ if(pinfo->fd->flags.visited){ - fd_head=fragment_get(pinfo, frame, dcerpc_co_reassemble_table); + fd_head=fragment_get_reassembled(pinfo, frame, dcerpc_co_reassemble_table); goto end_cn_stub; } @@ -3106,65 +3111,16 @@ dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo, goto end_cn_stub; } - /* defragmentation is a bit tricky here, as there's no offset of the fragment + /* defragmentation is a bit tricky, as there's no offset of the fragment * in the protocol data. * - * The allocation hint will contain the remaining bytes of all fragments following. - * - * Currently two possible ways: - * - the transmitter sends an alloc_hint != 0, use it - * - the transmitter sends an alloc_hint == 0, simply append fragments - */ - - /* if this is the first fragment we need to start reassembly + * just use fragment_add_seq_next() and hope that TCP/SMB segments coming + * in with the correct sequence. */ - if(hdr->flags&PFC_FIRST_FRAG){ - fragment_add(decrypted_tvb, 0, pinfo, frame, - dcerpc_co_reassemble_table, - 0 /* fragment offset */, tvb_length(decrypted_tvb), TRUE /* more_frags */); - fragment_set_tot_len(pinfo, frame, - dcerpc_co_reassemble_table, alloc_hint ? alloc_hint : tvb_length(decrypted_tvb)); - - goto end_cn_stub; - } - - /* if this is a middle fragment, just add it and exit */ - if(!(hdr->flags&PFC_LAST_FRAG)){ - tot_len = fragment_get_tot_len(pinfo, frame, - dcerpc_co_reassemble_table); - if(alloc_hint == 0) { - fragment_set_tot_len(pinfo, frame, - dcerpc_co_reassemble_table, tot_len + tvb_length(decrypted_tvb)); - } else { - /* the alloc_hint shouldn't be larger than the expected remaining length */ - if(alloc_hint > (tot_len - tvb_length(decrypted_tvb))) { - THROW(ReportedBoundsError); - } - } - fragment_add(decrypted_tvb, 0, pinfo, frame, - dcerpc_co_reassemble_table, - tot_len-alloc_hint /* fragment offset */, tvb_length(decrypted_tvb), - TRUE /* more_frags */); - - goto end_cn_stub; - } - - /* this was the last fragment add it to reassembly - */ - tot_len = fragment_get_tot_len(pinfo, frame, - dcerpc_co_reassemble_table); - /* the alloc_hint shouldn't be larger than the expected remaining length */ - if(alloc_hint != 0 && alloc_hint > (tot_len - tvb_length(decrypted_tvb))) { - THROW(ReportedBoundsError); - } - fd_head = fragment_add(decrypted_tvb, 0, pinfo, frame, - dcerpc_co_reassemble_table, - tot_len-alloc_hint /* fragment offset */, tvb_length(decrypted_tvb), - FALSE /* more_frags */); - if(alloc_hint == 0) { - fragment_set_tot_len(pinfo, frame, - dcerpc_co_reassemble_table, tot_len + tvb_length(decrypted_tvb)); - } + fd_head = fragment_add_seq_next(decrypted_tvb, 0, pinfo, frame, + dcerpc_co_fragment_table, dcerpc_co_reassemble_table, + tvb_length(decrypted_tvb), + hdr->flags&PFC_LAST_FRAG ? FALSE : TRUE /* more_frags */); end_cn_stub: @@ -3178,7 +3134,7 @@ end_cn_stub: tvbuff_t *next_tvb; proto_item *frag_tree_item; - next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen); + next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len); tvb_set_child_real_data_tvbuff(decrypted_tvb, next_tvb); add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC"); show_fragment_tree(fd_head, &dcerpc_frag_items, diff --git a/epan/reassemble.c b/epan/reassemble.c index 688e07d405..2c43fd786f 100644 --- a/epan/reassemble.c +++ b/epan/reassemble.c @@ -386,6 +386,20 @@ fragment_get(packet_info *pinfo, guint32 id, GHashTable *fragment_table) return fd_head; } +fragment_data * +fragment_get_reassembled(packet_info *pinfo, guint32 id, GHashTable *reassembled_table) +{ + fragment_data *fd_head; + reassembled_key key; + + /* create key to search hash with */ + key.frame = id; + key.id = id; + fd_head = g_hash_table_lookup(reassembled_table, &key); + + return fd_head; +} + /* This function can be used to explicitely set the total length (if known) * for reassembly of a PDU. * This is useful for reassembly of PDUs where one may have the total length specified @@ -711,13 +725,6 @@ fragment_add_work(fragment_data *fd_head, tvbuff_t *tvb, int offset, fd_head->flags |= FD_TOOLONGFRAGMENT; } - if(more_frags) { - /* dissector told us, that this isn't the last fragment, - * trust this information and don't try to defragment for now. - */ - return FALSE; - } - /* we have received an entire packet, defragment it and * free all fragments */ diff --git a/epan/reassemble.h b/epan/reassemble.h index e0598da225..69ebf94e1f 100644 --- a/epan/reassemble.h +++ b/epan/reassemble.h @@ -200,6 +200,10 @@ fragment_set_partial_reassembly(packet_info *pinfo, guint32 id, GHashTable *frag extern fragment_data * fragment_get(packet_info *pinfo, guint32 id, GHashTable *fragment_table); +/* The same for the reassemble table */ +extern fragment_data * +fragment_get_reassembled(packet_info *pinfo, guint32 id, GHashTable *reassembled_table); + /* This will free up all resources and delete reassembly state for this PDU. * Except if the PDU is completely reassembled, then it would NOT deallocate the * buffer holding the reassembled data but instead return the pointer to that |