epan: Allow nested dependent packets

Save all dependent frames when there are multiple levels
of reassembly.

This is a retry of !6329, combined with the fix in !6509 which
were reverted in !6545.

epan: fix a segfault, introduced in !6329
master
Sake Blok 2022-02-27 15:35:58 +01:00 committed by Sake Blok
parent 693dc40936
commit f870c6085d
15 changed files with 30 additions and 26 deletions

View File

@ -1879,7 +1879,7 @@ static void dissect_host_anchor_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree
proto_item_set_generated(pi);
/* XXX: Need to do this each time because pinfo is discarded. Filtering does not reset visited as it does not do a full redissect.
We also might not catch all frames in the first pass (e.g. comment after record). */
mark_frame_as_depended_upon(pinfo, anchored_info->frame_num);
mark_frame_as_depended_upon(pinfo->fd, anchored_info->frame_num);
}
frame = wmem_list_frame_next(frame);
}
@ -1925,12 +1925,12 @@ dissect_host_id_source_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
pi = proto_tree_add_uint(hostid_tree, hf_erf_source_next, tvb, 0, 0, fnum_next);
proto_item_set_generated(pi);
/* XXX: Save the surrounding nearest periodic records when we do a filtered save so we keep native ERF metadata */
mark_frame_as_depended_upon(pinfo, fnum_next);
mark_frame_as_depended_upon(pinfo->fd, fnum_next);
}
if (fnum != G_MAXUINT32) {
pi = proto_tree_add_uint(hostid_tree, hf_erf_source_prev, tvb, 0, 0, fnum);
proto_item_set_generated(pi);
mark_frame_as_depended_upon(pinfo, fnum);
mark_frame_as_depended_upon(pinfo->fd, fnum);
}
}
}

View File

@ -2919,7 +2919,7 @@ fragment_reassembly(tvbuff_t *tvb, sctp_fragment *fragment,
frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
offset += frag_i->len;
mark_frame_as_depended_upon(pinfo, frag_i->frame_num);
mark_frame_as_depended_upon(pinfo->fd, frag_i->frame_num);
}
for (frag_i = msg->fragments;
@ -2931,7 +2931,7 @@ fragment_reassembly(tvbuff_t *tvb, sctp_fragment *fragment,
frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
offset += frag_i->len;
mark_frame_as_depended_upon(pinfo, frag_i->frame_num);
mark_frame_as_depended_upon(pinfo->fd, frag_i->frame_num);
}
} else {
for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num, u_bit);
@ -2943,7 +2943,7 @@ fragment_reassembly(tvbuff_t *tvb, sctp_fragment *fragment,
frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
offset += frag_i->len;
mark_frame_as_depended_upon(pinfo, frag_i->frame_num);
mark_frame_as_depended_upon(pinfo->fd, frag_i->frame_num);
}
}
@ -3158,7 +3158,7 @@ fragment_reassembly(tvbuff_t *tvb, sctp_fragment *fragment,
frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
offset += frag_i->len;
mark_frame_as_depended_upon(pinfo, frag_i->frame_num);
mark_frame_as_depended_upon(pinfo->fd, frag_i->frame_num);
}
for (frag_i = msg->fragments;
@ -3170,7 +3170,7 @@ fragment_reassembly(tvbuff_t *tvb, sctp_fragment *fragment,
frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
offset += frag_i->len;
mark_frame_as_depended_upon(pinfo, frag_i->frame_num);
mark_frame_as_depended_upon(pinfo->fd, frag_i->frame_num);
}
} else {
for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num, u_bit);
@ -3182,7 +3182,7 @@ fragment_reassembly(tvbuff_t *tvb, sctp_fragment *fragment,
frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
offset += frag_i->len;
mark_frame_as_depended_upon(pinfo, frag_i->frame_num);
mark_frame_as_depended_upon(pinfo->fd, frag_i->frame_num);
}
}

View File

@ -611,7 +611,7 @@ tree_add_fragment_list(struct rlc_sdu *sdu, tvbuff_t *tvb,packet_info *pinfo, pr
sdufrag->frame_num, sdufrag->seq);
}
mark_frame_as_depended_upon(pinfo, sdufrag->frame_num);
mark_frame_as_depended_upon(pinfo->fd, sdufrag->frame_num);
offset += sdufrag->len;
sdufrag = sdufrag->next;

View File

@ -573,7 +573,6 @@ epan_dissect_reset(epan_dissect_t *edt)
wtap_block_unref(edt->pi.rec->block);
g_slist_free(edt->pi.proto_data);
g_slist_free(edt->pi.dependent_frames);
/* Free the data sources list. */
free_data_sources(&edt->pi);
@ -684,7 +683,6 @@ epan_dissect_cleanup(epan_dissect_t* edt)
g_slist_foreach(epan_plugins, epan_plugin_dissect_cleanup, edt);
g_slist_free(edt->pi.proto_data);
g_slist_free(edt->pi.dependent_frames);
/* Free the data sources list. */
free_data_sources(&edt->pi);

View File

