epan: Separate fragment_head and fragment_item

Separate fragment_head and fragment_item into two
different types of structs.

Remove "offset" from fragment_head, which was unused,
making fragment heads 4 bytes smaller.

Remove fragment_nr_offset, datalen, reassembled_in,
reas_in_layer_num, and error from fragment_item,
making them 24 bytes smaller.

Change a few dissectors which were using fragment_head
and fragment_item indistinguishably.

Ping #17311
This commit is contained in:
John Thacker 2022-11-12 10:23:01 -05:00
parent 0bfdd0d954
commit 4f3b028d94
14 changed files with 167 additions and 137 deletions

View File

@ -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,

View File

@ -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 ? */

View File

@ -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 */

View File

@ -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;

View File

@ -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,

View File

@ -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(&ampdu_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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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", "<null tvb_data>");
}
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);

View File

@ -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')
{