Fix https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=3315 -
authormorriss <morriss@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 28 Feb 2012 03:19:49 +0000 (03:19 +0000)
committermorriss <morriss@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 28 Feb 2012 03:19:49 +0000 (03:19 +0000)
make Save-As/Displayed/All-Packets save not only the displayed packets but
also any other packets needed (e.g., for reassembly) to fully dissect the
displayed packets.

This works only for the "All packets" case; choosing only the Selected packet,
the Marked packets, or a range of packets would require actually storing which
packets depend on which (too much memory) or going through the packet list many
times (too slow).  Also, this behavior is always the case: you can't save the
displayed packets without their dependencies (I don't see why this would be
desirable).

So far this is done for SCTP and things using the reassembly routines (TCP has
been tested).

The Win32 dialog was modified but hasn't been tested yet.

One confusing aspect of the UI is that the Displayed count in the Save-As
dialog does not match the number of displayed packets.  (I tried renaming the
button "Displayed + Dependencies" but it looked too big.)  The tooltip tries
to explain this and the fact that this works only in the All-Packets case;
suggestions for improvement are welcome.

Implementation details:

Dissectors (or the reassembly code) can list frames which were needed to
build the current frame's tree.  If the current frame passes the display
filter then each listed frame is marked as "depended upon" (this takes up the
last free frame_data flag).

When performing a Save-As/Displayed/All-Packets then choose packets which
passed the dfilter _or_ are depended upon.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@41216 f5534014-38df-0310-8fa8-9805f1628bb7

17 files changed:
epan/dissectors/packet-sctp.c
epan/epan.c
epan/frame_data.c
epan/frame_data.h
epan/libwireshark.def
epan/packet.c
epan/packet.h
epan/packet_info.h
epan/reassemble.c
file.c
packet-range.c
packet-range.h
ui/gtk/capture_file_dlg.c
ui/gtk/print_dlg.c
ui/gtk/range_utils.c
ui/gtk/range_utils.h
ui/win32/file_dlg_win32.c

index de0f986f02dcca4a6760bb8ccae61fdac8245533..18fdfbb562a3d08cc3be697168297fab620a890a 100644 (file)
@@ -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;
                                      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;
         }
 
         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;
                                      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);
         }
       } 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;
                                      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);
         }
       }
 
         }
       }
 
index a74ee9538e3da72bb14b8e6a62c22316b96969ee..c61260a65fe5d0cf558def0f1526b1c159b0ad27 100644 (file)
@@ -172,6 +172,8 @@ epan_dissect_init(epan_dissect_t *edt, const gboolean create_proto_tree, const g
                edt->tree = NULL;
        }
 
                edt->tree = NULL;
        }
 
+       edt->pi.dependent_frames = NULL;
+
        return edt;
 }
 
        return edt;
 }
 
index c757f9b1a998e236bb1b7a7a8df5331a89f23863..6a456b1c6938fff31c140eab3ffa12d86d692a9d 100644 (file)
@@ -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->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;
   fdata->flags.encoding = PACKET_CHAR_ENC_CHAR_ASCII;
   fdata->flags.visited = 0;
   fdata->flags.marked = 0;
index 5b25275f357e452eb24a8f56b6155884ba3b89c4..1a2c258ec96519a70fb591f180f9dd43beaf309d 100644 (file)
@@ -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 */
   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 */
     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 */
index 02a6e837a0049563ad6fe7c5c62f65a17d2dfd45..b250865846b18acc21fa5d096d546b2a4b46b109 100644 (file)
@@ -646,6 +646,7 @@ list_stat_cmd_args
 llc_add_oui
 LocationRejectReason_vals       DATA
 make_printable_string
 llc_add_oui
 LocationRejectReason_vals       DATA
 make_printable_string
+mark_frame_as_depended_upon
 match_strrval
 match_strrval_idx
 match_strval
 match_strrval
 match_strrval_idx
 match_strval
index 135c8958e0ed02f8018c0520ef132315429f8c76..9cd70efa6aeb9934fdb78286e4305a9f9dcb01fe 100644 (file)
@@ -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
 /* 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
index 5db30200611654baaa8cc0c6c5267ae493ea9c9d..51465216d9c6b290926659edaa0034888672829a 100644 (file)
@@ -447,6 +447,14 @@ extern const char* get_data_source_name(data_source *src);
  */
 extern void free_data_sources(packet_info *pinfo);
 
  */
 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.
  */
 /*
  * Dissectors should never modify the packet data.
  */