@ -161,6 +161,7 @@ frame_data_init(frame_data *fdata, guint32 num, const wtap_rec *rec,
fdata->subnum = 0;
fdata->passed_dfilter = 0;
fdata->dependent_of_displayed = 0;
fdata->dependent_frames = NULL;
fdata->encoding = PACKET_CHAR_ENC_CHAR_ASCII;
fdata->visited = 0;
fdata->marked = 0;
@ -306,6 +307,11 @@ frame_data_destroy(frame_data *fdata)
g_slist_free(fdata->pfd);
fdata->pfd = NULL;
}
if (fdata->dependent_frames) {
g_slist_free(fdata->dependent_frames);
fdata->dependent_frames = NULL;
}
}
/*

View File

@ -77,6 +77,7 @@ typedef struct _frame_data {
are 32 bits. */
unsigned int passed_dfilter : 1; /**< 1 = display, 0 = no display */
unsigned int dependent_of_displayed : 1; /**< 1 if a displayed frame depends on this frame */
GSList *dependent_frames; /**< A list of frames which this one depends on */
/* Do NOT use packet_char_enc enum here: MSVC compiler does not handle an enum in a bit field properly */
unsigned int encoding : 1; /**< Character encoding (ASCII, EBCDIC...) */
unsigned int visited : 1; /**< Has this packet been visited yet? 1=Yes,0=No*/

View File

@ -321,6 +321,7 @@ find_and_mark_frame_depended_upon(gpointer data, gpointer user_data)
if (dependent_frame && frames) {
dependent_fd = frame_data_sequence_find(frames, dependent_frame);
dependent_fd->dependent_of_displayed = 1;
g_slist_foreach(dependent_fd->dependent_frames, find_and_mark_frame_depended_upon, frames);
}
}

View File

@ -445,11 +445,11 @@ free_data_sources(packet_info *pinfo)
}
void
mark_frame_as_depended_upon(packet_info *pinfo, guint32 frame_num)
mark_frame_as_depended_upon(frame_data *fd, guint32 frame_num)
{
/* Don't mark a frame as dependent on itself */
if (frame_num != pinfo->num) {
pinfo->dependent_frames = g_slist_prepend(pinfo->dependent_frames, GUINT_TO_POINTER(frame_num));
if (frame_num != fd->num) {
fd->dependent_frames = g_slist_prepend(fd->dependent_frames, GUINT_TO_POINTER(frame_num));
}
}

View File

@ -772,7 +772,7 @@ extern void free_data_sources(packet_info *pinfo);
* if the user does a File->Save-As of only the Displayed packets and the
* current frame passed the display filter.
*/
WS_DLL_PUBLIC void mark_frame_as_depended_upon(packet_info *pinfo, guint32 frame_num);
WS_DLL_PUBLIC void mark_frame_as_depended_upon(frame_data *fd, guint32 frame_num);
/* Structure passed to the frame dissector */
typedef struct frame_data_s

View File

@ -149,8 +149,6 @@ typedef struct _packet_info {
GSList* proto_data; /**< Per packet proto data */
GSList* dependent_frames; /**< A list of frames which this one depends on */
GSList* frame_end_routines;
wmem_allocator_t *pool; /**< Memory pool scoped to the pinfo struct */

View File

@ -2964,7 +2964,7 @@ show_fragment(fragment_item *fd, const int offset, const fragment_items *fit,
plurality(fd->len, "", "s"));
}
proto_item_set_generated(fei);
mark_frame_as_depended_upon(pinfo, fd->frame);
mark_frame_as_depended_upon(pinfo->fd, fd->frame);
if (fd->flags & (FD_OVERLAP|FD_OVERLAPCONFLICT
|FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) {
/* this fragment has some flags set, create a subtree

2
file.c
View File

@ -1199,7 +1199,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
* (potentially not displayed) frames. Find those frames and mark them
* as depended upon.
*/
g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
g_slist_foreach(edt->pi.fd->dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
}
} else
fdata->passed_dfilter = 1;

View File

@ -309,14 +309,14 @@ process_packet(capture_file *cf, epan_dissect_t *edt,
cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
/* If we're not doing dissection then there won't be any dependent frames.
* More importantly, edt.pi.dependent_frames won't be initialized because
* More importantly, edt.pi.fd.dependent_frames won't be initialized because
* epan hasn't been initialized.
* if we *are* doing dissection, then mark the dependent frames, but only
* if a display filter was given and it matches this packet.
*/
if (edt && cf->dfcode) {
if (dfilter_apply_edt(cf->dfcode, edt)) {
g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
g_slist_foreach(edt->pi.fd->dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
}
}

View File

@ -1068,11 +1068,11 @@ process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
/* If we're not doing dissection then there won't be any dependent frames.
* More importantly, edt.pi.dependent_frames won't be initialized because
* More importantly, edt.pi.fd.dependent_frames won't be initialized because
* epan hasn't been initialized.
*/
if (edt) {
g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
g_slist_foreach(edt->pi.fd->dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
}
cf->count++;

View File

@ -3050,14 +3050,14 @@ process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
/* If we're not doing dissection then there won't be any dependent frames.
* More importantly, edt.pi.dependent_frames won't be initialized because
* More importantly, edt.pi.fd.dependent_frames won't be initialized because
* epan hasn't been initialized.
* if we *are* doing dissection, then mark the dependent frames, but only
* if a display filter was given and it matches this packet.
*/
if (edt && cf->dfcode) {
if (dfilter_apply_edt(cf->dfcode, edt)) {
g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
g_slist_foreach(edt->pi.fd->dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
}
if (selected_frame_number != 0 && selected_frame_number == cf->count + 1) {