diff options
author | Jakub Zawadzki <darkjames-ws@darkjames.pl> | 2013-07-14 14:42:05 +0000 |
---|---|---|
committer | Jakub Zawadzki <darkjames-ws@darkjames.pl> | 2013-07-14 14:42:05 +0000 |
commit | c766e78cfa1527ed242580b808635b0b5966cf3e (patch) | |
tree | 7a4318d94e33c292936eb8cffca5e5ff31e73c55 /epan/reassemble.c | |
parent | d924325d37c8724a447f76f8789063580bd86876 (diff) |
Rewrite reassemble API to use TVBs instead of raw data.
(it seems to be working for TCP ^^)
svn path=/trunk/; revision=50580
Diffstat (limited to 'epan/reassemble.c')
-rw-r--r-- | epan/reassemble.c | 137 |
1 files changed, 69 insertions, 68 deletions
diff --git a/epan/reassemble.c b/epan/reassemble.c index 413fa8e385..98fd8b97c9 100644 --- a/epan/reassemble.c +++ b/epan/reassemble.c @@ -339,8 +339,8 @@ free_all_fragments(gpointer key_arg _U_, gpointer value, gpointer user_data _U_) for (fd_head = (fragment_data *)value; fd_head != NULL; fd_head = tmp_fd) { tmp_fd=fd_head->next; - if(fd_head->data && !(fd_head->flags&FD_NOT_MALLOCED)) - g_free(fd_head->data); + if(fd_head->tvb_data && !(fd_head->flags&FD_SUBSET_TVB)) + tvb_free(fd_head->tvb_data); g_slice_free(fragment_data, fd_head); } @@ -383,8 +383,8 @@ free_all_reassembled_fragments(gpointer key_arg, gpointer value, * free_fragments() */ if (fd_head->flags != FD_VISITED_FREE) { - if (fd_head->flags & FD_NOT_MALLOCED) - fd_head->data = NULL; + if (fd_head->flags & FD_SUBSET_TVB) + fd_head->tvb_data = NULL; g_ptr_array_add(allocated_fragments, fd_head); fd_head->flags = FD_VISITED_FREE; } @@ -400,7 +400,8 @@ free_fragments(gpointer data, gpointer user_data _U_) { fragment_data *fd_head = (fragment_data *) data; - g_free(fd_head->data); + if (fd_head->tvb_data) + tvb_free(fd_head->tvb_data); g_slice_free(fragment_data, fd_head); } @@ -568,14 +569,14 @@ insert_fd_head(reassembly_table *table, fragment_data *fd_head, * Othervise the function will return NULL. * * So, if you call fragment_delete and it returns non-NULL, YOU are responsible to - * g_free() that buffer. + * tvb_free() that buffer. */ -unsigned char * +tvbuff_t * fragment_delete(reassembly_table *table, const packet_info *pinfo, const guint32 id, const void *data) { fragment_data *fd_head, *fd; - unsigned char *fd_data=NULL; + tvbuff_t *fd_tvb_data=NULL; gpointer key; fd_head = lookup_fd_head(table, pinfo, id, data, &key); @@ -584,21 +585,21 @@ fragment_delete(reassembly_table *table, const packet_info *pinfo, return NULL; } - fd_data=fd_head->data; + fd_tvb_data=fd_head->tvb_data; /* loop over all partial fragments and free any buffers */ for(fd=fd_head->next;fd;){ fragment_data *tmp_fd; tmp_fd=fd->next; - if( !(fd->flags&FD_NOT_MALLOCED) ) - g_free(fd->data); + if (fd->tvb_data && !(fd->flags & FD_SUBSET_TVB)) + tvb_free(fd->tvb_data); g_slice_free(fragment_data, fd); fd=tmp_fd; } g_slice_free(fragment_data, fd_head); g_hash_table_remove(table->fragment_table, key); - return fd_data; + return fd_tvb_data; } /* This function is used to check if there is partial or completed reassembly state @@ -862,7 +863,8 @@ fragment_add_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, fragment_data *fd; fragment_data *fd_i; guint32 max, dfpos, fraglen; - unsigned char *old_data; + tvbuff_t *old_tvb_data; + char *data; /* create new fd describing this fragment */ fd = g_slice_new(fragment_data); @@ -872,7 +874,7 @@ fragment_add_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, fd->offset = frag_offset; fd->fragment_nr_offset = 0; /* will only be used with sequence */ fd->len = frag_data_len; - fd->data = NULL; + fd->tvb_data = NULL; fd->error = NULL; /* @@ -896,9 +898,9 @@ fragment_add_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, * point old fds to malloc'ed data. */ for(fd_i=fd_head->next; fd_i; fd_i=fd_i->next){ - if( !fd_i->data ) { - fd_i->data = fd_head->data + fd_i->offset; - fd_i->flags |= FD_NOT_MALLOCED; + if( !fd_i->tvb_data ) { + fd_i->tvb_data = tvb_new_subset_remaining(fd_head->tvb_data, fd_i->offset); + fd_i->flags |= FD_SUBSET_TVB; } fd_i->flags &= (~FD_TOOLONGFRAGMENT) & (~FD_MULTIPLETAILS); } @@ -995,7 +997,7 @@ fragment_add_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, fd_head->flags |= FD_TOOLONGFRAGMENT; } /* make sure it doesn't conflict with previous data */ - else if ( memcmp(fd_head->data+fd->offset, + else if ( tvb_memeql(fd_head->tvb_data, fd->offset, tvb_get_ptr(tvb,offset,fd->len),fd->len) ){ fd->flags |= FD_OVERLAPCONFLICT; fd_head->flags |= FD_OVERLAPCONFLICT; @@ -1012,8 +1014,7 @@ fragment_add_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, * XXX - what if we didn't capture the entire fragment due * to a too-short snapshot length? */ - fd->data = (unsigned char *)g_malloc(fd->len); - tvb_memcpy(tvb, fd->data, offset, fd->len); + fd->tvb_data = tvb_clone_offset_len(tvb, offset, fd->len); LINK_FRAG(fd_head,fd); @@ -1056,8 +1057,10 @@ fragment_add_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, * free all fragments */ /* store old data just in case */ - old_data=fd_head->data; - fd_head->data = (unsigned char *)g_malloc(fd_head->datalen); + old_tvb_data=fd_head->tvb_data; + data = g_malloc(fd_head->datalen); + fd_head->tvb_data = tvb_new_real_data(data, fd_head->datalen, fd_head->datalen); + tvb_set_free_cb(fd_head->tvb_data, g_free); /* add all data fragments */ for (dfpos=0,fd_i=fd_head;fd_i;fd_i=fd_i->next) { @@ -1113,7 +1116,7 @@ fragment_add_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, fd_head->error = "dfpos < offset"; } else if (dfpos - fd_i->offset > fd_i->len) fd_head->error = "dfpos - offset > len"; - else if (!fd_head->data) + else if (!fd_head->tvb_data) fd_head->error = "no data"; else { fraglen = fd_i->len; @@ -1137,12 +1140,14 @@ fragment_add_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, fraglen = fd_head->datalen - fd_i->offset; } if (fd_i->offset < dfpos) { + guint32 cmp_len = MIN(fd_i->len,(dfpos-fd_i->offset)); + fd_i->flags |= FD_OVERLAP; fd_head->flags |= FD_OVERLAP; - if ( memcmp(fd_head->data+fd_i->offset, - fd_i->data, - MIN(fd_i->len,(dfpos-fd_i->offset)) - ) ) { + if ( memcmp(data + fd_i->offset, + tvb_get_ptr(fd_i->tvb_data, 0, cmp_len), + cmp_len) + ) { fd_i->flags |= FD_OVERLAPCONFLICT; fd_head->flags |= FD_OVERLAPCONFLICT; } @@ -1153,8 +1158,8 @@ fragment_add_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, */ fd_head->error = "fraglen < dfpos - offset"; } else { - memcpy(fd_head->data+dfpos, - fd_i->data+(dfpos-fd_i->offset), + memcpy(data+dfpos, + tvb_get_ptr(fd_i->tvb_data, (dfpos-fd_i->offset), fraglen-(dfpos-fd_i->offset)), fraglen-(dfpos-fd_i->offset)); dfpos=MAX(dfpos, (fd_i->offset + fraglen)); } @@ -1165,15 +1170,18 @@ fragment_add_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, fd_head->error = "offset + len < offset"; } } - if (fd_i->flags & FD_NOT_MALLOCED) - fd_i->flags &= ~FD_NOT_MALLOCED; - else - g_free(fd_i->data); - fd_i->data=NULL; + + if (fd_i->flags & FD_SUBSET_TVB) + fd_i->flags &= ~FD_SUBSET_TVB; + else if (fd_i->tvb_data) + tvb_free(fd_i->tvb_data); + + fd_i->tvb_data=NULL; } } - g_free(old_data); + if (old_tvb_data) + tvb_free(old_tvb_data); /* mark this packet as defragmented. allows us to skip any trailing fragments */ fd_head->flags |= FD_DEFRAGMENTED; @@ -1474,7 +1482,8 @@ fragment_defragment_and_free (fragment_data *fd_head, const packet_info *pinfo) fragment_data *fd_i = NULL; fragment_data *last_fd = NULL; guint32 dfpos = 0, size = 0; - void *old_data = NULL; + tvbuff_t *old_tvb_data = NULL; + char *data; for(fd_i=fd_head->next;fd_i;fd_i=fd_i->next) { if(!last_fd || last_fd->offset!=fd_i->offset){ @@ -1484,8 +1493,10 @@ fragment_defragment_and_free (fragment_data *fd_head, const packet_info *pinfo) } /* store old data in case the fd_i->data pointers refer to it */ - old_data=fd_head->data; - fd_head->data = (unsigned char *)g_malloc(size); + old_tvb_data=fd_head->tvb_data; + data = g_malloc(size); + fd_head->tvb_data = tvb_new_real_data(data, size, size); + tvb_set_free_cb(fd_head->tvb_data, g_free); fd_head->len = size; /* record size for caller */ /* add all data fragments */ @@ -1494,14 +1505,14 @@ fragment_defragment_and_free (fragment_data *fd_head, const packet_info *pinfo) if (fd_i->len) { if(!last_fd || last_fd->offset != fd_i->offset) { /* First fragment or in-sequence fragment */ - memcpy(fd_head->data+dfpos, fd_i->data, fd_i->len); + memcpy(data+dfpos, tvb_get_ptr(fd_i->tvb_data, 0, fd_i->len), fd_i->len); dfpos += fd_i->len; } else { /* duplicate/retransmission/overlap */ fd_i->flags |= FD_OVERLAP; fd_head->flags |= FD_OVERLAP; if(last_fd->len != fd_i->len - || memcmp(last_fd->data, fd_i->data, last_fd->len) ) { + || tvb_memeql(last_fd->tvb_data, 0, tvb_get_ptr(fd_i->tvb_data, 0, last_fd->len), last_fd->len) ) { fd_i->flags |= FD_OVERLAPCONFLICT; fd_head->flags |= FD_OVERLAPCONFLICT; } @@ -1512,13 +1523,14 @@ fragment_defragment_and_free (fragment_data *fd_head, const packet_info *pinfo) /* we have defragmented the pdu, now free all fragments*/ for (fd_i=fd_head->next;fd_i;fd_i=fd_i->next) { - if( fd_i->flags & FD_NOT_MALLOCED ) - fd_i->flags &= ~FD_NOT_MALLOCED; - else - g_free(fd_i->data); - fd_i->data=NULL; + if (fd_i->flags & FD_SUBSET_TVB) + fd_i->flags &= ~FD_SUBSET_TVB; + else if (fd_i->tvb_data) + tvb_free(fd_i->tvb_data); + fd_i->tvb_data=NULL; } - g_free(old_data); + if (old_tvb_data) + tvb_free(old_tvb_data); /* mark this packet as defragmented. * allows us to skip any trailing fragments. @@ -1564,17 +1576,17 @@ fragment_add_seq_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, guint32 lastdfpos = 0; dfpos = 0; for(fd_i=fd_head->next; fd_i; fd_i=fd_i->next){ - if( !fd_i->data ) { + if( !fd_i->tvb_data ) { if( fd_i->flags & FD_OVERLAP ) { /* this is a duplicate of the previous * fragment. */ - fd_i->data = fd_head->data + lastdfpos; + fd_i->tvb_data = tvb_new_subset_remaining(fd_head->tvb_data, lastdfpos); } else { - fd_i->data = fd_head->data + dfpos; + fd_i->tvb_data = tvb_new_subset_remaining(fd_head->tvb_data, dfpos); lastdfpos = dfpos; dfpos += fd_i->len; } - fd_i->flags |= FD_NOT_MALLOCED; + fd_i->flags |= FD_SUBSET_TVB; } fd_i->flags &= (~FD_TOOLONGFRAGMENT) & (~FD_MULTIPLETAILS); } @@ -1592,7 +1604,7 @@ fragment_add_seq_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, fd->frame = pinfo->fd->num; fd->offset = frag_number_work; fd->len = frag_data_len; - fd->data = NULL; + fd->tvb_data = NULL; fd->error = NULL; if (!more_frags) { @@ -1659,7 +1671,7 @@ fragment_add_seq_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, return TRUE; } DISSECTOR_ASSERT(fd_head->len >= dfpos + fd->len); - if ( memcmp(fd_head->data+dfpos, + if (tvb_memeql(fd_head->tvb_data, dfpos, tvb_get_ptr(tvb,offset,fd->len),fd->len) ){ /* * They have the same length, but the @@ -1717,8 +1729,7 @@ fragment_add_seq_work(fragment_data *fd_head, tvbuff_t *tvb, const int offset, */ /* check len, there may be a fragment with 0 len, that is actually the tail */ if (fd->len) { - fd->data = (unsigned char *)g_malloc(fd->len); - tvb_memcpy(tvb, fd->data, offset, fd->len); + fd->tvb_data = tvb_clone_offset_len(tvb, offset, fd->len); } LINK_FRAG(fd_head,fd); @@ -2063,7 +2074,7 @@ fragment_start_seq_check(reassembly_table *table, const packet_info *pinfo, fd_head->fragment_nr_offset = 0; fd_head->len = 0; fd_head->flags = FD_BLOCKSEQUENCE|FD_DATALEN_SET; - fd_head->data = NULL; + fd_head->tvb_data = NULL; fd_head->reassembled_in = 0; fd_head->error = NULL; @@ -2154,22 +2165,12 @@ process_reassembled_data(tvbuff_t *tvb, const int offset, packet_info *pinfo, /* * Yes. * Allocate a new tvbuff, referring to the - * reassembled payload. - */ - if (fd_head->flags & FD_BLOCKSEQUENCE) { - next_tvb = tvb_new_real_data(fd_head->data, - fd_head->len, fd_head->len); - } else { - next_tvb = tvb_new_real_data(fd_head->data, - fd_head->datalen, fd_head->datalen); - } - - /* - * Add the tvbuff to the list of tvbuffs to which + * reassembled payload, and set + * the tvbuff to the list of tvbuffs to which * the tvbuff we were handed refers, so it'll get * cleaned up when that tvbuff is cleaned up. */ - tvb_set_child_real_data_tvbuff(tvb, next_tvb); + next_tvb = tvb_new_chain(tvb, fd_head->tvb_data); /* Add the defragmented data to the data source list. */ add_new_data_source(pinfo, next_tvb, name); |