index 95e1045f4632ad69c83ba83be1db0b09271d3725..49f444e76f14d33c55311f86f0217d61c8334979 100644 (file)
@@ -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.
                              */
   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. */
 } packet_info;
 
 /* For old code that hasn't yet been changed. */
index 7a82c8a631c364d943f6fd592e37297719c351f3..074861db8c648eb2a1f4a38716f3c8df3f178636 100644 (file)
@@ -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,
  */
 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;
 {
        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);
                        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
        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) {
                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;
        }
 
                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;
                        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;
        }
 
                first_frag = FALSE;
        }
 
diff --git a/file.c b/file.c
index 6766c8097aca70b308f0b3fb88a95b53ebc70c06..171bacec814e77304d1c52be1d9b221ecf627b1a 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1066,6 +1066,17 @@ void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
   cf->rfcode = 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,
 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;
   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;
 
     }
   } 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++;
 
   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;
     }
 
         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;
     if( fdata->flags.passed_dfilter ) {
         nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
         prev_dis_ts = fdata->abs_ts;
index ed9955e09447ec9b5da622fd7c370f202a018cde..6e0e49fd541d47342b663acfb53421c2b7ee54cb 100644 (file)
@@ -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_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;
     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) {
                 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++;
             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();
     }
 
         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;
     }
 
         return range_process_next;
     }
 
index 0a00af2e2e63e1406de6aba341d794407de5c3f8..fab651ca20f740b2a44516e67d3dd50119c502dd 100644 (file)
@@ -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 */
     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;
 
     /* 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;
 
     /* 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;
     guint32  displayed_marked_cnt;
     guint32  displayed_mark_range_cnt;
     guint32  displayed_user_range_cnt;
index c8b5e0495b8c3ac7354f9dc652976aebaa3d858c..05765f6813f8458f9188ae1c63e9fd586d56007b 100644 (file)
@@ -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;
   /* 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",
 
   /* 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 */
   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);
 
   gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
   gtk_widget_show(range_tb);
 
index 4536a9b0cae0a66c5e8945cc93108ba9a5c19448..803cd6a55b15254e839bd61d5d9f0d02b8b30946 100644 (file)
@@ -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);
 
   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);
 
   gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
   gtk_widget_show(range_tb);
 
index ded2a9e86a4066def5ea4076d5f9dc0771dafacf..6d4a039644791a36163db41783dc1baee1dd5390 100644 (file)
@@ -100,9 +100,10 @@ range_update_dynamics(gpointer data)
   gboolean      selected_packets;
   gchar         label_text[100];
   guint32       ignored_cnt = 0, displayed_ignored_cnt = 0;
   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 = 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));
 
   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);
   }
   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) {
   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 {
   } 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);
 
   }
   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);
 
 
   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;
   /* 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);
     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);
   }
 }
     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);
 
 
   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;
   /* 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);
 
 
   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;
   /* 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);
 
 
   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;
   /* 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);
 
 
   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;
   /* 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);
 
 
   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);
   }
   /* 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);
 
   /* 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);
   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;
   /* 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;
 
 
   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);
   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" */
 
 
 /* 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;
 {
   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;
   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);
   /* 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);
   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 */
 
 
   /* Process all packets */
index 6842ea199b944eff9800db43a365b8a67d4253f7..5c14488cf3695d7b291bdea20420d0ffe1529760 100644 (file)
@@ -42,9 +42,10 @@ extern gboolean range_check_validity(packet_range_t *range);
 /** Create a new range widget.
  *
  * @param range the range to set
 /** 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
  */
  * @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.
  *
 
 /* Update all "dynamic" range things.
  *
index 67bb7b9d92f4f4cc9c19ee40fc76ee6a34335c29..1a11b8d25ce6b82d3189a8da7f6f6da60731ceaa 100644 (file)
@@ -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;
             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);*/
 
             /* 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;
     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)
 
     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);
 
     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) {
     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 {
     } 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);
 
     }
     SetWindowText(cur_ctrl, static_val);