diff options
-rw-r--r-- | epan/dissectors/packet-sctp.c | 6 | ||||
-rw-r--r-- | epan/epan.c | 2 | ||||
-rw-r--r-- | epan/frame_data.c | 1 | ||||
-rw-r--r-- | epan/frame_data.h | 1 | ||||
-rw-r--r-- | epan/libwireshark.def | 1 | ||||
-rw-r--r-- | epan/packet.c | 9 | ||||
-rw-r--r-- | epan/packet.h | 8 | ||||
-rw-r--r-- | epan/packet_info.h | 5 | ||||
-rw-r--r-- | epan/reassemble.c | 8 | ||||
-rw-r--r-- | file.c | 24 | ||||
-rw-r--r-- | packet-range.c | 13 | ||||
-rw-r--r-- | packet-range.h | 2 | ||||
-rw-r--r-- | ui/gtk/capture_file_dlg.c | 3 | ||||
-rw-r--r-- | ui/gtk/print_dlg.c | 2 | ||||
-rw-r--r-- | ui/gtk/range_utils.c | 42 | ||||
-rw-r--r-- | ui/gtk/range_utils.h | 3 | ||||
-rw-r--r-- | ui/win32/file_dlg_win32.c | 10 |
17 files changed, 109 insertions, 31 deletions
diff --git a/epan/dissectors/packet-sctp.c b/epan/dissectors/packet-sctp.c index de0f986f02..18fdfbb562 100644 --- a/epan/dissectors/packet-sctp.c +++ b/epan/dissectors/packet-sctp.c @@ -2356,6 +2356,8 @@ fragment_reassembly(tvbuff_t *tvb, sctp_fragment* fragment, frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)", 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); } for (frag_i = msg->fragments; @@ -2366,6 +2368,8 @@ fragment_reassembly(tvbuff_t *tvb, sctp_fragment* fragment, frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)", 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); } } else { for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num); @@ -2376,6 +2380,8 @@ fragment_reassembly(tvbuff_t *tvb, sctp_fragment* fragment, frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)", 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); } } diff --git a/epan/epan.c b/epan/epan.c index a74ee9538e..c61260a65f 100644 --- a/epan/epan.c +++ b/epan/epan.c @@ -172,6 +172,8 @@ epan_dissect_init(epan_dissect_t *edt, const gboolean create_proto_tree, const g edt->tree = NULL; } + edt->pi.dependent_frames = NULL; + return edt; } diff --git a/epan/frame_data.c b/epan/frame_data.c index c757f9b1a9..6a456b1c69 100644 --- a/epan/frame_data.c +++ b/epan/frame_data.c @@ -207,6 +207,7 @@ frame_data_init(frame_data *fdata, guint32 num, fdata->shift_offset.secs = 0; fdata->shift_offset.nsecs = 0; fdata->flags.passed_dfilter = 0; + fdata->flags.dependent_of_displayed = 0; fdata->flags.encoding = PACKET_CHAR_ENC_CHAR_ASCII; fdata->flags.visited = 0; fdata->flags.marked = 0; diff --git a/epan/frame_data.h b/epan/frame_data.h index 5b25275f35..1a2c258ec9 100644 --- a/epan/frame_data.h +++ b/epan/frame_data.h @@ -51,6 +51,7 @@ typedef struct _frame_data { gint16 lnk_t; /**< Per-packet encapsulation/data-link type */ struct { 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 */ unsigned int encoding : 2; /**< Character encoding (ASCII, EBCDIC...) */ unsigned int visited : 1; /**< Has this packet been visited yet? 1=Yes,0=No*/ unsigned int marked : 1; /**< 1 = marked by user, 0 = normal */ diff --git a/epan/libwireshark.def b/epan/libwireshark.def index 02a6e837a0..b250865846 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -646,6 +646,7 @@ list_stat_cmd_args llc_add_oui LocationRejectReason_vals DATA make_printable_string +mark_frame_as_depended_upon match_strrval match_strrval_idx match_strval diff --git a/epan/packet.c b/epan/packet.c index 135c8958e0..9cd70efa6a 100644 --- a/epan/packet.c +++ b/epan/packet.c @@ -238,6 +238,15 @@ free_data_sources(packet_info *pinfo) } } +void +mark_frame_as_depended_upon(packet_info *pinfo, guint32 frame_num) +{ + /* Don't mark a frame as dependent on itself */ + if (frame_num != PINFO_FD_NUM(pinfo)) { + pinfo->dependent_frames = g_slist_prepend(pinfo->dependent_frames, GUINT_TO_POINTER(frame_num)); + } +} + /* Allow dissectors to register a "final_registration" routine * that is run like the proto_register_XXX() routine, but at the * end of the epan_init() function; that is, *after* all other diff --git a/epan/packet.h b/epan/packet.h index 5db3020061..51465216d9 100644 --- a/epan/packet.h +++ b/epan/packet.h @@ -447,6 +447,14 @@ extern const char* get_data_source_name(data_source *src); */ extern void free_data_sources(packet_info *pinfo); +/* Mark another frame as depended upon by the current frame. + * + * This information is used to ensure that the dependend-upon frame is saved + * if the user does a File->Save-As of only the Displayed packets and the + * current frame passed the display filter. + */ +extern void mark_frame_as_depended_upon(packet_info *pinfo, guint32 frame_num); + /* * Dissectors should never modify the packet data. */ diff --git a/epan/packet_info.h b/epan/packet_info.h index 95e1045f46..49f444e76f 100644 --- a/epan/packet_info.h +++ b/epan/packet_info.h @@ -200,9 +200,8 @@ typedef struct _packet_info { guint8 zbee_stack_vers; /* ZigBee stack version number, present in the ZigBee network layer, but * impacts the packet format at all layers of the ZigBee stack. */ - int link_dir; /* 3GPP messages are sometime different UP link(UL) or Downlink(DL) - * - */ + int link_dir; /* 3GPP messages are sometime different UP link(UL) or Downlink(DL) */ + GSList* dependent_frames; /* A list of frames which this one depends on */ } packet_info; /* For old code that hasn't yet been changed. */ diff --git a/epan/reassemble.c b/epan/reassemble.c index 7a82c8a631..074861db8c 100644 --- a/epan/reassemble.c +++ b/epan/reassemble.c @@ -1898,7 +1898,8 @@ process_reassembled_data(tvbuff_t *tvb, const int offset, packet_info *pinfo, */ static void show_fragment(fragment_data *fd, const int offset, const fragment_items *fit, - proto_tree *ft, proto_item *fi, const gboolean first_frag, const guint32 count, tvbuff_t *tvb) + proto_tree *ft, proto_item *fi, const gboolean first_frag, + const guint32 count, tvbuff_t *tvb, packet_info *pinfo) { proto_item *fei=NULL; int hf; @@ -1942,6 +1943,7 @@ show_fragment(fragment_data *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); if (fd->flags & (FD_OVERLAP|FD_OVERLAPCONFLICT |FD_MULTIPLETAILS|FD_TOOLONGFRAGMENT) ) { /* this fragment has some flags set, create a subtree @@ -2023,7 +2025,7 @@ show_fragment_tree(fragment_data *fd_head, const fragment_items *fit, count++; } for (fd = fd_head->next; fd != NULL; fd = fd->next) { - show_fragment(fd, fd->offset, fit, ft, *fi, first_frag, count, tvb); + show_fragment(fd, fd->offset, fit, ft, *fi, first_frag, count, tvb, pinfo); first_frag = FALSE; } @@ -2077,7 +2079,7 @@ show_fragment_seq_tree(fragment_data *fd_head, const fragment_items *fit, next_offset += fd->len; } last_fd = fd; - show_fragment(fd, offset, fit, ft, *fi, first_frag, count, tvb); + show_fragment(fd, offset, fit, ft, *fi, first_frag, count, tvb, pinfo); first_frag = FALSE; } @@ -1066,6 +1066,17 @@ void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode) cf->rfcode = rfcode; } +static void +find_and_mark_frame_depended_upon(gpointer data, gpointer user_data) +{ + frame_data *dependent_fd; + guint32 dependent_frame = GPOINTER_TO_UINT(data); + capture_file *cf = (capture_file *)user_data; + + dependent_fd = frame_data_sequence_find(cf->frames, dependent_frame); + dependent_fd->flags.dependent_of_displayed = 1; +} + static int add_packet_to_packet_list(frame_data *fdata, capture_file *cf, dfilter_t *dfcode, gboolean filtering_tap_listeners, @@ -1114,10 +1125,19 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, if (dfcode != NULL) { if (refilter) { fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0; + + /* This frame passed the display filter but it may depend on other + * (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); } } else fdata->flags.passed_dfilter = 1; + /* We're done with this list */ + g_slist_free(edt.pi.dependent_frames); + if(fdata->flags.passed_dfilter || fdata->flags.ref_time) cf->displayed_count++; @@ -1983,8 +2003,8 @@ ref_time_packets(capture_file *cf) cf->elapsed_time = fdata->rel_ts; } - /* If this frame is displayed, get the time elapsed between the - previous displayed packet and this packet. */ + /* If this frame is displayed, get the time elapsed between the + previous displayed packet and this packet. */ if( fdata->flags.passed_dfilter ) { nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts); prev_dis_ts = fdata->abs_ts; diff --git a/packet-range.c b/packet-range.c index ed9955e094..6e0e49fd54 100644 --- a/packet-range.c +++ b/packet-range.c @@ -66,6 +66,7 @@ static void packet_range_calc(packet_range_t *range) { range->displayed_cnt = 0L; range->displayed_marked_cnt = 0L; range->displayed_mark_range_cnt=0L; + range->displayed_plus_dependents_cnt = 0L; range->displayed_ignored_cnt = 0L; range->displayed_ignored_marked_cnt = 0L; range->displayed_ignored_mark_range_cnt = 0L; @@ -95,6 +96,10 @@ static void packet_range_calc(packet_range_t *range) { if (packet->flags.passed_dfilter) { range->displayed_cnt++; } + if (packet->flags.passed_dfilter || + packet->flags.dependent_of_displayed) { + range->displayed_plus_dependents_cnt++; + } if (packet->flags.marked) { if (packet->flags.ignored) { range->ignored_marked_cnt++; @@ -292,8 +297,12 @@ range_process_e packet_range_process_packet(packet_range_t *range, frame_data *f g_assert_not_reached(); } - /* this packet has to pass the display filter but didn't? -> try next */ - if (range->process_filtered && fdata->flags.passed_dfilter == FALSE) { + /* This packet has to pass the display filter but didn't? + * Try next, but only if we're not including dependent packets and this + * packet happens to be a dependency on something that is displayed. + */ + if ((range->process_filtered && fdata->flags.passed_dfilter == FALSE) && + !(range->include_dependents && fdata->flags.dependent_of_displayed)) { return range_process_next; } diff --git a/packet-range.h b/packet-range.h index 0a00af2e2e..fab651ca20 100644 --- a/packet-range.h +++ b/packet-range.h @@ -49,6 +49,7 @@ typedef struct packet_range_tag { packet_range_e process; /* which range to process */ gboolean process_filtered; /* captured or filtered packets */ gboolean remove_ignored; /* remove ignored packets */ + gboolean include_dependents; /* True if packets which are dependents of others should be processed */ /* user specified range(s) and, if null, error status */ range_t *user_range; @@ -69,6 +70,7 @@ typedef struct packet_range_tag { /* current packet counts (displayed) */ guint32 displayed_cnt; + guint32 displayed_plus_dependents_cnt; guint32 displayed_marked_cnt; guint32 displayed_mark_range_cnt; guint32 displayed_user_range_cnt; diff --git a/ui/gtk/capture_file_dlg.c b/ui/gtk/capture_file_dlg.c index c8b5e0495b..05765f6813 100644 --- a/ui/gtk/capture_file_dlg.c +++ b/ui/gtk/capture_file_dlg.c @@ -1184,6 +1184,7 @@ file_save_as_cmd(action_after_save_e action_after_save, gpointer action_after_sa /* init the packet range */ packet_range_init(&range); range.process_filtered = save_only_displayed; + range.include_dependents = TRUE; /* build the file selection */ file_save_as_w = file_selection_new ("Wireshark: Save Capture File As", @@ -1207,7 +1208,7 @@ file_save_as_cmd(action_after_save_e action_after_save, gpointer action_after_sa gtk_widget_show(range_fr); /* range table */ - range_tb = range_new(&range); + range_tb = range_new(&range, TRUE); gtk_container_add(GTK_CONTAINER(range_fr), range_tb); gtk_widget_show(range_tb); diff --git a/ui/gtk/print_dlg.c b/ui/gtk/print_dlg.c index 4536a9b0ca..803cd6a55b 100644 --- a/ui/gtk/print_dlg.c +++ b/ui/gtk/print_dlg.c @@ -681,7 +681,7 @@ open_print_dialog(const char *title, output_action_e action, print_args_t *args) gtk_box_pack_start(GTK_BOX(packet_hb), range_fr, FALSE, FALSE, 0); gtk_widget_show(range_fr); - range_tb = range_new(&args->range); + range_tb = range_new(&args->range, FALSE); gtk_container_add(GTK_CONTAINER(range_fr), range_tb); gtk_widget_show(range_tb); diff --git a/ui/gtk/range_utils.c b/ui/gtk/range_utils.c index ded2a9e86a..6d4a039644 100644 --- a/ui/gtk/range_utils.c +++ b/ui/gtk/range_utils.c @@ -100,9 +100,10 @@ range_update_dynamics(gpointer data) gboolean selected_packets; gchar label_text[100]; guint32 ignored_cnt = 0, displayed_ignored_cnt = 0; + guint32 displayed_cnt; range = g_object_get_data(G_OBJECT(data), RANGE_VALUES_KEY); - + range_displayed_bt = g_object_get_data(G_OBJECT(data), RANGE_DISPLAYED_BT_KEY); filtered_active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(range_displayed_bt)); @@ -126,10 +127,14 @@ range_update_dynamics(gpointer data) } gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(data), RANGE_SELECT_ALL_C_KEY)), label_text); gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(data), RANGE_SELECT_ALL_D_KEY), filtered_active); + if (range->include_dependents) + displayed_cnt = range->displayed_plus_dependents_cnt; + else + displayed_cnt = range->displayed_cnt; if (range->remove_ignored) { - g_snprintf(label_text, sizeof(label_text), "%u", range->displayed_cnt - range->displayed_ignored_cnt); + g_snprintf(label_text, sizeof(label_text), "%u", displayed_cnt - range->displayed_ignored_cnt); } else { - g_snprintf(label_text, sizeof(label_text), "%u", range->displayed_cnt); + g_snprintf(label_text, sizeof(label_text), "%u", displayed_cnt); } gtk_label_set_text(GTK_LABEL(g_object_get_data(G_OBJECT(data), RANGE_SELECT_ALL_D_KEY)), label_text); @@ -329,7 +334,7 @@ toggle_filtered_cb(GtkWidget *widget, gpointer data) range = g_object_get_data(G_OBJECT(data), RANGE_VALUES_KEY); - + /* is the button now active? */ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) { range->process_filtered = TRUE; @@ -337,7 +342,7 @@ toggle_filtered_cb(GtkWidget *widget, gpointer data) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bt), FALSE); bt = g_object_get_data(G_OBJECT(data), RANGE_DISPLAYED_BT_KEY); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bt), TRUE); - + range_update_dynamics(data); } } @@ -349,7 +354,7 @@ toggle_select_all(GtkWidget *widget, gpointer data) range = g_object_get_data(G_OBJECT(data), RANGE_VALUES_KEY); - + /* is the button now active? */ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) { range->process = range_process_all; @@ -364,7 +369,7 @@ toggle_select_selected(GtkWidget *widget, gpointer data) range = g_object_get_data(G_OBJECT(data), RANGE_VALUES_KEY); - + /* is the button now active? */ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) { range->process = range_process_selected; @@ -379,7 +384,7 @@ toggle_select_marked_only(GtkWidget *widget, gpointer data) range = g_object_get_data(G_OBJECT(data), RANGE_VALUES_KEY); - + /* is the button now active? */ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) { range->process = range_process_marked; @@ -394,7 +399,7 @@ toggle_select_marked_range(GtkWidget *widget, gpointer data) range = g_object_get_data(G_OBJECT(data), RANGE_VALUES_KEY); - + /* is the button now active? */ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) { range->process = range_process_marked_range; @@ -409,13 +414,13 @@ toggle_select_user_range(GtkWidget *widget, gpointer data) range = g_object_get_data(G_OBJECT(data), RANGE_VALUES_KEY); - + /* is the button now active? */ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) { range->process = range_process_user_range; range_update_dynamics(data); } - + /* Make the entry widget sensitive or insensitive */ gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(data), RANGE_SELECT_USER_ENTRY_KEY), range->process == range_process_user_range); @@ -431,7 +436,7 @@ toggle_remove_ignored(GtkWidget *widget, gpointer data) packet_range_t *range; range = g_object_get_data(G_OBJECT(data), RANGE_VALUES_KEY); - + /* is the button now active? */ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) { range->remove_ignored = TRUE; @@ -450,7 +455,7 @@ range_entry(GtkWidget *widget _U_, gpointer data) packet_range_t *range; - range = g_object_get_data(G_OBJECT(data), RANGE_VALUES_KEY); + range = g_object_get_data(G_OBJECT(data), RANGE_VALUES_KEY); entry = g_object_get_data(G_OBJECT(data), RANGE_SELECT_USER_ENTRY_KEY); gtk_toggle_button_set_active(g_object_get_data(G_OBJECT(data), RANGE_SELECT_USER_KEY), TRUE); @@ -480,7 +485,7 @@ range_entry_in_event(GtkWidget *widget _U_, GdkEventFocus *event _U_, gpointer u /* create a new range "widget" */ -GtkWidget *range_new(packet_range_t *range) +GtkWidget *range_new(packet_range_t *range, gboolean saving) { GtkWidget *range_tb; GtkWidget *captured_bt; @@ -505,7 +510,7 @@ GtkWidget *range_new(packet_range_t *range) GtkWidget *remove_ignored_cb; GtkWidget *ignored_c_lb; GtkWidget *ignored_d_lb; - + /* range table */ range_tb = gtk_table_new(7, 3, FALSE); gtk_container_set_border_width(GTK_CONTAINER(range_tb), 5); @@ -520,7 +525,12 @@ GtkWidget *range_new(packet_range_t *range) displayed_bt = gtk_toggle_button_new_with_mnemonic("_Displayed"); gtk_table_attach_defaults(GTK_TABLE(range_tb), displayed_bt, 2, 3, 0, 1); g_signal_connect(displayed_bt, "toggled", G_CALLBACK(toggle_filtered_cb), range_tb); - gtk_widget_set_tooltip_text (displayed_bt,("Process only the below chosen packets, which also passes the current display filter")); + if (saving) + gtk_widget_set_tooltip_text (displayed_bt,("Save the packets chosen below which also pass the current display filter. If" + " \"all packets\" is selected then packets required (e.g., for reassembled data) by the packets" + " that passed the display filter are also included.")); + else + gtk_widget_set_tooltip_text (displayed_bt,("Process only the below chosen packets which also pass the current display filter")); /* Process all packets */ diff --git a/ui/gtk/range_utils.h b/ui/gtk/range_utils.h index 6842ea199b..5c14488cf3 100644 --- a/ui/gtk/range_utils.h +++ b/ui/gtk/range_utils.h @@ -42,9 +42,10 @@ extern gboolean range_check_validity(packet_range_t *range); /** Create a new range widget. * * @param range the range to set + * @param saving TRUE if range is selecting packets to save * @return the new range widget */ -extern GtkWidget *range_new(packet_range_t *range); +extern GtkWidget *range_new(packet_range_t *range, gboolean saving); /* Update all "dynamic" range things. * diff --git a/ui/win32/file_dlg_win32.c b/ui/win32/file_dlg_win32.c index 67bb7b9d92..1a11b8d25c 100644 --- a/ui/win32/file_dlg_win32.c +++ b/ui/win32/file_dlg_win32.c @@ -1571,6 +1571,7 @@ save_as_file_hook_proc(HWND sf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) { packet_range_init(&g_range); /* default to displayed packets */ g_range.process_filtered = TRUE; + g_range.include_dependents = TRUE; /* Fill in the file format list */ /*build_file_format_list(sf_hwnd);*/ @@ -1662,6 +1663,7 @@ range_update_dynamics(HWND dlg_hwnd, packet_range_t *range) { TCHAR static_val[STATIC_LABEL_CHARS]; gint selected_num; guint32 ignored_cnt = 0, displayed_ignored_cnt = 0; + guint32 displayed_cnt; cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_DISPLAYED_BTN); if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) @@ -1679,10 +1681,14 @@ range_update_dynamics(HWND dlg_hwnd, packet_range_t *range) { cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_DISP); EnableWindow(cur_ctrl, filtered_active); + if (range->include_dependents) + displayed_cnt = range->displayed_plus_dependents_cnt; + else + displayed_cnt = range->displayed_cnt; if (range->remove_ignored) { - _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_cnt - range->displayed_ignored_cnt); + _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), displayed_cnt - range->displayed_ignored_cnt); } else { - _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_cnt); + _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), displayed_cnt); } SetWindowText(cur_ctrl, static_val); |