diff --git a/epan/dissectors/packet-btatt.c b/epan/dissectors/packet-btatt.c index 4e5aee02c7..e676fd21cc 100644 --- a/epan/dissectors/packet-btatt.c +++ b/epan/dissectors/packet-btatt.c @@ -4733,7 +4733,7 @@ again: { offset = (pinfo->desegment_offset==-1?0:pinfo->desegment_offset); tvbuff_t *new_tvb = NULL; - fragment_item *frag_msg = NULL; + fragment_head *frag_msg = NULL; pinfo->fragmented = TRUE; frag_msg = fragment_add_seq_next(&msg_reassembly_table, tvb, offset, pinfo, diff --git a/epan/dissectors/packet-dcp-etsi.c b/epan/dissectors/packet-dcp-etsi.c index 654408ac74..f52167c499 100644 --- a/epan/dissectors/packet-dcp-etsi.c +++ b/epan/dissectors/packet-dcp-etsi.c @@ -316,10 +316,12 @@ dissect_pft_fec_detailed(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, got = (guint32 *)wmem_alloc(pinfo->pool, fcount*sizeof(guint32)); /* make a list of the findex (offset) numbers of the fragments we have */ - fd = fragment_get(&dcp_reassembly_table, pinfo, seq, NULL); - for (fd_head = fd; fd_head != NULL && fragments < fcount; fd_head = fd_head->next) { - if(fd_head->tvb_data) { - got[fragments++] = fd_head->offset; /* this is the findex of the fragment */ + fd_head = fragment_get(&dcp_reassembly_table, pinfo, seq, NULL); + if (fd_head) { + for (fd = fd_head->next; fd != NULL && fragments < fcount; fd = fd->next) { + if(fd->tvb_data) { + got[fragments++] = fd->offset; /* this is the findex of the fragment */ + } } } /* have we got enough for Reed Solomon to try to correct ? */ diff --git a/epan/dissectors/packet-docsis.c b/epan/dissectors/packet-docsis.c index 4d886db03a..58f53efb92 100644 --- a/epan/dissectors/packet-docsis.c +++ b/epan/dissectors/packet-docsis.c @@ -794,7 +794,7 @@ dissect_docsis (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* da /* Only defragment valid frames with a good FCS */ if (sent_fcs == fcs) { - fragment_item *frag_msg = NULL; + fragment_head *frag_msg = NULL; frag_msg = fragment_add_seq_check(&docsis_reassembly_table, tvb, hdrlen, pinfo, frag_sid, NULL, /* ID for fragments belonging together */ diff --git a/epan/dissectors/packet-mp2t.c b/epan/dissectors/packet-mp2t.c index 8ee267309d..b36aa8fe49 100644 --- a/epan/dissectors/packet-mp2t.c +++ b/epan/dissectors/packet-mp2t.c @@ -573,16 +573,17 @@ mp2t_get_packet_length(tvbuff_t *tvb, guint offset, packet_info *pinfo, guint32 frag_id, enum pid_payload_type pload_type) { mp2t_stream_key *stream; - fragment_head *frag; + fragment_head *frag_head; + fragment_item *frag = NULL; tvbuff_t *len_tvb = NULL, *frag_tvb = NULL, *data_tvb = NULL; gint pkt_len = 0; guint remaining_len; stream = (mp2t_stream_key *)p_get_proto_data(pinfo->pool, pinfo, proto_mp2t, MP2T_PROTO_DATA_STREAM); if (pinfo->fd->visited) { - frag = fragment_get_reassembled_id(&mp2t_reassembly_table, pinfo, frag_id); - if (frag) { - len_tvb = frag->tvb_data; + frag_head = fragment_get_reassembled_id(&mp2t_reassembly_table, pinfo, frag_id); + if (frag_head) { + len_tvb = frag_head->tvb_data; offset = 0; } else { /* Not reassembled on the first pass. There are two possibilities: @@ -590,8 +591,8 @@ mp2t_get_packet_length(tvbuff_t *tvb, guint offset, packet_info *pinfo, * put in the table. * 2) Dangling fragments at the end of the capture. */ - frag = fragment_get(&mp2t_reassembly_table, pinfo, frag_id, stream); - if (!frag) { + frag_head = fragment_get(&mp2t_reassembly_table, pinfo, frag_id, stream); + if (!frag_head) { /* This is the entire packet */ len_tvb = tvb; } else { @@ -602,9 +603,10 @@ mp2t_get_packet_length(tvbuff_t *tvb, guint offset, packet_info *pinfo, } } } else { - frag = fragment_get(&mp2t_reassembly_table, pinfo, frag_id, stream); - if (frag) - frag = frag->next; + frag_head = fragment_get(&mp2t_reassembly_table, pinfo, frag_id, stream); + if (frag_head) { + frag = frag_head->next; + } if (!frag) { /* First frame */ len_tvb = tvb; diff --git a/epan/dissectors/packet-obex.c b/epan/dissectors/packet-obex.c index e1aba17914..3830e1c0f9 100644 --- a/epan/dissectors/packet-obex.c +++ b/epan/dissectors/packet-obex.c @@ -2226,6 +2226,7 @@ dissect_obex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) proto_tree *main_tree; proto_item *sub_item; fragment_head *frag_msg = NULL; + fragment_item *frag = NULL; gboolean save_fragmented; gboolean complete; tvbuff_t* new_tvb = NULL; @@ -2353,14 +2354,12 @@ dissect_obex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) /* packet stream is guaranted to be sequence of fragments, one by one, so find last fragment for its offset and length */ - while (frag_msg->next) { - frag_msg = frag_msg->next; - } + for (frag = frag_msg->next; frag; frag = frag->next) {} frag_msg = fragment_add_check(&obex_reassembly_table, tvb, 0, pinfo, pinfo->p2p_dir, NULL, - frag_msg->offset + frag_msg->len, tvb_reported_length(tvb), - ((frag_msg->offset + frag_msg->len + tvb_reported_length(tvb)) < + frag->offset + frag->len, tvb_reported_length(tvb), + ((frag->offset + frag->len + tvb_reported_length(tvb)) < fragment_get_tot_len(&obex_reassembly_table, pinfo, pinfo->p2p_dir, NULL)) ? TRUE : FALSE); new_tvb = process_reassembled_data(tvb, 0, pinfo, diff --git a/epan/dissectors/packet-ppi.c b/epan/dissectors/packet-ppi.c index 27b46fbb8a..87253685ee 100644 --- a/epan/dissectors/packet-ppi.c +++ b/epan/dissectors/packet-ppi.c @@ -1107,9 +1107,10 @@ dissect_ppi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) /* Make sure we aren't going to go past AGGREGATE_MAX * and caclulate our full A-MPDU length */ fd_head = fragment_get(&du_reassembly_table, pinfo, ampdu_id, NULL); - while (fd_head) { - ampdu_len += fd_head->len + PADDING4(fd_head->len) + 4; - fd_head = fd_head->next; + if (fd_head) { + for (ft_fdh = fd_head->next; ft_fdh; ft_fdh = ft_fdh->next) { + ampdu_len += ft_fdh->len + PADDING4(ft_fdh->len) + 4; + } } if (ampdu_len > AGGREGATE_MAX) { proto_tree_add_expert_format(ppi_tree, pinfo, &ei_ppi_invalid_length, tvb, offset, -1, "Aggregate length greater than maximum (%u)", AGGREGATE_MAX); @@ -1132,7 +1133,7 @@ dissect_ppi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) /* Show our fragments */ if (fd_head && tree) { - ft_fdh = fd_head; + ft_fdh = fd_head->next; /* List our fragments */ seg_tree = proto_tree_add_subtree_format(ppi_tree, tvb, offset, -1, ett_ampdu_segments, &ti, "A-MPDU (%u bytes w/hdrs):", ampdu_len); @@ -1168,18 +1169,17 @@ dissect_ppi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) agg_tree = proto_item_add_subtree(ti, ett_ampdu); } - while (fd_head) { - if (fd_head->tvb_data && fd_head->len) { + for (ft_fdh = fd_head->next; ft_fdh; ft_fdh = ft_fdh->next) { + if (ft_fdh->tvb_data && ft_fdh->len) { mpdu_count++; mpdu_str = wmem_strdup_printf(pinfo->pool, "MPDU #%d", mpdu_count); - next_tvb = tvb_new_chain(tvb, fd_head->tvb_data); + next_tvb = tvb_new_chain(tvb, ft_fdh->tvb_data); add_new_data_source(pinfo, next_tvb, mpdu_str); ampdu_tree = proto_tree_add_subtree(agg_tree, next_tvb, 0, -1, ett_ampdu_segment, NULL, mpdu_str); call_dissector_with_data(ieee80211_radio_handle, next_tvb, pinfo, ampdu_tree, &phdr); } - fd_head = fd_head->next; } proto_tree_add_uint(seg_tree, hf_ampdu_count, tvb, 0, 0, mpdu_count); pinfo->fragmented=FALSE; diff --git a/epan/dissectors/packet-smb-pipe.c b/epan/dissectors/packet-smb-pipe.c index fd8e9df1fc..8896dfe70e 100644 --- a/epan/dissectors/packet-smb-pipe.c +++ b/epan/dissectors/packet-smb-pipe.c @@ -3239,6 +3239,7 @@ dissect_pipe_dcerpc(tvbuff_t *d_tvb, packet_info *pinfo, proto_tree *parent_tree guint reported_len; fragment_head *fd_head; + fragment_item *fd_i; tvbuff_t *new_tvb; proto_item *frag_tree_item; @@ -3325,12 +3326,10 @@ dissect_pipe_dcerpc(tvbuff_t *d_tvb, packet_info *pinfo, proto_tree *parent_tree we might pick up from the Read/Write calls instead of assuming we always get them in the correct order */ - while(fd_head->next){ - fd_head=fd_head->next; - } + for (fd_i = fd_head->next; fd_i; fd_i = fd_i->next) {} fd_head=fragment_add_check(&dcerpc_reassembly_table, d_tvb, 0, pinfo, fid, NULL, - fd_head->offset+fd_head->len, + fd_i->offset+fd_i->len, reported_len, TRUE); /* if we completed reassembly */ diff --git a/epan/dissectors/packet-smb2.c b/epan/dissectors/packet-smb2.c index 2ca3cc98de..8ec2cdd6e6 100644 --- a/epan/dissectors/packet-smb2.c +++ b/epan/dissectors/packet-smb2.c @@ -6287,6 +6287,7 @@ dissect_file_data_smb2_pipe(tvbuff_t *raw_tvb, packet_info *pinfo, proto_tree *t const smb2_fid_info_t *file = NULL; guint32 id; fragment_head *fd_head; + fragment_item *fd_i; tvbuff_t *tvb; tvbuff_t *new_tvb; proto_item *frag_tree_item; @@ -6386,12 +6387,10 @@ dissect_file_data_smb2_pipe(tvbuff_t *raw_tvb, packet_info *pinfo, proto_tree *t we might pick up from the Read/Write calls instead of assuming we always get them in the correct order */ - while (fd_head->next) { - fd_head = fd_head->next; - } + for (fd_i = fd_head->next; fd_i; fd_i = fd_i->next) {} fd_head = fragment_add_check(&smb2_pipe_reassembly_table, tvb, 0, pinfo, id, NULL, - fd_head->offset+fd_head->len, + fd_i->offset+fd_i->len, reported_len, TRUE); /* if we completed reassembly */ diff --git a/epan/dissectors/packet-someip.c b/epan/dissectors/packet-someip.c index 94c8934150..6287d87e44 100644 --- a/epan/dissectors/packet-someip.c +++ b/epan/dissectors/packet-someip.c @@ -3589,7 +3589,7 @@ dissect_someip_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void gboolean tp_more_segments = FALSE; gboolean update_col_info = TRUE; guint32 segment_key; - fragment_item *someip_tp_head = NULL; + fragment_head *someip_tp_head = NULL; proto_tree *tp_tree = NULL; ti = proto_tree_add_item(someip_tree, hf_someip_tp, tvb, offset, someip_payload_length, ENC_NA); diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c index db5ec84197..175e976d4a 100644 --- a/epan/dissectors/packet-tcp.c +++ b/epan/dissectors/packet-tcp.c @@ -3693,7 +3693,7 @@ find_maxnextseq(packet_info *pinfo, struct tcp_multisegment_pdu *msp, guint32 ma /* Find length of contiguous fragments. */ guint32 max = maxnextseq - msp->seq; - for (fragment_item *frag = fd_head; frag; frag = frag->next) { + for (fragment_item *frag = fd_head->next; frag; frag = frag->next) { guint32 frag_end = frag->offset + frag->len; if (frag->offset <= max && max < frag_end) { max = frag_end; diff --git a/epan/reassemble.c b/epan/reassemble.c index 3669a236ed..19ba265e70 100644 --- a/epan/reassemble.c +++ b/epan/reassemble.c @@ -326,17 +326,25 @@ static gboolean free_all_fragments(gpointer key_arg _U_, gpointer value, gpointer user_data _U_) { fragment_head *fd_head; - fragment_item *tmp_fd; + fragment_item *fd_i = NULL, *tmp_fd; /* g_hash_table_new_full() was used to supply a function * to free the key and anything to which it points */ - for (fd_head = (fragment_head *)value; fd_head != NULL; fd_head = tmp_fd) { - tmp_fd=fd_head->next; - + fd_head = (fragment_head *)value; + if (fd_head != NULL) { + fd_i = fd_head->next; if(fd_head->tvb_data && !(fd_head->flags&FD_SUBSET_TVB)) tvb_free(fd_head->tvb_data); - g_slice_free(fragment_item, fd_head); + g_slice_free(fragment_head, fd_head); + } + + for (; fd_i != NULL; fd_i = tmp_fd) { + tmp_fd=fd_i->next; + + if(fd_i->tvb_data && !(fd_i->flags&FD_SUBSET_TVB)) + tvb_free(fd_i->tvb_data); + g_slice_free(fragment_item, fd_i); } return TRUE; @@ -369,16 +377,19 @@ free_all_reassembled_fragments(gpointer key_arg _U_, gpointer value, GPtrArray *allocated_fragments = (GPtrArray *) user_data; fragment_head *fd_head; - for (fd_head = (fragment_head *)value; fd_head != NULL; fd_head = fd_head->next) { + fd_head = (fragment_head *)value; + if (fd_head != NULL) { /* * A reassembled packet is inserted into the * hash table once for every frame that made - * up the reassembled packet; add first seen - * fragments to array and later free them in + * up the reassembled packet; add to the array + * the first time seen and later free them in * free_fragments() */ - if (fd_head->flags == FD_VISITED_FREE) - break; + if (fd_head->flags == FD_VISITED_FREE) { + /* Already visited with another key */ + return TRUE; + } if (fd_head->flags & FD_SUBSET_TVB) fd_head->tvb_data = NULL; g_ptr_array_add(allocated_fragments, fd_head); @@ -391,11 +402,21 @@ free_all_reassembled_fragments(gpointer key_arg _U_, gpointer value, static void free_fragments(gpointer data, gpointer user_data _U_) { - fragment_item *fd_head = (fragment_item *) data; + fragment_head *fd_head = (fragment_head *) data; + fragment_item *fd_i, *tmp; if (fd_head->tvb_data) tvb_free(fd_head->tvb_data); - g_slice_free(fragment_item, fd_head); + for (fd_i = fd_head->next; fd_i; fd_i = tmp) { + tmp = fd_i->next; + if (fd_i->flags & FD_SUBSET_TVB) + fd_i->tvb_data = NULL; + if (fd_i->tvb_data) { + tvb_free(fd_i->tvb_data); + } + g_slice_free(fragment_item, fd_i); + } + g_slice_free(fragment_head, fd_head); } typedef struct register_reassembly_table { @@ -723,9 +744,8 @@ fragment_set_tot_len(reassembly_table *table, const packet_info *pinfo, * doesn't conflict with values set by existing fragments. * XXX - eliminate this check? */ - fd = fd_head; if (fd_head->flags & FD_BLOCKSEQUENCE) { - while (fd) { + for (fd = fd_head->next; fd; fd = fd->next) { if (fd->offset > max_offset) { max_offset = fd->offset; if (max_offset > tot_len) { @@ -733,7 +753,6 @@ fragment_set_tot_len(reassembly_table *table, const packet_info *pinfo, THROW_MESSAGE(ReassemblyError, fd_head->error); } } - fd = fd->next; } } @@ -829,7 +848,7 @@ fragment_truncate(reassembly_table *table, const packet_info *pinfo, * so we'll just leave the overlap flags as-is. */ fd_head->flags &= ~(FD_OVERLAP|FD_OVERLAPCONFLICT|FD_TOOLONGFRAGMENT|FD_MULTIPLETAILS); - fragment_item *fd_i, *prev_fd = fd_head; + fragment_item *fd_i, *prev_fd = NULL; for (fd_i = fd_head->next; fd_i && (fd_i->offset < tot_len); fd_i = fd_i->next) { fd_i->flags &= ~(FD_TOOLONGFRAGMENT|FD_MULTIPLETAILS); /* Check for the split point occuring in the middle of the @@ -850,7 +869,11 @@ fragment_truncate(reassembly_table *table, const packet_info *pinfo, } /* Remove all the other fragments, as they are past the split point. */ - prev_fd->next = NULL; + if (prev_fd) { + prev_fd->next = NULL; + } else { + fd_head->next = NULL; + } fragment_item *tmp_fd; for (; fd_i; fd_i = tmp_fd) { tmp_fd=fd_i->next; @@ -1007,12 +1030,18 @@ LINK_FRAG(fragment_head *fd_head,fragment_item *fd) fragment_item *fd_i; /* add fragment to list, keep list sorted */ - for(fd_i= fd_head; fd_i->next;fd_i=fd_i->next) { - if (fd->offset < fd_i->next->offset ) - break; + if (fd_head->next == NULL || fd->offset < fd_head->next->offset) { + /* New first fragment */ + fd->next = fd_head->next; + fd_head->next = fd; + } else { + for(fd_i = fd_head->next; fd_i->next; fd_i=fd_i->next) { + if (fd->offset < fd_i->next->offset ) + break; + } + fd->next = fd_i->next; + fd_i->next = fd; } - fd->next=fd_i->next; - fd_i->next=fd; } static void @@ -1022,7 +1051,12 @@ MERGE_FRAG(fragment_head *fd_head, fragment_item *fd) if (fd == NULL) return; - for(fd_i = fd_head; fd_i->next; fd_i=fd_i->next) { + if (fd_head->next == NULL || fd->offset < fd_head->next->offset) { + tmp = fd_head->next; + fd_head->next = fd; + fd = tmp; + } + for(fd_i = fd_head->next; fd_i->next; fd_i=fd_i->next) { if (fd->offset < fd_i->next->offset) { tmp = fd_i->next; fd_i->next = fd; @@ -1071,10 +1105,8 @@ fragment_add_work(fragment_head *fd_head, tvbuff_t *tvb, const int offset, fd->flags = 0; fd->frame = frag_frame; fd->offset = frag_offset; - fd->fragment_nr_offset = 0; /* will only be used with sequence */ fd->len = frag_data_len; fd->tvb_data = NULL; - fd->error = NULL; /* * Are we adding to an already-completed reassembly? @@ -1260,7 +1292,7 @@ fragment_add_work(fragment_head *fd_head, tvbuff_t *tvb, const int offset, 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) { + for (dfpos=0,fd_i=fd_head->next;fd_i;fd_i=fd_i->next) { if (fd_i->len) { /* * The loop above that calculates max also @@ -1839,7 +1871,6 @@ fragment_add_seq_work(fragment_head *fd_head, tvbuff_t *tvb, const int offset, fd->offset = frag_number_work; fd->len = frag_data_len; fd->tvb_data = NULL; - fd->error = NULL; /* fd_head->frame is the maximum of the frame numbers of all the * fragments added to the reassembly. */ @@ -2106,7 +2137,7 @@ fragment_add_seq_common(reassembly_table *table, tvbuff_t *tvb, * use the next expected fragment number as the fragment * number for this fragment. */ - for (fd = fd_head; fd != NULL; fd = fd->next) { + for (fd = fd_head->next; fd != NULL; fd = fd->next) { if (fd->next == NULL) frag_number = fd->offset + 1; } @@ -2289,7 +2320,7 @@ fragment_add_seq_single_move(reassembly_table *table, const packet_info *pinfo, new_fh = lookup_fd_head(table, pinfo, id+offset, data, NULL); if (new_fh != NULL) { /* Attach to the end of the sorted list. */ - for(prev_fd = fh; prev_fd->next != NULL; prev_fd=prev_fd->next) {} + for(prev_fd = fh->next; prev_fd->next != NULL; prev_fd=prev_fd->next) {} /* Don't take a reassembly starting with a First fragment. */ fd = new_fh->next; if (fd && fd->offset != 0) { @@ -2363,7 +2394,7 @@ fragment_add_seq_single_work(reassembly_table *table, tvbuff_t *tvb, for (frag_number=1; frag_number < max_frags; frag_number++) { new_fh = lookup_fd_head(table, pinfo, id-frag_number, data, NULL); if (new_fh != NULL) { - prev_fd = new_fh; + prev_fd = new_fh->next; new_fh->frame = 0; for (fd=new_fh->next; fd && fd->offset < frag_number; fd=fd->next) { prev_fd = fd; @@ -2371,7 +2402,9 @@ fragment_add_seq_single_work(reassembly_table *table, tvbuff_t *tvb, new_fh->frame = fd->frame; } } - prev_fd->next = NULL; + if (prev_fd) { + prev_fd->next = NULL; + } break; } } @@ -2441,7 +2474,7 @@ fragment_add_seq_single_work(reassembly_table *table, tvbuff_t *tvb, } if (last) { /* Look for fragments past the end set by this Last fragment. */ - prev_fd = fh; + prev_fd = fh->next; for (fd=fh->next; fd && fd->offset <= frag_number; fd=fd->next) { prev_fd = fd; } @@ -2453,7 +2486,9 @@ fragment_add_seq_single_work(reassembly_table *table, tvbuff_t *tvb, * looped around on the sequence numbers. It can also happen * if bit errors mess up Last or First. */ if (fd != NULL) { - prev_fd->next = NULL; + if (prev_fd) { + prev_fd->next = NULL; + } fh->frame = 0; for (prev_fd=fh->next; prev_fd; prev_fd=prev_fd->next) { if (fh->frame < prev_fd->frame) { @@ -2588,7 +2623,6 @@ fragment_start_seq_check(reassembly_table *table, const packet_info *pinfo, fd_head = g_slice_new(fragment_head); fd_head->next = NULL; fd_head->frame = 0; - fd_head->offset = 0; fd_head->len = 0; fd_head->fragment_nr_offset = 0; fd_head->datalen = tot_len; @@ -2609,7 +2643,9 @@ fragment_end_seq_next(reassembly_table *table, const packet_info *pinfo, reassembled_key reass_key; reassembled_key *new_key; fragment_head *fd_head; + fragment_item *fd; gpointer orig_key; + guint32 max_offset = 0; /* * Have we already seen this frame? @@ -2624,7 +2660,12 @@ fragment_end_seq_next(reassembly_table *table, const packet_info *pinfo, fd_head = lookup_fd_head(table, pinfo, id, data, &orig_key); if (fd_head) { - fd_head->datalen = fd_head->offset; + for (fd = fd_head->next; fd; fd = fd->next) { + if (fd->offset > max_offset) { + max_offset = fd->offset; + } + } + fd_head->datalen = max_offset; fd_head->flags |= FD_DATALEN_SET; fragment_defragment_and_free (fd_head, pinfo); diff --git a/epan/reassemble.h b/epan/reassemble.h index 14a41ebff5..9e97d9bc07 100644 --- a/epan/reassemble.h +++ b/epan/reassemble.h @@ -51,13 +51,25 @@ typedef struct _fragment_item { struct _fragment_item *next; - guint32 frame; /* XXX - does this apply to reassembly heads? */ - guint32 offset; /* XXX - does this apply to reassembly heads? */ - guint32 len; /* XXX - does this apply to reassembly heads? */ + guint32 frame; /**< frame number where the fragment is from */ + guint32 offset; /**< fragment number for FD_BLOCKSEQUENCE, byte + * offset otherwise */ + guint32 len; /**< fragment length */ + guint32 flags; /**< XXX - do some of these apply only to reassembly + * heads and others only to fragments within + * a reassembly? */ + tvbuff_t *tvb_data; +} fragment_item; + +typedef struct _fragment_head { + struct _fragment_item *next; + guint32 frame; /**< maximum of all frame numbers added to reassembly */ + guint32 len; /**< When flags&FD_BLOCKSEQUENCE and FD_DEFRAGMENTED + * are set, the number of bytes of the full datagram. + * Otherwise not valid. */ guint32 fragment_nr_offset; /**< offset for frame numbering, for sequences, where the * provided fragment number of the first fragment does - * not start with 0 - * XXX - does this apply only to reassembly heads? */ + * not start with 0 */ guint32 datalen; /**< When flags&FD_BLOCKSEQUENCE is set, the * index of the last block (segments in * datagram + 1); otherwise the number of @@ -65,11 +77,11 @@ typedef struct _fragment_item { * the first item of the fragments list when * flags&FD_DATALEN is set.*/ guint32 reassembled_in; /**< frame where this PDU was reassembled, - * only valid in the first item of the list - * and when FD_DEFRAGMENTED is set*/ - guint8 reas_in_layer_num; /**< The current "depth" or layer number in the current frame where reassembly was completed. - * Example: in SCTP there can be several data chunks and we want the reassemblied tvb for the final - * segment only. */ + * only valid when FD_DEFRAGMENTED is set */ + guint8 reas_in_layer_num; /**< The current "depth" or layer number in the current + * frame where reassembly was completed. + * Example: in SCTP there can be several data chunks and + * we want the reassemblied tvb for the final segment only. */ guint32 flags; /**< XXX - do some of these apply only to reassembly * heads and others only to fragments within * a reassembly? */ @@ -77,14 +89,9 @@ typedef struct _fragment_item { /** * Null if the reassembly had no error; non-null if it had * an error, in which case it's the string for the error. - * - * XXX - this is wasted in all but the reassembly head; we - * should probably have separate data structures for a - * reassembly and for the fragments in a reassembly. */ const char *error; -} fragment_item, fragment_head; - +} fragment_head; /* * Flags for fragment_add_seq_* @@ -359,7 +366,8 @@ fragment_start_seq_check(reassembly_table *table, const packet_info *pinfo, * Mark end of reassembly and returns the reassembled fragment (if completed). * Use it when fragments were added with "more_flags" set while you discovered * that no more fragments have to be added. - * XXX rename to fragment_finish as it works also for fragment_add? + * This is for fragments added with add_seq_next; it doesn't check for gaps, + * and doesn't set datalen correctly for the fragment_add family. */ WS_DLL_PUBLIC fragment_head * fragment_end_seq_next(reassembly_table *table, const packet_info *pinfo, diff --git a/epan/reassemble_test.c b/epan/reassemble_test.c index 3568f656a9..e988bc1cef 100644 --- a/epan/reassemble_test.c +++ b/epan/reassemble_test.c @@ -108,16 +108,32 @@ static struct _fd_flags { #define N_FD_FLAGS (signed)(sizeof(fd_flags)/sizeof(struct _fd_flags)) static void -print_fd(fragment_head *fd, gboolean is_head) { +print_fd_head(fragment_head *fd) { + int i; + + g_assert_true(fd != NULL); + printf(" %16p %16p %3u %3u", (void *)fd, (void *)(fd->next), fd->frame, fd->len); + + printf(" %3u %3u", fd->datalen, fd->reassembled_in); + + if (fd->tvb_data != NULL) { + printf(" %16p", tvb_get_ptr(fd->tvb_data, 0, 1)); /* Address of first byte only... */ + } else { + printf(" %16s", ""); + } + for (i=0; i < N_FD_FLAGS; i++) { + printf(" %s", (fd->flags & fd_flags[i].flag) ? fd_flags[i].flag_name : " "); + } + printf("\n"); +} + +static void +print_fd_item(fragment_item *fd) { int i; g_assert_true(fd != NULL); printf(" %16p %16p %3u %3u %3u", (void *)fd, (void *)(fd->next), fd->frame, fd->offset, fd->len); - if (is_head) { - printf(" %3u %3u", fd->datalen, fd->reassembled_in); - } else { - printf( " "); - } + printf( " "); if (fd->tvb_data != NULL) { printf(" %16p", tvb_get_ptr(fd->tvb_data, 0, 1)); /* Address of first byte only... */ } else { @@ -134,9 +150,9 @@ print_fd_chain(fragment_head *fd_head) { fragment_item *fdp; g_assert_true(fd_head != NULL); - print_fd(fd_head, TRUE); + print_fd_head(fd_head); for (fdp=fd_head->next; fdp != NULL; fdp=fdp->next) { - print_fd(fdp, FALSE); + print_fd_item(fdp); } } @@ -248,7 +264,6 @@ test_simple_fragment_add_seq(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame number of fragment in assembly */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(170,fd_head->len); /* the length of data we have */ ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(4,fd_head->reassembled_in); @@ -348,7 +363,6 @@ test_fragment_add_seq_partial_reassembly(void) /* check the contents of the structure */ ASSERT_EQ(1,fd_head->frame); /* max frame in reassembly */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(50,fd_head->len); /* the length of data we have */ ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(1,fd_head->reassembled_in); @@ -385,7 +399,6 @@ test_fragment_add_seq_partial_reassembly(void) /* check the contents of the structure */ ASSERT_EQ(2,fd_head->frame); /* max frame in reassembly */ - ASSERT_EQ(0,fd_head->offset); /* unused */ /* ASSERT_EQ(50,fd_head->len); the length of data we have */ ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(0,fd_head->reassembled_in); @@ -420,7 +433,6 @@ test_fragment_add_seq_partial_reassembly(void) fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL); ASSERT_NE_POINTER(NULL,fd_head); ASSERT_EQ(3,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ /* ASSERT_EQ(50,fd_head->len); the length of data we have */ ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(0,fd_head->reassembled_in); @@ -464,7 +476,6 @@ test_fragment_add_seq_partial_reassembly(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(190,fd_head->len); /* the length of data we have */ ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(4,fd_head->reassembled_in); @@ -522,7 +533,6 @@ test_fragment_add_seq_partial_reassembly(void) fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL); ASSERT_NE_POINTER(NULL,fd_head); ASSERT_EQ(5,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(230,fd_head->len); /* the length of data we have */ ASSERT_EQ(3,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(5,fd_head->reassembled_in); @@ -629,7 +639,6 @@ test_fragment_add_seq_duplicate_first(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(150,fd_head->len); /* the length of data we have */ ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(3,fd_head->reassembled_in); @@ -728,7 +737,6 @@ test_fragment_add_seq_duplicate_middle(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(150,fd_head->len); /* the length of data we have */ ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(4,fd_head->reassembled_in); @@ -826,7 +834,6 @@ test_fragment_add_seq_duplicate_last(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(150,fd_head->len); /* the length of data we have */ ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(3,fd_head->reassembled_in); @@ -928,7 +935,6 @@ test_fragment_add_seq_duplicate_conflict(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(150,fd_head->len); /* the length of data we have */ ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(4,fd_head->reassembled_in); @@ -1040,7 +1046,6 @@ test_fragment_add_seq_check_work(fragment_head *(*fn)(reassembly_table *, /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(170,fd_head->len); /* the length of data we have */ ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(4,fd_head->reassembled_in); @@ -1119,7 +1124,6 @@ test_fragment_add_seq_check_1(void) /* check the contents of the structure */ ASSERT_EQ(2,fd_head->frame); /* max frame of fragment in structure */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(110,fd_head->len); /* the length of data we have */ ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(2,fd_head->reassembled_in); @@ -1174,7 +1178,6 @@ test_fragment_add_seq_802_11_0(void) /* check the contents of the structure */ ASSERT_EQ(0,fd_head->frame); /* unused */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(0,fd_head->datalen); /* unused */ ASSERT_EQ(1,fd_head->reassembled_in); @@ -1312,7 +1315,6 @@ test_simple_fragment_add_seq_next(void) /* check the contents of the structure */ ASSERT_EQ(3,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(110,fd_head->len); /* the length of data we have */ ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(3,fd_head->reassembled_in); @@ -1365,7 +1367,6 @@ test_missing_data_fragment_add_seq_next(void) /* check the contents of the structure. Reassembly failed so everything * should be null (meaning, just use the original tvb) */ ASSERT_EQ(0,fd_head->frame); /* unused */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* the length of data we have */ ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(0,fd_head->reassembled_in); @@ -1488,7 +1489,6 @@ test_missing_data_fragment_add_seq_next_3(void) /* check the contents of the structure. */ ASSERT_EQ(0,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* the length of data we have */ ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(20,fd_head->reassembled_in); @@ -1507,7 +1507,6 @@ test_missing_data_fragment_add_seq_next_3(void) ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.reassembled_table)); ASSERT_NE_POINTER(NULL,fd_head); ASSERT_EQ(0,fd_head->frame); /* unused */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* the length of data we have */ ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */ ASSERT_EQ(20,fd_head->reassembled_in); @@ -1584,7 +1583,6 @@ test_simple_fragment_add(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame number of fragment in assembly */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused in fragment_add */ ASSERT_EQ(170,fd_head->datalen); /* total datalen of assembly */ ASSERT_EQ(4,fd_head->reassembled_in); @@ -1685,7 +1683,6 @@ test_fragment_add_partial_reassembly(void) /* check the contents of the structure */ ASSERT_EQ(1,fd_head->frame); /* max frame in reassembly */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(50,fd_head->datalen); /* the length of data we have */ ASSERT_EQ(1,fd_head->reassembled_in); @@ -1722,7 +1719,6 @@ test_fragment_add_partial_reassembly(void) /* check the contents of the structure */ ASSERT_EQ(2,fd_head->frame); /* max frame in reassembly */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ /* ASSERT_EQ(0,fd_head->datalen); * reassembly not finished; datalen not well defined. @@ -1759,7 +1755,6 @@ test_fragment_add_partial_reassembly(void) fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL); ASSERT_NE_POINTER(NULL,fd_head); ASSERT_EQ(3,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ /* ASSERT_EQ(0,fd_head->datalen); * reassembly not finished; datalen not well defined. @@ -1805,7 +1800,6 @@ test_fragment_add_partial_reassembly(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(190,fd_head->datalen); /* the length of data we have */ ASSERT_EQ(4,fd_head->reassembled_in); @@ -1863,7 +1857,6 @@ test_fragment_add_partial_reassembly(void) fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL); ASSERT_NE_POINTER(NULL,fd_head); ASSERT_EQ(5,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(230,fd_head->datalen); /* the length of data we have */ ASSERT_EQ(5,fd_head->reassembled_in); @@ -1992,7 +1985,6 @@ test_fragment_add_duplicate_first(void) /* check the contents of the structure */ /*ASSERT_EQ(4,fd_head->frame); max frame we have */ ASSERT_EQ(3,fd_head->frame); /* never add the duplicate frame */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(150,fd_head->datalen); ASSERT_EQ(3,fd_head->reassembled_in); @@ -2100,7 +2092,6 @@ test_fragment_add_duplicate_middle(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(150,fd_head->datalen); ASSERT_EQ(4,fd_head->reassembled_in); @@ -2224,7 +2215,6 @@ test_fragment_add_duplicate_last(void) /* check the contents of the structure */ /* ASSERT_EQ(4,fd_head->frame); never add the last frame again */ ASSERT_EQ(3,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(150,fd_head->datalen); ASSERT_EQ(3,fd_head->reassembled_in); @@ -2336,7 +2326,6 @@ test_fragment_add_duplicate_conflict(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(150,fd_head->datalen); ASSERT_EQ(4,fd_head->reassembled_in); @@ -2458,7 +2447,6 @@ test_simple_fragment_add_check(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame number of fragment in assembly */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused in fragment_add */ ASSERT_EQ(170,fd_head->datalen); /* total datalen of assembly */ ASSERT_EQ(4,fd_head->reassembled_in); @@ -2565,7 +2553,6 @@ test_fragment_add_check_partial_reassembly(void) /* check the contents of the structure */ ASSERT_EQ(1,fd_head->frame); /* max frame in reassembly */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(50,fd_head->datalen); /* the length of data we have */ ASSERT_EQ(1,fd_head->reassembled_in); @@ -2603,7 +2590,6 @@ test_fragment_add_check_partial_reassembly(void) /* check the contents of the structure */ ASSERT_EQ(2,fd_head->frame); /* max frame in reassembly */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ /* ASSERT_EQ(0,fd_head->datalen); * reassembly not finished; datalen not well defined. @@ -2640,7 +2626,6 @@ test_fragment_add_check_partial_reassembly(void) fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL); ASSERT_NE_POINTER(NULL,fd_head); ASSERT_EQ(3,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ /* ASSERT_EQ(0,fd_head->datalen); * reassembly not finished; datalen not well defined. @@ -2686,7 +2671,6 @@ test_fragment_add_check_partial_reassembly(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(190,fd_head->datalen); /* the length of data we have */ ASSERT_EQ(4,fd_head->reassembled_in); @@ -2744,7 +2728,6 @@ test_fragment_add_check_partial_reassembly(void) fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL); ASSERT_NE_POINTER(NULL,fd_head); ASSERT_EQ(5,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(230,fd_head->datalen); /* the length of data we have */ ASSERT_EQ(5,fd_head->reassembled_in); @@ -2878,7 +2861,6 @@ test_fragment_add_check_duplicate_first(void) /* check the contents of the structure */ /*ASSERT_EQ(4,fd_head->frame); max frame we have */ ASSERT_EQ(3,fd_head->frame); /* never add the duplicate frame */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(150,fd_head->datalen); ASSERT_EQ(3,fd_head->reassembled_in); @@ -2990,7 +2972,6 @@ test_fragment_add_check_duplicate_middle(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(150,fd_head->datalen); ASSERT_EQ(4,fd_head->reassembled_in); @@ -3102,7 +3083,6 @@ test_fragment_add_check_duplicate_last(void) /* check the contents of the structure */ /* ASSERT_EQ(4,fd_head->frame); never add the last frame again */ ASSERT_EQ(3,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(150,fd_head->datalen); ASSERT_EQ(3,fd_head->reassembled_in); @@ -3218,7 +3198,6 @@ test_fragment_add_check_duplicate_conflict(void) /* check the contents of the structure */ ASSERT_EQ(4,fd_head->frame); /* max frame we have */ - ASSERT_EQ(0,fd_head->offset); /* unused */ ASSERT_EQ(0,fd_head->len); /* unused */ ASSERT_EQ(150,fd_head->datalen); ASSERT_EQ(4,fd_head->reassembled_in); diff --git a/plugins/epan/opcua/opcua.c b/plugins/epan/opcua/opcua.c index b5d2d1b138..2eb3884f5b 100644 --- a/plugins/epan/opcua/opcua.c +++ b/plugins/epan/opcua/opcua.c @@ -226,6 +226,7 @@ static int dissect_opcua_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree * guint32 opcua_num = 0; guint32 opcua_seqnum = 0; fragment_head *frag_msg = NULL; + fragment_item *frag_i = NULL; offset = 3; @@ -281,8 +282,8 @@ static int dissect_opcua_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree * arbitrary value, so we have to fake the numbers in the stored fragments. this way Wireshark reassembles the message, as it expects the fragment sequence numbers to start at 0 */ - while (frag_msg->next) {frag_msg = frag_msg->next;} - opcua_seqnum = frag_msg->offset + 1; + for (frag_i = frag_msg->next; frag_i; frag_i = frag_i->next) {} + opcua_seqnum = frag_i->offset + 1; if (chunkType == 'F') {