6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #include <epan/epan.h>
47 #include <epan/filesystem.h>
50 #include "color_filters.h"
52 #include <epan/column.h>
53 #include <epan/packet.h>
54 #include "packet-range.h"
60 #include "alert_box.h"
61 #include "simple_dialog.h"
62 #include "progress_dlg.h"
64 #include <epan/prefs.h>
65 #include <epan/dfilter/dfilter.h>
66 #include <epan/epan_dissect.h>
68 #include <epan/dissectors/packet-data.h>
69 #include <epan/dissectors/packet-ber.h>
70 #include <epan/timestamp.h>
71 #include <epan/dfilter/dfilter-macro.h>
72 #include <wsutil/file_util.h>
73 #include <epan/column-utils.h>
74 #include <epan/strutil.h>
77 gboolean auto_scroll_live;
80 static nstime_t first_ts;
81 static nstime_t prev_dis_ts;
82 static guint32 cum_bytes = 0;
84 static void cf_reset_state(capture_file *cf);
86 static int read_packet(capture_file *cf, dfilter_t *dfcode,
87 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset);
89 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
90 gboolean refilter, gboolean redissect);
92 static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata,
94 static void match_subtree_text(proto_node *node, gpointer data);
95 static gboolean match_summary_line(capture_file *cf, frame_data *fdata,
97 static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
99 static gboolean match_ascii(capture_file *cf, frame_data *fdata,
101 static gboolean match_unicode(capture_file *cf, frame_data *fdata,
103 static gboolean match_binary(capture_file *cf, frame_data *fdata,
105 static gboolean match_dfilter(capture_file *cf, frame_data *fdata,
107 static gboolean find_packet(capture_file *cf,
108 gboolean (*match_function)(capture_file *, frame_data *, void *),
111 static void cf_open_failure_alert_box(const char *filename, int err,
112 gchar *err_info, gboolean for_writing,
114 static const char *file_rename_error_message(int err);
115 static void cf_write_failure_alert_box(const char *filename, int err);
116 static void cf_close_failure_alert_box(const char *filename, int err);
118 /* Update the progress bar this many times when reading a file. */
119 #define N_PROGBAR_UPDATES 100
121 /* Number of "frame_data" structures per memory chunk.
122 XXX - is this the right number? */
123 #define FRAME_DATA_CHUNK_SIZE 1024
126 /* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
128 cf_callback_t cb_fct;
130 } cf_callback_data_t;
132 static GList *cf_callbacks = NULL;
135 cf_callback_invoke(int event, gpointer data)
137 cf_callback_data_t *cb;
138 GList *cb_item = cf_callbacks;
140 /* there should be at least one interested */
141 g_assert(cb_item != NULL);
143 while(cb_item != NULL) {
145 cb->cb_fct(event, data, cb->user_data);
146 cb_item = g_list_next(cb_item);
152 cf_callback_add(cf_callback_t func, gpointer user_data)
154 cf_callback_data_t *cb;
156 cb = g_malloc(sizeof(cf_callback_data_t));
158 cb->user_data = user_data;
160 cf_callbacks = g_list_append(cf_callbacks, cb);
164 cf_callback_remove(cf_callback_t func)
166 cf_callback_data_t *cb;
167 GList *cb_item = cf_callbacks;
169 while(cb_item != NULL) {
171 if(cb->cb_fct == func) {
172 cf_callbacks = g_list_remove(cf_callbacks, cb);
176 cb_item = g_list_next(cb_item);
179 g_assert_not_reached();
183 cf_timestamp_auto_precision(capture_file *cf)
185 int prec = timestamp_get_precision();
188 /* don't try to get the file's precision if none is opened */
189 if(cf->state == FILE_CLOSED) {
193 /* if we are in auto mode, set precision of current file */
194 if(prec == TS_PREC_AUTO ||
195 prec == TS_PREC_AUTO_SEC ||
196 prec == TS_PREC_AUTO_DSEC ||
197 prec == TS_PREC_AUTO_CSEC ||
198 prec == TS_PREC_AUTO_MSEC ||
199 prec == TS_PREC_AUTO_USEC ||
200 prec == TS_PREC_AUTO_NSEC)
202 switch(wtap_file_tsprecision(cf->wth)) {
203 case(WTAP_FILE_TSPREC_SEC):
204 timestamp_set_precision(TS_PREC_AUTO_SEC);
206 case(WTAP_FILE_TSPREC_DSEC):
207 timestamp_set_precision(TS_PREC_AUTO_DSEC);
209 case(WTAP_FILE_TSPREC_CSEC):
210 timestamp_set_precision(TS_PREC_AUTO_CSEC);
212 case(WTAP_FILE_TSPREC_MSEC):
213 timestamp_set_precision(TS_PREC_AUTO_MSEC);
215 case(WTAP_FILE_TSPREC_USEC):
216 timestamp_set_precision(TS_PREC_AUTO_USEC);
218 case(WTAP_FILE_TSPREC_NSEC):
219 timestamp_set_precision(TS_PREC_AUTO_NSEC);
222 g_assert_not_reached();
229 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
234 wth = wtap_open_offline(fname, err, &err_info, TRUE);
238 /* The open succeeded. Close whatever capture file we had open,
239 and fill in the information for this file. */
242 /* Initialize all data structures used for dissection. */
245 /* We're about to start reading the file. */
246 cf->state = FILE_READ_IN_PROGRESS;
251 /* Set the file name because we need it to set the follow stream filter.
252 XXX - is that still true? We need it for other reasons, though,
254 cf->filename = g_strdup(fname);
256 /* Indicate whether it's a permanent or temporary file. */
257 cf->is_tempfile = is_tempfile;
259 /* If it's a temporary capture buffer file, mark it as not saved. */
260 cf->user_saved = !is_tempfile;
262 cf->cd_t = wtap_file_type(cf->wth);
264 cf->displayed_count = 0;
265 cf->marked_count = 0;
266 cf->drops_known = FALSE;
268 cf->snap = wtap_snapshot_length(cf->wth);
270 /* Snapshot length not known. */
271 cf->has_snap = FALSE;
272 cf->snap = WTAP_MAX_PACKET_SIZE;
275 nstime_set_zero(&cf->elapsed_time);
276 nstime_set_unset(&first_ts);
277 nstime_set_unset(&prev_dis_ts);
279 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
281 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
283 g_assert(cf->plist_chunk);
285 /* change the time formats now, as we might have a new precision */
286 cf_change_time_formats(cf);
288 fileset_file_opened(fname);
290 if(cf->cd_t == WTAP_FILE_BER) {
291 /* tell the BER dissector the file name */
292 ber_set_filename(cf->filename);
298 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
304 * Reset the state for the currently closed file, but don't do the
305 * UI callbacks; this is for use in "cf_open()", where we don't
306 * want the UI to go from "file open" to "file closed" back to
307 * "file open", we want it to go from "old file open" to "new file
308 * open and being read".
311 cf_reset_state(capture_file *cf)
313 /* Die if we're in the middle of reading a file. */
314 g_assert(cf->state != FILE_READ_IN_PROGRESS);
320 /* We have no file open... */
321 if (cf->filename != NULL) {
322 /* If it's a temporary file, remove it. */
324 ws_unlink(cf->filename);
325 g_free(cf->filename);
328 /* ...which means we have nothing to save. */
329 cf->user_saved = FALSE;
331 if (cf->plist_chunk != NULL) {
332 frame_data *fdata = cf->plist;
334 g_strfreev(fdata->col_expr.col_expr);
335 g_strfreev(fdata->col_expr.col_expr_val);
338 g_mem_chunk_destroy(cf->plist_chunk);
339 cf->plist_chunk = NULL;
341 if (cf->rfcode != NULL) {
342 dfilter_free(cf->rfcode);
346 cf->plist_end = NULL;
347 cf_unselect_packet(cf); /* nothing to select */
348 cf->first_displayed = NULL;
349 cf->last_displayed = NULL;
351 /* No frame selected, no field in that frame selected. */
352 cf->current_frame = NULL;
354 cf->finfo_selected = NULL;
356 /* Clear the packet list. */
357 packet_list_freeze();
363 nstime_set_zero(&cf->elapsed_time);
365 reset_tap_listeners();
367 /* We have no file open. */
368 cf->state = FILE_CLOSED;
370 fileset_file_closed();
373 /* Reset everything to a pristine state */
375 cf_close(capture_file *cf)
377 /* do GUI things even if file is already closed,
378 * e.g. to cleanup things if a capture couldn't be started */
379 cf_callback_invoke(cf_cb_file_closing, cf);
381 /* close things, if not already closed before */
382 if(cf->state != FILE_CLOSED) {
384 color_filters_cleanup();
388 cleanup_dissection();
391 cf_callback_invoke(cf_cb_file_closed, cf);
394 /* an out of memory exception occured, wait for a user button press to exit */
395 void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
401 cf_read(capture_file *cf)
405 const gchar *name_ptr;
407 char errmsg_errno[1024+1];
409 progdlg_t *volatile progbar = NULL;
411 volatile gint64 size;
413 volatile float progbar_val;
415 gchar status_str[100];
416 volatile gint64 progbar_nextstep;
417 volatile gint64 progbar_quantum;
419 gboolean filtering_tap_listeners;
422 volatile int displayed_once = 0;
425 /* Compile the current display filter.
426 * We assume this will not fail since cf->dfilter is only set in
427 * cf_filter IFF the filter was valid.
431 dfilter_compile(cf->dfilter, &dfcode);
434 /* Do we have any tap listeners with filters? */
435 filtering_tap_listeners = have_filtering_tap_listeners();
437 /* Get the union of the flags for all tap listeners. */
438 tap_flags = union_of_tap_listener_flags();
442 reset_tap_listeners();
444 cf_callback_invoke(cf_cb_file_read_start, cf);
446 name_ptr = get_basename(cf->filename);
448 /* Find the size of the file. */
449 size = wtap_file_size(cf->wth, NULL);
451 /* Update the progress bar when it gets to this value. */
452 progbar_nextstep = 0;
453 /* When we reach the value that triggers a progress bar update,
454 bump that value by this amount. */
456 progbar_quantum = size/N_PROGBAR_UPDATES;
459 /* Progress so far. */
462 packet_list_freeze();
465 g_get_current_time(&start_time);
467 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
469 /* Create the progress bar if necessary.
470 We check on every iteration of the loop, so that it takes no
471 longer than the standard time to create it (otherwise, for a
472 large file, we might take considerably longer than that standard
473 time in order to get to the next progress bar step). */
474 if (progbar == NULL) {
475 progbar = delayed_create_progress_dlg("Loading", name_ptr,
476 TRUE, &stop_flag, &start_time, progbar_val);
479 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
480 when we update it, we have to run the GTK+ main loop to get it
481 to repaint what's pending, and doing so may involve an "ioctl()"
482 to see if there's any pending input from an X server, and doing
483 that for every packet can be costly, especially on a big file. */
484 if (data_offset >= progbar_nextstep) {
485 file_pos = wtap_read_so_far(cf->wth, NULL);
486 progbar_val = (gfloat) file_pos / (gfloat) size;
487 if (progbar_val > 1.0) {
488 /* The file probably grew while we were reading it.
489 Update file size, and try again. */
490 size = wtap_file_size(cf->wth, NULL);
492 progbar_val = (gfloat) file_pos / (gfloat) size;
493 /* If it's still > 1, either "wtap_file_size()" failed (in which
494 case there's not much we can do about it), or the file
495 *shrank* (in which case there's not much we can do about
496 it); just clip the progress value at 1.0. */
497 if (progbar_val > 1.0f)
500 if (progbar != NULL) {
501 /* update the packet lists content on the first run or frequently on very large files */
502 /* (on smaller files the display update takes longer than reading the file) */
504 if (progbar_quantum > 500000 || displayed_once == 0) {
505 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
508 if (auto_scroll_live)
509 packet_list_moveto_end();
510 packet_list_freeze();
515 g_snprintf(status_str, sizeof(status_str),
516 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
517 file_pos / 1024, size / 1024);
518 update_progress_dlg(progbar, progbar_val, status_str);
520 progbar_nextstep += progbar_quantum;
525 /* Well, the user decided to abort the read. He/She will be warned and
526 it might be enough for him/her to work with the already loaded
528 This is especially true for very large capture files, where you don't
529 want to wait loading the whole file (which may last minutes or even
530 hours even on fast machines) just to see that it was the wrong file. */
534 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
536 CATCH(OutOfMemoryError) {
539 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
540 "%sOut Of Memory!%s\n"
542 "Sorry, but Wireshark has to terminate now!\n"
544 "Some infos / workarounds can be found at:\n"
545 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
546 simple_dialog_primary_start(), simple_dialog_primary_end());
547 /* we have to terminate, as we cannot recover from the memory error */
548 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
550 main_window_update();
551 /* XXX - how to avoid a busy wait? */
559 /* Cleanup and release all dfilter resources */
561 dfilter_free(dfcode);
564 /* We're done reading the file; destroy the progress bar if it was created. */
566 destroy_progress_dlg(progbar);
568 /* We're done reading sequentially through the file. */
569 cf->state = FILE_READ_DONE;
571 /* Close the sequential I/O side, to free up memory it requires. */
572 wtap_sequential_close(cf->wth);
574 /* Allow the protocol dissectors to free up memory that they
575 * don't need after the sequential run-through of the packets. */
576 postseq_cleanup_all_protocols();
578 /* Set the file encapsulation type now; we don't know what it is until
579 we've looked at all the packets, as we don't know until then whether
580 there's more than one type (and thus whether it's
581 WTAP_ENCAP_PER_PACKET). */
582 cf->lnk_t = wtap_file_encap(cf->wth);
584 cf->current_frame = cf->first_displayed;
589 cf_callback_invoke(cf_cb_file_read_finished, cf);
591 /* If we have any displayed packets to select, select the first of those
592 packets by making the first row the selected row. */
593 if (cf->first_displayed != NULL)
594 packet_list_select_row(0);
597 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
598 "%sFile loading was cancelled!%s\n"
600 "The remaining packets in the file were discarded.\n"
602 "As a lot of packets from the original file will be missing,\n"
603 "remember to be careful when saving the current content to a file.\n",
604 simple_dialog_primary_start(), simple_dialog_primary_end());
605 return CF_READ_ERROR;
609 /* Put up a message box noting that the read failed somewhere along
610 the line. Don't throw out the stuff we managed to read, though,
614 case WTAP_ERR_UNSUPPORTED_ENCAP:
615 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
616 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
619 errmsg = errmsg_errno;
622 case WTAP_ERR_CANT_READ:
623 errmsg = "An attempt to read from the capture file failed for"
624 " some unknown reason.";
627 case WTAP_ERR_SHORT_READ:
628 errmsg = "The capture file appears to have been cut short"
629 " in the middle of a packet.";
632 case WTAP_ERR_BAD_RECORD:
633 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
634 "The capture file appears to be damaged or corrupt.\n(%s)",
637 errmsg = errmsg_errno;
641 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
642 "An error occurred while reading the"
643 " capture file: %s.", wtap_strerror(err));
644 errmsg = errmsg_errno;
647 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
648 return CF_READ_ERROR;
655 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
657 cf_status_t cf_status;
659 cf_status = cf_open(cf, fname, is_tempfile, err);
664 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
666 gint64 data_offset = 0;
668 volatile int newly_displayed_packets = 0;
670 gboolean filtering_tap_listeners;
673 /* Compile the current display filter.
674 * We assume this will not fail since cf->dfilter is only set in
675 * cf_filter IFF the filter was valid.
679 dfilter_compile(cf->dfilter, &dfcode);
682 /* Do we have any tap listeners with filters? */
683 filtering_tap_listeners = have_filtering_tap_listeners();
685 /* Get the union of the flags for all tap listeners. */
686 tap_flags = union_of_tap_listener_flags();
690 packet_list_check_end();
691 packet_list_freeze();
693 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
695 while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
696 if (cf->state == FILE_READ_ABORTED) {
697 /* Well, the user decided to exit Wireshark. Break out of the
698 loop, and let the code below (which is called even if there
699 aren't any packets left to read) exit. */
703 if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
704 data_offset) != -1) {
705 newly_displayed_packets++;
708 CATCH(OutOfMemoryError) {
711 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
712 "%sOut Of Memory!%s\n"
714 "Sorry, but Wireshark has to terminate now!\n"
716 "The capture file is not lost, it can be found at:\n"
719 "Some infos / workarounds can be found at:\n"
720 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
721 simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
722 /* we have to terminate, as we cannot recover from the memory error */
723 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
725 main_window_update();
726 /* XXX - how to avoid a busy wait? */
730 return CF_READ_ABORTED;
736 /* Cleanup and release all dfilter resources */
738 dfilter_free(dfcode);
741 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
742 cf->count, cf->state, *err);*/
744 /* XXX - this causes "flickering" of the list */
747 /* moving to the end of the packet list - if the user requested so and
748 we have some new packets.
749 this doesn't seem to work well with a frozen GTK_Clist, so do this after
750 packet_list_thaw() is done, see bugzilla 1188 */
751 /* XXX - this cheats and looks inside the packet list to find the final
753 if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL)
754 packet_list_moveto_end();
756 if (cf->state == FILE_READ_ABORTED) {
757 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
758 so that our caller can kill off the capture child process;
759 this will cause an EOF on the pipe from the child, so
760 "cf_finish_tail()" will be called, and it will clean up
762 return CF_READ_ABORTED;
763 } else if (*err != 0) {
764 /* We got an error reading the capture file.
765 XXX - pop up a dialog box instead? */
766 g_warning("Error \"%s\" while reading: \"%s\"\n",
767 wtap_strerror(*err), cf->filename);
769 return CF_READ_ERROR;
775 cf_finish_tail(capture_file *cf, int *err)
780 gboolean filtering_tap_listeners;
783 /* Compile the current display filter.
784 * We assume this will not fail since cf->dfilter is only set in
785 * cf_filter IFF the filter was valid.
789 dfilter_compile(cf->dfilter, &dfcode);
792 /* Do we have any tap listeners with filters? */
793 filtering_tap_listeners = have_filtering_tap_listeners();
795 /* Get the union of the flags for all tap listeners. */
796 tap_flags = union_of_tap_listener_flags();
798 if(cf->wth == NULL) {
800 return CF_READ_ERROR;
803 packet_list_check_end();
804 packet_list_freeze();
806 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
807 if (cf->state == FILE_READ_ABORTED) {
808 /* Well, the user decided to abort the read. Break out of the
809 loop, and let the code below (which is called even if there
810 aren't any packets left to read) exit. */
813 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
816 /* Cleanup and release all dfilter resources */
818 dfilter_free(dfcode);
823 if (cf->state == FILE_READ_ABORTED) {
824 /* Well, the user decided to abort the read. We're only called
825 when the child capture process closes the pipe to us (meaning
826 it's probably exited), so we can just close the capture
827 file; we return CF_READ_ABORTED so our caller can do whatever
828 is appropriate when that happens. */
830 return CF_READ_ABORTED;
833 if (auto_scroll_live && cf->plist_end != NULL)
834 /* XXX - this cheats and looks inside the packet list to find the final
836 packet_list_moveto_end();
838 /* We're done reading sequentially through the file. */
839 cf->state = FILE_READ_DONE;
841 /* We're done reading sequentially through the file; close the
842 sequential I/O side, to free up memory it requires. */
843 wtap_sequential_close(cf->wth);
845 /* Allow the protocol dissectors to free up memory that they
846 * don't need after the sequential run-through of the packets. */
847 postseq_cleanup_all_protocols();
849 /* Set the file encapsulation type now; we don't know what it is until
850 we've looked at all the packets, as we don't know until then whether
851 there's more than one type (and thus whether it's
852 WTAP_ENCAP_PER_PACKET). */
853 cf->lnk_t = wtap_file_encap(cf->wth);
856 /* We got an error reading the capture file.
857 XXX - pop up a dialog box? */
858 return CF_READ_ERROR;
863 #endif /* HAVE_LIBPCAP */
866 cf_get_display_name(capture_file *cf)
868 const gchar *displayname;
870 /* Return a name to use in displays */
871 if (!cf->is_tempfile) {
872 /* Get the last component of the file name, and use that. */
874 displayname = get_basename(cf->filename);
876 displayname="(No file)";
879 /* The file we read is a temporary file from a live capture;
880 we don't mention its name. */
881 displayname = "(Untitled)";
886 /* XXX - use a macro instead? */
888 cf_get_packet_count(capture_file *cf)
893 /* XXX - use a macro instead? */
895 cf_set_packet_count(capture_file *cf, int packet_count)
897 cf->count = packet_count;
900 /* XXX - use a macro instead? */
902 cf_is_tempfile(capture_file *cf)
904 return cf->is_tempfile;
907 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
909 cf->is_tempfile = is_tempfile;
913 /* XXX - use a macro instead? */
914 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
916 cf->drops_known = drops_known;
919 /* XXX - use a macro instead? */
920 void cf_set_drops(capture_file *cf, guint32 drops)
925 /* XXX - use a macro instead? */
926 gboolean cf_get_drops_known(capture_file *cf)
928 return cf->drops_known;
931 /* XXX - use a macro instead? */
932 guint32 cf_get_drops(capture_file *cf)
937 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
943 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
944 dfilter_t *dfcode, gboolean filtering_tap_listeners,
946 union wtap_pseudo_header *pseudo_header, const guchar *buf,
950 gboolean create_proto_tree = FALSE;
953 /* just add some value here until we know if it is being displayed or not */
954 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
956 /* If we don't have the time stamp of the first packet in the
957 capture, it's because this is the first packet. Save the time
958 stamp of this packet as the time stamp of the first packet. */
959 if (nstime_is_unset(&first_ts)) {
960 first_ts = fdata->abs_ts;
962 /* if this frames is marked as a reference time frame, reset
963 firstsec and firstusec to this frame */
964 if(fdata->flags.ref_time){
965 first_ts = fdata->abs_ts;
968 /* If we don't have the time stamp of the previous displayed packet,
969 it's because this is the first displayed packet. Save the time
970 stamp of this packet as the time stamp of the previous displayed
972 if (nstime_is_unset(&prev_dis_ts)) {
973 prev_dis_ts = fdata->abs_ts;
976 /* Get the time elapsed between the first packet and this packet. */
977 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
979 /* If it's greater than the current elapsed time, set the elapsed time
980 to it (we check for "greater than" so as not to be confused by
981 time moving backwards). */
982 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
983 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
984 cf->elapsed_time = fdata->rel_ts;
987 /* Get the time elapsed between the previous displayed packet and
989 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
993 we have a display filter and are re-applying it;
995 we have a list of color filters;
997 we have tap listeners with filters;
999 we have tap listeners that require a protocol tree;
1001 we have custom columns;
1003 allocate a protocol tree root node, so that we'll construct
1004 a protocol tree against which a filter expression can be
1006 if ((dfcode != NULL && refilter) || color_filters_used() ||
1007 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1008 have_custom_cols(&cf->cinfo))
1009 create_proto_tree = TRUE;
1011 /* Dissect the frame. */
1012 edt = epan_dissect_new(create_proto_tree, FALSE);
1014 if (dfcode != NULL && refilter) {
1015 epan_dissect_prime_dfilter(edt, dfcode);
1017 /* prepare color filters */
1018 if (color_filters_used()) {
1019 color_filters_prime_edt(edt);
1022 col_custom_prime_edt(edt, &cf->cinfo);
1024 tap_queue_init(edt);
1025 epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
1026 tap_push_tapped_queue(edt);
1028 /* If we have a display filter, apply it if we're refiltering, otherwise
1029 leave the "passed_dfilter" flag alone.
1031 If we don't have a display filter, set "passed_dfilter" to 1. */
1032 if (dfcode != NULL) {
1034 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1037 fdata->flags.passed_dfilter = 1;
1039 if( (fdata->flags.passed_dfilter)
1040 || (edt->pi.fd->flags.ref_time) ){
1041 /* This frame either passed the display filter list or is marked as
1042 a time reference frame. All time reference frames are displayed
1043 even if they dont pass the display filter */
1044 if(edt->pi.fd->flags.ref_time){
1045 /* if this was a TIME REF frame we should reset the cul bytes field */
1046 cum_bytes = fdata->pkt_len;
1047 fdata->cum_bytes = cum_bytes;
1049 /* increase cum_bytes with this packets length */
1050 cum_bytes += fdata->pkt_len;
1053 epan_dissect_fill_in_columns(edt);
1055 /* If we haven't yet seen the first frame, this is it.
1057 XXX - we must do this before we add the row to the display,
1058 as, if the display's GtkCList's selection mode is
1059 GTK_SELECTION_BROWSE, when the first entry is added to it,
1060 "cf_select_packet()" will be called, and it will fetch the row
1061 data for the 0th row, and will get a null pointer rather than
1062 "fdata", as "gtk_clist_append()" won't yet have returned and
1063 thus "gtk_clist_set_row_data()" won't yet have been called.
1065 We thus need to leave behind bread crumbs so that
1066 "cf_select_packet()" can find this frame. See the comment
1067 in "cf_select_packet()". */
1068 if (cf->first_displayed == NULL)
1069 cf->first_displayed = fdata;
1071 /* This is the last frame we've seen so far. */
1072 cf->last_displayed = fdata;
1074 /* XXX - GLIB1 implementation provided to support backport of this feature. */
1075 #if (GLIB_MAJOR_VERSION >= 2)
1076 fdata->col_expr.col_expr = g_strdupv(cf->cinfo.col_expr.col_expr);
1077 fdata->col_expr.col_expr_val = g_strdupv(cf->cinfo.col_expr.col_expr_val);
1082 fdata->col_expr.col_expr = (gchar **) g_malloc(sizeof(gchar *) * (cf->cinfo.num_cols + 1));
1083 fdata->col_expr.col_expr_val = (gchar **) g_malloc(sizeof(gchar *) * (cf->cinfo.num_cols + 1));
1085 for (i=0; i <= cf->cinfo.num_cols; i++)
1087 fdata->col_expr.col_expr[i] = g_strdup(cf->cinfo.col_expr.col_expr[i]);
1088 fdata->col_expr.col_expr_val[i] = g_strdup(cf->cinfo.col_expr.col_expr_val[i]);
1092 row = packet_list_append(cf->cinfo.col_data, fdata);
1094 /* colorize packet: first apply color filters
1095 * then if packet is marked, use preferences to overwrite color
1096 * we do both to make sure that when a packet gets un-marked, the
1097 * color will be correctly set (fixes bug 2038)
1099 fdata->color_filter = color_filters_colorize_packet(row, edt);
1100 if (fdata->flags.marked) {
1101 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
1104 /* Set the time of the previous displayed frame to the time of this
1106 prev_dis_ts = fdata->abs_ts;
1108 cf->displayed_count++;
1110 /* This frame didn't pass the display filter, so it's not being added
1111 to the clist, and thus has no row. */
1114 epan_dissect_free(edt);
1118 /* read in a new packet */
1119 /* returns the row of the new packet in the packet list or -1 if not displayed */
1121 read_packet(capture_file *cf, dfilter_t *dfcode,
1122 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1124 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1125 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1126 const guchar *buf = wtap_buf_ptr(cf->wth);
1129 frame_data *plist_end;
1130 epan_dissect_t *edt;
1133 /* Allocate the next list entry, and add it to the list. */
1134 fdata = g_mem_chunk_alloc(cf->plist_chunk);
1140 fdata->pkt_len = phdr->len;
1141 fdata->cap_len = phdr->caplen;
1142 fdata->file_off = offset;
1143 fdata->lnk_t = phdr->pkt_encap;
1144 fdata->flags.encoding = CHAR_ASCII;
1145 fdata->flags.visited = 0;
1146 fdata->flags.marked = 0;
1147 fdata->flags.ref_time = 0;
1148 fdata->color_filter = NULL;
1149 fdata->col_expr.col_expr = NULL;
1150 fdata->col_expr.col_expr_val = NULL;
1152 fdata->abs_ts.secs = phdr->ts.secs;
1153 fdata->abs_ts.nsecs = phdr->ts.nsecs;
1155 if (cf->plist_end != NULL)
1156 nstime_delta(&fdata->del_cap_ts, &fdata->abs_ts, &cf->plist_end->abs_ts);
1158 nstime_set_zero(&fdata->del_cap_ts);
1162 edt = epan_dissect_new(TRUE, FALSE);
1163 epan_dissect_prime_dfilter(edt, cf->rfcode);
1164 epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
1165 passed = dfilter_apply_edt(cf->rfcode, edt);
1166 epan_dissect_free(edt);
1169 plist_end = cf->plist_end;
1170 fdata->prev = plist_end;
1171 if (plist_end != NULL)
1172 plist_end->next = fdata;
1175 cf->plist_end = fdata;
1178 cf->f_datalen = offset + phdr->caplen;
1179 fdata->num = cf->count;
1180 if (!cf->redissecting) {
1181 row = add_packet_to_packet_list(fdata, cf, dfcode,
1182 filtering_tap_listeners, tap_flags,
1183 pseudo_header, buf, TRUE);
1186 /* XXX - if we didn't have read filters, or if we could avoid
1187 allocating the "frame_data" structure until we knew whether
1188 the frame passed the read filter, we could use a G_ALLOC_ONLY
1191 ...but, at least in one test I did, where I just made the chunk
1192 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
1193 seem to save a noticeable amount of time or space. */
1194 g_strfreev(fdata->col_expr.col_expr);
1195 g_strfreev(fdata->col_expr.col_expr_val);
1196 g_mem_chunk_free(cf->plist_chunk, fdata);
1203 cf_merge_files(char **out_filenamep, int in_file_count,
1204 char *const *in_filenames, int file_type, gboolean do_append)
1206 merge_in_file_t *in_files;
1209 char tmpname[128+1];
1212 int open_err, read_err, write_err, close_err;
1216 char errmsg_errno[1024+1];
1218 gboolean got_read_error = FALSE, got_write_error = FALSE;
1220 progdlg_t *progbar = NULL;
1222 gint64 f_len, file_pos;
1224 GTimeVal start_time;
1225 gchar status_str[100];
1226 gint64 progbar_nextstep;
1227 gint64 progbar_quantum;
1229 /* open the input files */
1230 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1231 &open_err, &err_info, &err_fileno)) {
1233 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1238 if (*out_filenamep != NULL) {
1239 out_filename = *out_filenamep;
1240 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1244 out_fd = create_tempfile(tmpname, sizeof tmpname, "wireshark");
1247 out_filename = g_strdup(tmpname);
1248 *out_filenamep = out_filename;
1252 merge_close_in_files(in_file_count, in_files);
1254 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1258 pdh = wtap_dump_fdopen(out_fd, file_type,
1259 merge_select_frame_type(in_file_count, in_files),
1260 merge_max_snapshot_length(in_file_count, in_files),
1261 FALSE /* compressed */, &open_err);
1264 merge_close_in_files(in_file_count, in_files);
1266 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1271 /* Get the sum of the sizes of all the files. */
1273 for (i = 0; i < in_file_count; i++)
1274 f_len += in_files[i].size;
1276 /* Update the progress bar when it gets to this value. */
1277 progbar_nextstep = 0;
1278 /* When we reach the value that triggers a progress bar update,
1279 bump that value by this amount. */
1280 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1281 /* Progress so far. */
1285 g_get_current_time(&start_time);
1287 /* do the merge (or append) */
1290 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1293 wth = merge_read_packet(in_file_count, in_files, &read_err,
1297 got_read_error = TRUE;
1301 /* Get the sum of the data offsets in all of the files. */
1303 for (i = 0; i < in_file_count; i++)
1304 data_offset += in_files[i].data_offset;
1306 /* Create the progress bar if necessary.
1307 We check on every iteration of the loop, so that it takes no
1308 longer than the standard time to create it (otherwise, for a
1309 large file, we might take considerably longer than that standard
1310 time in order to get to the next progress bar step). */
1311 if (progbar == NULL) {
1312 progbar = delayed_create_progress_dlg("Merging", "files",
1313 FALSE, &stop_flag, &start_time, progbar_val);
1316 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1317 when we update it, we have to run the GTK+ main loop to get it
1318 to repaint what's pending, and doing so may involve an "ioctl()"
1319 to see if there's any pending input from an X server, and doing
1320 that for every packet can be costly, especially on a big file. */
1321 if (data_offset >= progbar_nextstep) {
1322 /* Get the sum of the seek positions in all of the files. */
1324 for (i = 0; i < in_file_count; i++)
1325 file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1326 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1327 if (progbar_val > 1.0f) {
1328 /* Some file probably grew while we were reading it.
1329 That "shouldn't happen", so we'll just clip the progress
1333 if (progbar != NULL) {
1334 g_snprintf(status_str, sizeof(status_str),
1335 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1336 file_pos / 1024, f_len / 1024);
1337 update_progress_dlg(progbar, progbar_val, status_str);
1339 progbar_nextstep += progbar_quantum;
1343 /* Well, the user decided to abort the merge. */
1347 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1348 wtap_buf_ptr(wth), &write_err)) {
1349 got_write_error = TRUE;
1354 /* We're done merging the files; destroy the progress bar if it was created. */
1355 if (progbar != NULL)
1356 destroy_progress_dlg(progbar);
1358 merge_close_in_files(in_file_count, in_files);
1359 if (!got_read_error && !got_write_error) {
1360 if (!wtap_dump_close(pdh, &write_err))
1361 got_write_error = TRUE;
1363 wtap_dump_close(pdh, &close_err);
1365 if (got_read_error) {
1367 * Find the file on which we got the error, and report the error.
1369 for (i = 0; i < in_file_count; i++) {
1370 if (in_files[i].state == GOT_ERROR) {
1371 /* Put up a message box noting that a read failed somewhere along
1375 case WTAP_ERR_UNSUPPORTED_ENCAP:
1376 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1377 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1380 errmsg = errmsg_errno;
1383 case WTAP_ERR_CANT_READ:
1384 errmsg = "An attempt to read from the capture file %s failed for"
1385 " some unknown reason.";
1388 case WTAP_ERR_SHORT_READ:
1389 errmsg = "The capture file %s appears to have been cut short"
1390 " in the middle of a packet.";
1393 case WTAP_ERR_BAD_RECORD:
1394 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1395 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1398 errmsg = errmsg_errno;
1402 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1403 "An error occurred while reading the"
1404 " capture file %%s: %s.", wtap_strerror(read_err));
1405 errmsg = errmsg_errno;
1408 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
1413 if (got_write_error) {
1414 /* Put up an alert box for the write error. */
1415 cf_write_failure_alert_box(out_filename, write_err);
1418 if (got_read_error || got_write_error || stop_flag) {
1419 /* Callers aren't expected to treat an error or an explicit abort
1420 differently - we put up error dialogs ourselves, so they don't
1428 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1430 const char *filter_new = dftext ? dftext : "";
1431 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1434 /* if new filter equals old one, do nothing unless told to do so */
1435 if (!force && strcmp(filter_new, filter_old) == 0) {
1441 if (dftext == NULL) {
1442 /* The new filter is an empty filter (i.e., display all packets).
1443 * so leave dfcode==NULL
1447 * We have a filter; make a copy of it (as we'll be saving it),
1448 * and try to compile it.
1450 dftext = g_strdup(dftext);
1451 if (!dfilter_compile(dftext, &dfcode)) {
1452 /* The attempt failed; report an error. */
1453 gchar *safe_dftext = simple_dialog_format_message(dftext);
1454 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1456 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1459 "The following display filter isn't a valid display filter:\n%s\n"
1460 "See the help for a description of the display filter syntax.",
1461 simple_dialog_primary_start(), safe_dfilter_error_msg,
1462 simple_dialog_primary_end(), safe_dftext);
1463 g_free(safe_dfilter_error_msg);
1464 g_free(safe_dftext);
1470 if (dfcode == NULL) {
1471 /* Yes - free the filter text, and set it to null. */
1477 /* We have a valid filter. Replace the current filter. */
1478 g_free(cf->dfilter);
1479 cf->dfilter = dftext;
1481 /* Now rescan the packet list, applying the new filter, but not
1482 throwing away information constructed on a previous pass. */
1483 if (dftext == NULL) {
1484 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1486 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1489 /* Cleanup and release all dfilter resources */
1490 if (dfcode != NULL){
1491 dfilter_free(dfcode);
1497 cf_colorize_packets(capture_file *cf)
1499 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1503 cf_reftime_packets(capture_file *cf)
1505 rescan_packets(cf, "Updating Reftime", "all packets", FALSE, FALSE);
1509 cf_redissect_packets(capture_file *cf)
1511 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1514 /* Rescan the list of packets, reconstructing the CList.
1516 "action" describes why we're doing this; it's used in the progress
1519 "action_item" describes what we're doing; it's used in the progress
1522 "refilter" is TRUE if we need to re-evaluate the filter expression.
1524 "redissect" is TRUE if we need to make the dissectors reconstruct
1525 any state information they have (because a preference that affects
1526 some dissector has changed, meaning some dissector might construct
1527 its state differently from the way it was constructed the last time). */
1529 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1530 gboolean refilter, gboolean redissect)
1533 progdlg_t *progbar = NULL;
1538 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1539 int selected_row, prev_row, preceding_row, following_row;
1540 gboolean selected_frame_seen;
1543 GTimeVal start_time;
1544 gchar status_str[100];
1545 int progbar_nextstep;
1546 int progbar_quantum;
1548 gboolean filtering_tap_listeners;
1551 /* Compile the current display filter.
1552 * We assume this will not fail since cf->dfilter is only set in
1553 * cf_filter IFF the filter was valid.
1557 dfilter_compile(cf->dfilter, &dfcode);
1560 /* Do we have any tap listeners with filters? */
1561 filtering_tap_listeners = have_filtering_tap_listeners();
1563 /* Get the union of the flags for all tap listeners. */
1564 tap_flags = union_of_tap_listener_flags();
1567 reset_tap_listeners();
1568 /* Which frame, if any, is the currently selected frame?
1569 XXX - should the selected frame or the focus frame be the "current"
1570 frame, that frame being the one from which "Find Frame" searches
1572 selected_frame = cf->current_frame;
1574 /* We don't yet know what row that frame will be on, if any, after we
1575 rebuild the clist, however. */
1579 /* We need to re-initialize all the state information that protocols
1580 keep, because some preference that controls a dissector has changed,
1581 which might cause the state information to be constructed differently
1582 by that dissector. */
1584 /* We might receive new packets while redissecting, and we don't
1585 want to dissect those before their time. */
1586 cf->redissecting = TRUE;
1588 /* Initialize all data structures used for dissection. */
1592 /* Freeze the packet list while we redo it, so we don't get any
1593 screen updates while it happens. */
1594 packet_list_freeze();
1597 packet_list_clear();
1599 /* We don't yet know which will be the first and last frames displayed. */
1600 cf->first_displayed = NULL;
1601 cf->last_displayed = NULL;
1603 /* We currently don't display any packets */
1604 cf->displayed_count = 0;
1606 /* Iterate through the list of frames. Call a routine for each frame
1607 to check whether it should be displayed and, if so, add it to
1608 the display list. */
1609 nstime_set_unset(&first_ts);
1610 nstime_set_unset(&prev_dis_ts);
1612 /* Update the progress bar when it gets to this value. */
1613 progbar_nextstep = 0;
1614 /* When we reach the value that triggers a progress bar update,
1615 bump that value by this amount. */
1616 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1617 /* Count of packets at which we've looked. */
1619 /* Progress so far. */
1623 g_get_current_time(&start_time);
1625 row = -1; /* no previous row yet */
1630 preceding_frame = NULL;
1632 following_frame = NULL;
1634 selected_frame_seen = FALSE;
1636 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1637 /* Create the progress bar if necessary.
1638 We check on every iteration of the loop, so that it takes no
1639 longer than the standard time to create it (otherwise, for a
1640 large file, we might take considerably longer than that standard
1641 time in order to get to the next progress bar step). */
1642 if (progbar == NULL)
1643 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1644 &stop_flag, &start_time,
1647 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1648 when we update it, we have to run the GTK+ main loop to get it
1649 to repaint what's pending, and doing so may involve an "ioctl()"
1650 to see if there's any pending input from an X server, and doing
1651 that for every packet can be costly, especially on a big file. */
1652 if (count >= progbar_nextstep) {
1653 /* let's not divide by zero. I should never be started
1654 * with count == 0, so let's assert that
1656 g_assert(cf->count > 0);
1657 progbar_val = (gfloat) count / cf->count;
1659 if (progbar != NULL) {
1660 g_snprintf(status_str, sizeof(status_str),
1661 "%4u of %u frames", count, cf->count);
1662 update_progress_dlg(progbar, progbar_val, status_str);
1665 progbar_nextstep += progbar_quantum;
1669 /* Well, the user decided to abort the filtering. Just stop.
1671 XXX - go back to the previous filter? Users probably just
1672 want not to wait for a filtering operation to finish;
1673 unless we cancel by having no filter, reverting to the
1674 previous filter will probably be even more expensive than
1675 continuing the filtering, as it involves going back to the
1676 beginning and filtering, and even with no filter we currently
1677 have to re-generate the entire clist, which is also expensive.
1679 I'm not sure what Network Monitor does, but it doesn't appear
1680 to give you an unfiltered display if you cancel. */
1687 /* Since all state for the frame was destroyed, mark the frame
1688 * as not visited, free the GSList referring to the state
1689 * data (the per-frame data itself was freed by
1690 * "init_dissection()"), and null out the GSList pointer. */
1691 fdata->flags.visited = 0;
1693 g_slist_free(fdata->pfd);
1698 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1699 cf->pd, fdata->cap_len, &err, &err_info)) {
1700 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1701 cf_read_error_message(err, err_info), cf->filename);
1705 /* If the previous frame is displayed, and we haven't yet seen the
1706 selected frame, remember that frame - it's the closest one we've
1707 yet seen before the selected frame. */
1708 if (prev_row != -1 && !selected_frame_seen) {
1709 preceding_row = prev_row;
1710 preceding_frame = prev_frame;
1712 row = add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1713 tap_flags, &cf->pseudo_header, cf->pd,
1716 /* If this frame is displayed, and this is the first frame we've
1717 seen displayed after the selected frame, remember this frame -
1718 it's the closest one we've yet seen at or after the selected
1720 if (row != -1 && selected_frame_seen && following_row == -1) {
1721 following_row = row;
1722 following_frame = fdata;
1724 if (fdata == selected_frame) {
1726 selected_frame_seen = TRUE;
1729 /* Remember this row/frame - it'll be the previous row/frame
1730 on the next pass through the loop. */
1735 /* We are done redissecting the packet list. */
1736 cf->redissecting = FALSE;
1738 /* Re-sort the list using the previously selected order */
1739 packet_list_set_sort_column();
1742 /* Clear out what remains of the visited flags and per-frame data
1745 XXX - that may cause various forms of bogosity when dissecting
1746 these frames, as they won't have been seen by this sequential
1747 pass, but the only alternative I see is to keep scanning them
1748 even though the user requested that the scan stop, and that
1749 would leave the user stuck with an Wireshark grinding on
1750 until it finishes. Should we just stick them with that? */
1751 for (; fdata != NULL; fdata = fdata->next) {
1752 fdata->flags.visited = 0;
1754 g_slist_free(fdata->pfd);
1760 /* We're done filtering the packets; destroy the progress bar if it
1762 if (progbar != NULL)
1763 destroy_progress_dlg(progbar);
1765 /* Unfreeze the packet list. */
1768 if (selected_row == -1) {
1769 /* The selected frame didn't pass the filter. */
1770 if (selected_frame == NULL) {
1771 /* That's because there *was* no selected frame. Make the first
1772 displayed frame the current frame. */
1775 /* Find the nearest displayed frame to the selected frame (whether
1776 it's before or after that frame) and make that the current frame.
1777 If the next and previous displayed frames are equidistant from the
1778 selected frame, choose the next one. */
1779 g_assert(following_frame == NULL ||
1780 following_frame->num >= selected_frame->num);
1781 g_assert(preceding_frame == NULL ||
1782 preceding_frame->num <= selected_frame->num);
1783 if (following_frame == NULL) {
1784 /* No frame after the selected frame passed the filter, so we
1785 have to select the last displayed frame before the selected
1787 selected_row = preceding_row;
1788 } else if (preceding_frame == NULL) {
1789 /* No frame before the selected frame passed the filter, so we
1790 have to select the first displayed frame after the selected
1792 selected_row = following_row;
1794 /* Frames before and after the selected frame passed the filter, so
1795 we'll select the previous frame */
1796 selected_row = preceding_row;
1801 if (selected_row == -1) {
1802 /* There are no frames displayed at all. */
1803 cf_unselect_packet(cf);
1805 /* Either the frame that was selected passed the filter, or we've
1806 found the nearest displayed frame to that frame. Select it, make
1807 it the focus row, and make it visible. */
1808 if (selected_row == 0) {
1809 /* Set to invalid to force update of packet list and packet details */
1810 cf->current_row = -1;
1812 packet_list_set_selected_row(selected_row);
1815 /* Cleanup and release all dfilter resources */
1816 if (dfcode != NULL){
1817 dfilter_free(dfcode);
1828 process_specified_packets(capture_file *cf, packet_range_t *range,
1829 const char *string1, const char *string2, gboolean terminate_is_stop,
1830 gboolean (*callback)(capture_file *, frame_data *,
1831 union wtap_pseudo_header *, const guint8 *, void *),
1832 void *callback_args)
1837 union wtap_pseudo_header pseudo_header;
1838 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1839 psp_return_t ret = PSP_FINISHED;
1841 progdlg_t *progbar = NULL;
1844 gboolean progbar_stop_flag;
1845 GTimeVal progbar_start_time;
1846 gchar progbar_status_str[100];
1847 int progbar_nextstep;
1848 int progbar_quantum;
1849 range_process_e process_this;
1851 /* Update the progress bar when it gets to this value. */
1852 progbar_nextstep = 0;
1853 /* When we reach the value that triggers a progress bar update,
1854 bump that value by this amount. */
1855 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1856 /* Count of packets at which we've looked. */
1858 /* Progress so far. */
1861 progbar_stop_flag = FALSE;
1862 g_get_current_time(&progbar_start_time);
1864 packet_range_process_init(range);
1866 /* Iterate through the list of packets, printing the packets that
1867 were selected by the current display filter. */
1868 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1869 /* Create the progress bar if necessary.
1870 We check on every iteration of the loop, so that it takes no
1871 longer than the standard time to create it (otherwise, for a
1872 large file, we might take considerably longer than that standard
1873 time in order to get to the next progress bar step). */
1874 if (progbar == NULL)
1875 progbar = delayed_create_progress_dlg(string1, string2,
1878 &progbar_start_time,
1881 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1882 when we update it, we have to run the GTK+ main loop to get it
1883 to repaint what's pending, and doing so may involve an "ioctl()"
1884 to see if there's any pending input from an X server, and doing
1885 that for every packet can be costly, especially on a big file. */
1886 if (progbar_count >= progbar_nextstep) {
1887 /* let's not divide by zero. I should never be started
1888 * with count == 0, so let's assert that
1890 g_assert(cf->count > 0);
1891 progbar_val = (gfloat) progbar_count / cf->count;
1893 if (progbar != NULL) {
1894 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1895 "%4u of %u packets", progbar_count, cf->count);
1896 update_progress_dlg(progbar, progbar_val, progbar_status_str);
1899 progbar_nextstep += progbar_quantum;
1902 if (progbar_stop_flag) {
1903 /* Well, the user decided to abort the operation. Just stop,
1904 and arrange to return PSP_STOPPED to our caller, so they know
1905 it was stopped explicitly. */
1912 /* do we have to process this packet? */
1913 process_this = packet_range_process_packet(range, fdata);
1914 if (process_this == range_process_next) {
1915 /* this packet uninteresting, continue with next one */
1917 } else if (process_this == range_processing_finished) {
1918 /* all interesting packets processed, stop the loop */
1922 /* Get the packet */
1923 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1924 pd, fdata->cap_len, &err, &err_info)) {
1925 /* Attempt to get the packet failed. */
1926 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1927 cf_read_error_message(err, err_info), cf->filename);
1931 /* Process the packet */
1932 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
1933 /* Callback failed. We assume it reported the error appropriately. */
1939 /* We're done printing the packets; destroy the progress bar if
1941 if (progbar != NULL)
1942 destroy_progress_dlg(progbar);
1948 gboolean construct_protocol_tree;
1950 } retap_callback_args_t;
1953 retap_packet(capture_file *cf _U_, frame_data *fdata,
1954 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1957 retap_callback_args_t *args = argsp;
1958 epan_dissect_t *edt;
1960 edt = epan_dissect_new(args->construct_protocol_tree, FALSE);
1961 tap_queue_init(edt);
1962 epan_dissect_run(edt, pseudo_header, pd, fdata, args->cinfo);
1963 tap_push_tapped_queue(edt);
1964 epan_dissect_free(edt);
1970 cf_retap_packets(capture_file *cf)
1972 packet_range_t range;
1973 retap_callback_args_t callback_args;
1974 gboolean filtering_tap_listeners;
1977 /* Do we have any tap listeners with filters? */
1978 filtering_tap_listeners = have_filtering_tap_listeners();
1980 tap_flags = union_of_tap_listener_flags();
1982 /* If any tap listeners have filters, or require the protocol tree,
1983 construct the protocol tree. */
1984 callback_args.construct_protocol_tree = filtering_tap_listeners ||
1985 (tap_flags & TL_REQUIRES_PROTO_TREE);
1987 /* If any tap listeners require the columns, construct them. */
1988 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1990 /* Reset the tap listeners. */
1991 reset_tap_listeners();
1993 /* Iterate through the list of packets, dissecting all packets and
1994 re-running the taps. */
1995 packet_range_init(&range);
1996 packet_range_process_init(&range);
1997 switch (process_specified_packets(cf, &range, "Recalculating statistics on",
1998 "all packets", TRUE, retap_packet,
2001 /* Completed successfully. */
2005 /* Well, the user decided to abort the refiltering.
2006 Return CF_READ_ABORTED so our caller knows they did that. */
2007 return CF_READ_ABORTED;
2010 /* Error while retapping. */
2011 return CF_READ_ERROR;
2014 g_assert_not_reached();
2019 print_args_t *print_args;
2020 gboolean print_header_line;
2021 char *header_line_buf;
2022 int header_line_buf_len;
2023 gboolean print_formfeed;
2024 gboolean print_separator;
2028 } print_callback_args_t;
2031 print_packet(capture_file *cf, frame_data *fdata,
2032 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2035 print_callback_args_t *args = argsp;
2036 epan_dissect_t *edt;
2042 gboolean proto_tree_needed;
2043 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2044 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2046 /* Create the protocol tree, and make it visible, if we're printing
2047 the dissection or the hex data.
2048 XXX - do we need it if we're just printing the hex data? */
2050 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2051 edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
2053 /* Fill in the column information if we're printing the summary
2055 if (args->print_args->print_summary) {
2056 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2057 epan_dissect_fill_in_columns(edt);
2059 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
2061 if (args->print_formfeed) {
2062 if (!new_page(args->print_args->stream))
2065 if (args->print_separator) {
2066 if (!print_line(args->print_args->stream, 0, ""))
2072 * We generate bookmarks, if the output format supports them.
2073 * The name is "__frameN__".
2075 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2077 if (args->print_args->print_summary) {
2078 if (args->print_header_line) {
2079 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2081 args->print_header_line = FALSE; /* we might not need to print any more */
2083 cp = &args->line_buf[0];
2085 for (i = 0; i < cf->cinfo.num_cols; i++) {
2086 /* Find the length of the string for this column. */
2087 column_len = (int) strlen(cf->cinfo.col_data[i]);
2088 if (args->col_widths[i] > column_len)
2089 column_len = args->col_widths[i];
2091 /* Make sure there's room in the line buffer for the column; if not,
2092 double its length. */
2093 line_len += column_len + 1; /* "+1" for space */
2094 if (line_len > args->line_buf_len) {
2095 cp_off = (int) (cp - args->line_buf);
2096 args->line_buf_len = 2 * line_len;
2097 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2098 cp = args->line_buf + cp_off;
2101 /* Right-justify the packet number column. */
2102 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2103 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
2105 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
2107 if (i != cf->cinfo.num_cols - 1)
2113 * Generate a bookmark, using the summary line as the title.
2115 if (!print_bookmark(args->print_args->stream, bookmark_name,
2119 if (!print_line(args->print_args->stream, 0, args->line_buf))
2123 * Generate a bookmark, using "Frame N" as the title, as we're not
2124 * printing the summary line.
2126 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2127 if (!print_bookmark(args->print_args->stream, bookmark_name,
2130 } /* if (print_summary) */
2132 if (args->print_args->print_dissections != print_dissections_none) {
2133 if (args->print_args->print_summary) {
2134 /* Separate the summary line from the tree with a blank line. */
2135 if (!print_line(args->print_args->stream, 0, ""))
2139 /* Print the information in that tree. */
2140 if (!proto_tree_print(args->print_args, edt, args->print_args->stream))
2143 /* Print a blank line if we print anything after this (aka more than one packet). */
2144 args->print_separator = TRUE;
2146 /* Print a header line if we print any more packet summaries */
2147 args->print_header_line = TRUE;
2150 if (args->print_args->print_hex) {
2151 /* Print the full packet data as hex. */
2152 if (!print_hex_data(args->print_args->stream, edt))
2155 /* Print a blank line if we print anything after this (aka more than one packet). */
2156 args->print_separator = TRUE;
2158 /* Print a header line if we print any more packet summaries */
2159 args->print_header_line = TRUE;
2160 } /* if (args->print_args->print_dissections != print_dissections_none) */
2162 epan_dissect_free(edt);
2164 /* do we want to have a formfeed between each packet from now on? */
2165 if(args->print_args->print_formfeed) {
2166 args->print_formfeed = TRUE;
2172 epan_dissect_free(edt);
2177 cf_print_packets(capture_file *cf, print_args_t *print_args)
2180 print_callback_args_t callback_args;
2188 callback_args.print_args = print_args;
2189 callback_args.print_header_line = TRUE;
2190 callback_args.header_line_buf = NULL;
2191 callback_args.header_line_buf_len = 256;
2192 callback_args.print_formfeed = FALSE;
2193 callback_args.print_separator = FALSE;
2194 callback_args.line_buf = NULL;
2195 callback_args.line_buf_len = 256;
2196 callback_args.col_widths = NULL;
2198 if (!print_preamble(print_args->stream, cf->filename)) {
2199 destroy_print_stream(print_args->stream);
2200 return CF_PRINT_WRITE_ERROR;
2203 if (print_args->print_summary) {
2204 /* We're printing packet summaries. Allocate the header line buffer
2205 and get the column widths. */
2206 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2208 /* Find the widths for each of the columns - maximum of the
2209 width of the title and the width of the data - and construct
2210 a buffer with a line containing the column titles. */
2211 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2212 cp = &callback_args.header_line_buf[0];
2214 for (i = 0; i < cf->cinfo.num_cols; i++) {
2215 /* Don't pad the last column. */
2216 if (i == cf->cinfo.num_cols - 1)
2217 callback_args.col_widths[i] = 0;
2219 callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
2220 data_width = get_column_char_width(get_column_format(i));
2221 if (data_width > callback_args.col_widths[i])
2222 callback_args.col_widths[i] = data_width;
2225 /* Find the length of the string for this column. */
2226 column_len = (int) strlen(cf->cinfo.col_title[i]);
2227 if (callback_args.col_widths[i] > column_len)
2228 column_len = callback_args.col_widths[i];
2230 /* Make sure there's room in the line buffer for the column; if not,
2231 double its length. */
2232 line_len += column_len + 1; /* "+1" for space */
2233 if (line_len > callback_args.header_line_buf_len) {
2234 cp_off = (int) (cp - callback_args.header_line_buf);
2235 callback_args.header_line_buf_len = 2 * line_len;
2236 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2237 callback_args.header_line_buf_len + 1);
2238 cp = callback_args.header_line_buf + cp_off;
2241 /* Right-justify the packet number column. */
2242 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2243 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2245 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2247 if (i != cf->cinfo.num_cols - 1)
2252 /* Now start out the main line buffer with the same length as the
2253 header line buffer. */
2254 callback_args.line_buf_len = callback_args.header_line_buf_len;
2255 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2256 } /* if (print_summary) */
2258 /* Iterate through the list of packets, printing the packets we were
2260 ret = process_specified_packets(cf, &print_args->range, "Printing",
2261 "selected packets", TRUE, print_packet,
2264 g_free(callback_args.header_line_buf);
2265 g_free(callback_args.line_buf);
2266 g_free(callback_args.col_widths);
2271 /* Completed successfully. */
2275 /* Well, the user decided to abort the printing.
2277 XXX - note that what got generated before they did that
2278 will get printed if we're piping to a print program; we'd
2279 have to write to a file and then hand that to the print
2280 program to make it actually not print anything. */
2284 /* Error while printing.
2286 XXX - note that what got generated before they did that
2287 will get printed if we're piping to a print program; we'd
2288 have to write to a file and then hand that to the print
2289 program to make it actually not print anything. */
2290 destroy_print_stream(print_args->stream);
2291 return CF_PRINT_WRITE_ERROR;
2294 if (!print_finale(print_args->stream)) {
2295 destroy_print_stream(print_args->stream);
2296 return CF_PRINT_WRITE_ERROR;
2299 if (!destroy_print_stream(print_args->stream))
2300 return CF_PRINT_WRITE_ERROR;
2306 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2307 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2311 epan_dissect_t *edt;
2313 /* Create the protocol tree, but don't fill in the column information. */
2314 edt = epan_dissect_new(TRUE, TRUE);
2315 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
2317 /* Write out the information in that tree. */
2318 proto_tree_write_pdml(edt, fh);
2320 epan_dissect_free(edt);
2326 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2331 fh = ws_fopen(print_args->file, "w");
2333 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2335 write_pdml_preamble(fh);
2338 return CF_PRINT_WRITE_ERROR;
2341 /* Iterate through the list of packets, printing the packets we were
2343 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2344 "selected packets", TRUE,
2345 write_pdml_packet, fh);
2350 /* Completed successfully. */
2354 /* Well, the user decided to abort the printing. */
2358 /* Error while printing. */
2360 return CF_PRINT_WRITE_ERROR;
2363 write_pdml_finale(fh);
2366 return CF_PRINT_WRITE_ERROR;
2369 /* XXX - check for an error */
2376 write_psml_packet(capture_file *cf, frame_data *fdata,
2377 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2381 epan_dissect_t *edt;
2382 gboolean proto_tree_needed;
2384 /* Fill in the column information, only create the protocol tree
2385 if having custom columns. */
2386 proto_tree_needed = have_custom_cols(&cf->cinfo);
2387 edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
2388 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2389 epan_dissect_fill_in_columns(edt);
2391 /* Write out the information in that tree. */
2392 proto_tree_write_psml(edt, fh);
2394 epan_dissect_free(edt);
2400 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2405 fh = ws_fopen(print_args->file, "w");
2407 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2409 write_psml_preamble(fh);
2412 return CF_PRINT_WRITE_ERROR;
2415 /* Iterate through the list of packets, printing the packets we were
2417 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2418 "selected packets", TRUE,
2419 write_psml_packet, fh);
2424 /* Completed successfully. */
2428 /* Well, the user decided to abort the printing. */
2432 /* Error while printing. */
2434 return CF_PRINT_WRITE_ERROR;
2437 write_psml_finale(fh);
2440 return CF_PRINT_WRITE_ERROR;
2443 /* XXX - check for an error */
2450 write_csv_packet(capture_file *cf, frame_data *fdata,
2451 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2455 epan_dissect_t *edt;
2456 gboolean proto_tree_needed;
2458 /* Fill in the column information, only create the protocol tree
2459 if having custom columns. */
2460 proto_tree_needed = have_custom_cols(&cf->cinfo);
2461 edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
2462 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2463 epan_dissect_fill_in_columns(edt);
2465 /* Write out the information in that tree. */
2466 proto_tree_write_csv(edt, fh);
2468 epan_dissect_free(edt);
2474 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2479 fh = ws_fopen(print_args->file, "w");
2481 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2483 write_csv_preamble(fh);
2486 return CF_PRINT_WRITE_ERROR;
2489 /* Iterate through the list of packets, printing the packets we were
2491 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2492 "selected packets", TRUE,
2493 write_csv_packet, fh);
2498 /* Completed successfully. */
2502 /* Well, the user decided to abort the printing. */
2506 /* Error while printing. */
2508 return CF_PRINT_WRITE_ERROR;
2511 write_csv_finale(fh);
2514 return CF_PRINT_WRITE_ERROR;
2517 /* XXX - check for an error */
2524 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
2525 union wtap_pseudo_header *pseudo_header _U_,
2526 const guint8 *pd, void *argsp)
2530 proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh);
2535 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2540 fh = ws_fopen(print_args->file, "w");
2543 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2545 write_carrays_preamble(fh);
2549 return CF_PRINT_WRITE_ERROR;
2552 /* Iterate through the list of packets, printing the packets we were
2554 ret = process_specified_packets(cf, &print_args->range,
2556 "selected packets", TRUE,
2557 write_carrays_packet, fh);
2560 /* Completed successfully. */
2563 /* Well, the user decided to abort the printing. */
2566 /* Error while printing. */
2568 return CF_PRINT_WRITE_ERROR;
2571 write_carrays_finale(fh);
2575 return CF_PRINT_WRITE_ERROR;
2582 /* Scan through the packet list and change all columns that use the
2583 "command-line-specified" time stamp format to use the current
2584 value of that format. */
2586 cf_change_time_formats(capture_file *cf)
2589 progdlg_t *progbar = NULL;
2595 GTimeVal start_time;
2596 gchar status_str[100];
2597 int progbar_nextstep;
2598 int progbar_quantum;
2599 gboolean sorted_by_frame_column;
2602 /* adjust timestamp precision if auto is selected */
2603 cf_timestamp_auto_precision(cf);
2605 /* Are there any columns with time stamps in the "command-line-specified"
2608 XXX - we have to force the "column is writable" flag on, as it
2609 might be off from the last frame that was dissected. */
2610 col_set_writable(&cf->cinfo, TRUE);
2611 if (!check_col(&cf->cinfo, COL_CLS_TIME) &&
2612 !check_col(&cf->cinfo, COL_ABS_TIME) &&
2613 !check_col(&cf->cinfo, COL_ABS_DATE_TIME) &&
2614 !check_col(&cf->cinfo, COL_REL_TIME) &&
2615 !check_col(&cf->cinfo, COL_DELTA_TIME) &&
2616 !check_col(&cf->cinfo, COL_DELTA_TIME_DIS)) {
2617 /* No, there aren't any columns in that format, so we have no work
2622 /* Freeze the packet list while we redo it, so we don't get any
2623 screen updates while it happens. */
2624 packet_list_freeze();
2626 /* Update the progress bar when it gets to this value. */
2627 progbar_nextstep = 0;
2628 /* When we reach the value that triggers a progress bar update,
2629 bump that value by this amount. */
2630 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2631 /* Count of packets at which we've looked. */
2633 /* Progress so far. */
2636 /* If the rows are currently sorted by the frame column then we know
2637 * the row number of each packet: it's the row number of the previously
2638 * displayed packet + 1.
2640 * Otherwise, if the display is sorted by a different column then we have
2641 * to use the O(N) packet_list_find_row_from_data() (thus making the job
2642 * of changing the time display format O(N**2)).
2644 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
2645 * the row number and walks that many elements down the clist to find
2646 * the appropriate element.)
2648 sorted_by_frame_column = FALSE;
2649 for (i = 0; i < cf->cinfo.num_cols; i++) {
2650 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2652 sorted_by_frame_column = (i == packet_list_get_sort_column());
2658 g_get_current_time(&start_time);
2660 /* Iterate through the list of packets, checking whether the packet
2661 is in a row of the summary list and, if so, whether there are
2662 any columns that show the time in the "command-line-specified"
2663 format and, if so, update that row. */
2664 for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
2665 /* Create the progress bar if necessary.
2666 We check on every iteration of the loop, so that it takes no
2667 longer than the standard time to create it (otherwise, for a
2668 large file, we might take considerably longer than that standard
2669 time in order to get to the next progress bar step). */
2670 if (progbar == NULL)
2671 progbar = delayed_create_progress_dlg("Changing", "time display",
2672 TRUE, &stop_flag, &start_time, progbar_val);
2674 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2675 when we update it, we have to run the GTK+ main loop to get it
2676 to repaint what's pending, and doing so may involve an "ioctl()"
2677 to see if there's any pending input from an X server, and doing
2678 that for every packet can be costly, especially on a big file. */
2679 if (count >= progbar_nextstep) {
2680 /* let's not divide by zero. I should never be started
2681 * with count == 0, so let's assert that
2683 g_assert(cf->count > 0);
2685 progbar_val = (gfloat) count / cf->count;
2687 if (progbar != NULL) {
2688 g_snprintf(status_str, sizeof(status_str),
2689 "%4u of %u packets", count, cf->count);
2690 update_progress_dlg(progbar, progbar_val, status_str);
2693 progbar_nextstep += progbar_quantum;
2697 /* Well, the user decided to abort the redisplay. Just stop.
2699 XXX - this leaves the time field in the old format in
2700 frames we haven't yet processed. So it goes; should we
2701 simply not offer them the option of stopping? */
2707 /* Find what row this packet is in. */
2708 if (!sorted_by_frame_column) {
2709 /* This function is O(N), so we try to avoid using it... */
2710 row = packet_list_find_row_from_data(fdata);
2712 /* ...which we do by maintaining a count of packets that are
2713 being displayed (i.e., that have passed the display filter),
2714 and using the current value of that count as the row number
2715 (which is why we can only do it when the display is sorted
2716 by the frame number). */
2717 if (fdata->flags.passed_dfilter)
2724 /* This packet is in the summary list, on row "row". */
2726 for (i = 0; i < cf->cinfo.num_cols; i++) {
2727 if (col_has_time_fmt(&cf->cinfo, i)) {
2728 /* This is one of the columns that shows the time in
2729 "command-line-specified" format; update it. */
2730 cf->cinfo.col_buf[i][0] = '\0';
2731 col_set_fmt_time(fdata, &cf->cinfo, cf->cinfo.col_fmt[i], i);
2732 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
2738 /* We're done redisplaying the packets; destroy the progress bar if it
2740 if (progbar != NULL)
2741 destroy_progress_dlg(progbar);
2743 /* Set the column widths of those columns that show the time in
2744 "command-line-specified" format. */
2745 for (i = 0; i < cf->cinfo.num_cols; i++) {
2746 if (col_has_time_fmt(&cf->cinfo, i)) {
2747 packet_list_set_time_width(cf->cinfo.col_fmt[i], i);
2751 /* Unfreeze the packet list. */
2759 gboolean frame_matched;
2763 cf_find_packet_protocol_tree(capture_file *cf, const char *string)
2767 mdata.string = string;
2768 mdata.string_len = strlen(string);
2769 return find_packet(cf, match_protocol_tree, &mdata);
2773 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2775 match_data *mdata = criterion;
2776 epan_dissect_t *edt;
2778 /* Construct the protocol tree, including the displayed text */
2779 edt = epan_dissect_new(TRUE, TRUE);
2780 /* We don't need the column information */
2781 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2783 /* Iterate through all the nodes, seeing if they have text that matches. */
2785 mdata->frame_matched = FALSE;
2786 proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
2787 epan_dissect_free(edt);
2788 return mdata->frame_matched;
2792 match_subtree_text(proto_node *node, gpointer data)
2794 match_data *mdata = (match_data*) data;
2795 const gchar *string = mdata->string;
2796 size_t string_len = mdata->string_len;
2797 capture_file *cf = mdata->cf;
2798 field_info *fi = PITEM_FINFO(node);
2799 gchar label_str[ITEM_LABEL_LENGTH];
2806 if (mdata->frame_matched) {
2807 /* We already had a match; don't bother doing any more work. */
2811 /* Don't match invisible entries. */
2812 if (PROTO_ITEM_IS_HIDDEN(node))
2815 /* was a free format label produced? */
2817 label_ptr = fi->rep->representation;
2819 /* no, make a generic label */
2820 label_ptr = label_str;
2821 proto_item_fill_label(fi, label_str);
2824 /* Does that label match? */
2825 label_len = strlen(label_ptr);
2826 for (i = 0; i < label_len; i++) {
2827 c_char = label_ptr[i];
2829 c_char = toupper(c_char);
2830 if (c_char == string[c_match]) {
2832 if (c_match == string_len) {
2833 /* No need to look further; we have a match */
2834 mdata->frame_matched = TRUE;
2841 /* Recurse into the subtree, if it exists */
2842 if (node->first_child != NULL)
2843 proto_tree_children_foreach(node, match_subtree_text, mdata);
2847 cf_find_packet_summary_line(capture_file *cf, const char *string)
2851 mdata.string = string;
2852 mdata.string_len = strlen(string);
2853 return find_packet(cf, match_summary_line, &mdata);
2857 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2859 match_data *mdata = criterion;
2860 const gchar *string = mdata->string;
2861 size_t string_len = mdata->string_len;
2862 epan_dissect_t *edt;
2863 const char *info_column;
2864 size_t info_column_len;
2865 gboolean frame_matched = FALSE;
2871 /* Don't bother constructing the protocol tree */
2872 edt = epan_dissect_new(FALSE, FALSE);
2873 /* Get the column information */
2874 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2876 /* Find the Info column */
2877 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2878 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2879 /* Found it. See if we match. */
2880 info_column = edt->pi.cinfo->col_data[colx];
2881 info_column_len = strlen(info_column);
2882 for (i = 0; i < info_column_len; i++) {
2883 c_char = info_column[i];
2885 c_char = toupper(c_char);
2886 if (c_char == string[c_match]) {
2888 if (c_match == string_len) {
2889 frame_matched = TRUE;
2898 epan_dissect_free(edt);
2899 return frame_matched;
2905 } cbs_t; /* "Counted byte string" */
2908 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
2913 info.data_len = string_size;
2915 /* String or hex search? */
2917 /* String search - what type of string? */
2918 switch (cf->scs_type) {
2920 case SCS_ASCII_AND_UNICODE:
2921 return find_packet(cf, match_ascii_and_unicode, &info);
2924 return find_packet(cf, match_ascii, &info);
2927 return find_packet(cf, match_unicode, &info);
2930 g_assert_not_reached();
2934 return find_packet(cf, match_binary, &info);
2938 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2940 cbs_t *info = criterion;
2941 const guint8 *ascii_text = info->data;
2942 size_t textlen = info->data_len;
2943 gboolean frame_matched;
2949 frame_matched = FALSE;
2950 buf_len = fdata->pkt_len;
2951 for (i = 0; i < buf_len; i++) {
2954 c_char = toupper(c_char);
2956 if (c_char == ascii_text[c_match]) {
2958 if (c_match == textlen) {
2959 frame_matched = TRUE;
2960 cf->search_pos = i; /* Save the position of the last character
2961 for highlighting the field. */
2968 return frame_matched;
2972 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2974 cbs_t *info = criterion;
2975 const guint8 *ascii_text = info->data;
2976 size_t textlen = info->data_len;
2977 gboolean frame_matched;
2983 frame_matched = FALSE;
2984 buf_len = fdata->pkt_len;
2985 for (i = 0; i < buf_len; i++) {
2988 c_char = toupper(c_char);
2989 if (c_char == ascii_text[c_match]) {
2991 if (c_match == textlen) {
2992 frame_matched = TRUE;
2993 cf->search_pos = i; /* Save the position of the last character
2994 for highlighting the field. */
3000 return frame_matched;
3004 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3006 cbs_t *info = criterion;
3007 const guint8 *ascii_text = info->data;
3008 size_t textlen = info->data_len;
3009 gboolean frame_matched;
3015 frame_matched = FALSE;
3016 buf_len = fdata->pkt_len;
3017 for (i = 0; i < buf_len; i++) {
3020 c_char = toupper(c_char);
3021 if (c_char == ascii_text[c_match]) {
3024 if (c_match == textlen) {
3025 frame_matched = TRUE;
3026 cf->search_pos = i; /* Save the position of the last character
3027 for highlighting the field. */
3033 return frame_matched;
3037 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3039 cbs_t *info = criterion;
3040 const guint8 *binary_data = info->data;
3041 size_t datalen = info->data_len;
3042 gboolean frame_matched;
3047 frame_matched = FALSE;
3048 buf_len = fdata->pkt_len;
3049 for (i = 0; i < buf_len; i++) {
3050 if (cf->pd[i] == binary_data[c_match]) {
3052 if (c_match == datalen) {
3053 frame_matched = TRUE;
3054 cf->search_pos = i; /* Save the position of the last character
3055 for highlighting the field. */
3061 return frame_matched;
3065 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
3067 return find_packet(cf, match_dfilter, sfcode);
3071 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3073 dfilter_t *sfcode = criterion;
3074 epan_dissect_t *edt;
3075 gboolean frame_matched;
3077 edt = epan_dissect_new(TRUE, FALSE);
3078 epan_dissect_prime_dfilter(edt, sfcode);
3079 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3080 frame_matched = dfilter_apply_edt(sfcode, edt);
3081 epan_dissect_free(edt);
3082 return frame_matched;
3086 find_packet(capture_file *cf,
3087 gboolean (*match_function)(capture_file *, frame_data *, void *),
3090 frame_data *start_fd;
3092 frame_data *new_fd = NULL;
3093 progdlg_t *progbar = NULL;
3100 GTimeVal start_time;
3101 gchar status_str[100];
3102 int progbar_nextstep;
3103 int progbar_quantum;
3106 start_fd = cf->current_frame;
3107 if (start_fd != NULL) {
3108 /* Iterate through the list of packets, starting at the packet we've
3109 picked, calling a routine to run the filter on the packet, see if
3110 it matches, and stop if so. */
3114 /* Update the progress bar when it gets to this value. */
3115 progbar_nextstep = 0;
3116 /* When we reach the value that triggers a progress bar update,
3117 bump that value by this amount. */
3118 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3119 /* Progress so far. */
3123 g_get_current_time(&start_time);
3126 title = cf->sfilter?cf->sfilter:"";
3128 /* Create the progress bar if necessary.
3129 We check on every iteration of the loop, so that it takes no
3130 longer than the standard time to create it (otherwise, for a
3131 large file, we might take considerably longer than that standard
3132 time in order to get to the next progress bar step). */
3133 if (progbar == NULL)
3134 progbar = delayed_create_progress_dlg("Searching", title,
3135 FALSE, &stop_flag, &start_time, progbar_val);
3137 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3138 when we update it, we have to run the GTK+ main loop to get it
3139 to repaint what's pending, and doing so may involve an "ioctl()"
3140 to see if there's any pending input from an X server, and doing
3141 that for every packet can be costly, especially on a big file. */
3142 if (count >= progbar_nextstep) {
3143 /* let's not divide by zero. I should never be started
3144 * with count == 0, so let's assert that
3146 g_assert(cf->count > 0);
3148 progbar_val = (gfloat) count / cf->count;
3150 if (progbar != NULL) {
3151 g_snprintf(status_str, sizeof(status_str),
3152 "%4u of %u packets", count, cf->count);
3153 update_progress_dlg(progbar, progbar_val, status_str);
3156 progbar_nextstep += progbar_quantum;
3160 /* Well, the user decided to abort the search. Go back to the
3161 frame where we started. */
3166 /* Go past the current frame. */
3167 if (cf->sbackward) {
3168 /* Go on to the previous frame. */
3169 fdata = fdata->prev;
3170 if (fdata == NULL) {
3172 * XXX - other apps have a bit more of a detailed message
3173 * for this, and instead of offering "OK" and "Cancel",
3174 * they offer things such as "Continue" and "Cancel";
3175 * we need an API for popping up alert boxes with
3176 * {Verb} and "Cancel".
3179 if (prefs.gui_find_wrap)
3181 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3182 "%sBeginning of capture exceeded!%s\n\n"
3183 "Search is continued from the end of the capture.",
3184 simple_dialog_primary_start(), simple_dialog_primary_end());
3185 fdata = cf->plist_end; /* wrap around */
3189 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3190 "%sBeginning of capture exceeded!%s\n\n"
3191 "Try searching forwards.",
3192 simple_dialog_primary_start(), simple_dialog_primary_end());
3193 fdata = start_fd; /* stay on previous packet */
3197 /* Go on to the next frame. */
3198 fdata = fdata->next;
3199 if (fdata == NULL) {
3200 if (prefs.gui_find_wrap)
3202 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3203 "%sEnd of capture exceeded!%s\n\n"
3204 "Search is continued from the start of the capture.",
3205 simple_dialog_primary_start(), simple_dialog_primary_end());
3206 fdata = cf->plist; /* wrap around */
3210 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3211 "%sEnd of capture exceeded!%s\n\n"
3212 "Try searching backwards.",
3213 simple_dialog_primary_start(), simple_dialog_primary_end());
3214 fdata = start_fd; /* stay on previous packet */
3221 /* Is this packet in the display? */
3222 if (fdata->flags.passed_dfilter) {
3223 /* Yes. Load its data. */
3224 if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
3225 cf->pd, fdata->cap_len, &err, &err_info)) {
3226 /* Read error. Report the error, and go back to the frame
3227 where we started. */
3228 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3229 cf_read_error_message(err, err_info), cf->filename);
3234 /* Does it match the search criterion? */
3235 if ((*match_function)(cf, fdata, criterion)) {
3237 break; /* found it! */
3241 if (fdata == start_fd) {
3242 /* We're back to the frame we were on originally, and that frame
3243 doesn't match the search filter. The search failed. */
3248 /* We're done scanning the packets; destroy the progress bar if it
3250 if (progbar != NULL)
3251 destroy_progress_dlg(progbar);
3254 if (new_fd != NULL) {
3255 /* We found a frame. Find what row it's in. */
3256 row = packet_list_find_row_from_data(new_fd);
3258 /* We didn't find a row even though we know that a frame
3259 * exists that satifies the search criteria. This means that the
3260 * frame isn't being displayed currently so we can't select it. */
3261 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3262 "%sEnd of capture exceeded!%s\n\n"
3263 "The capture file is probably not fully loaded.",
3264 simple_dialog_primary_start(), simple_dialog_primary_end());
3268 /* Select that row, make it the focus row, and make it visible. */
3269 packet_list_set_selected_row(row);
3270 return TRUE; /* success */
3272 return FALSE; /* failure */
3276 cf_goto_frame(capture_file *cf, guint fnumber)
3281 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
3284 if (fdata == NULL) {
3285 /* we didn't find a packet with that packet number */
3286 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3287 "There is no packet with the packet number %u.", fnumber);
3288 return FALSE; /* we failed to go to that packet */
3290 if (!fdata->flags.passed_dfilter) {
3291 /* that packet currently isn't displayed */
3292 /* XXX - add it to the set of displayed packets? */
3293 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3294 "The packet number %u isn't currently being displayed.", fnumber);
3295 return FALSE; /* we failed to go to that packet */
3298 /* We found that packet, and it's currently being displayed.
3299 Find what row it's in. */
3300 row = packet_list_find_row_from_data(fdata);
3301 g_assert(row != -1);
3303 /* Select that row, make it the focus row, and make it visible. */
3304 packet_list_set_selected_row(row);
3305 return TRUE; /* we got to that packet */
3309 cf_goto_top_frame(capture_file *cf)
3313 frame_data *lowest_fdata = NULL;
3315 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
3316 if (fdata->flags.passed_dfilter) {
3317 lowest_fdata = fdata;
3322 if (lowest_fdata == NULL) {
3326 /* We found that packet, and it's currently being displayed.
3327 Find what row it's in. */
3328 row = packet_list_find_row_from_data(lowest_fdata);
3329 g_assert(row != -1);
3331 /* Select that row, make it the focus row, and make it visible. */
3332 packet_list_set_selected_row(row);
3333 return TRUE; /* we got to that packet */
3337 cf_goto_bottom_frame(capture_file *cf)
3341 frame_data *highest_fdata = NULL;
3343 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
3344 if (fdata->flags.passed_dfilter) {
3345 highest_fdata = fdata;
3349 if (highest_fdata == NULL) {
3353 /* We found that packet, and it's currently being displayed.
3354 Find what row it's in. */
3355 row = packet_list_find_row_from_data(highest_fdata);
3356 g_assert(row != -1);
3358 /* Select that row, make it the focus row, and make it visible. */
3359 packet_list_set_selected_row(row);
3360 return TRUE; /* we got to that packet */
3364 * Go to frame specified by currently selected protocol tree item.
3367 cf_goto_framenum(capture_file *cf)
3369 header_field_info *hfinfo;
3372 if (cf->finfo_selected) {
3373 hfinfo = cf->finfo_selected->hfinfo;
3375 if (hfinfo->type == FT_FRAMENUM) {
3376 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3378 return cf_goto_frame(cf, framenum);
3385 /* Select the packet on a given row. */
3387 cf_select_packet(capture_file *cf, int row)
3393 /* Get the frame data struct pointer for this frame */
3394 fdata = (frame_data *)packet_list_get_row_data(row);
3396 if (fdata == NULL) {
3397 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3398 the first entry is added to it by "real_insert_row()", that row
3399 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3400 our version and the vanilla GTK+ version).
3402 This means that a "select-row" signal is emitted; this causes
3403 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3406 "cf_select_packet()" fetches, above, the data associated with the
3407 row that was selected; however, as "gtk_clist_append()", which
3408 called "real_insert_row()", hasn't yet returned, we haven't yet
3409 associated any data with that row, so we get back a null pointer.
3411 We can't assume that there's only one frame in the frame list,
3412 either, as we may be filtering the display.
3414 We therefore assume that, if "row" is 0, i.e. the first row
3415 is being selected, and "cf->first_displayed" equals
3416 "cf->last_displayed", i.e. there's only one frame being
3417 displayed, that frame is the frame we want.
3419 This means we have to set "cf->first_displayed" and
3420 "cf->last_displayed" before adding the row to the
3421 GtkCList; see the comment in "add_packet_to_packet_list()". */
3423 if (row == 0 && cf->first_displayed == cf->last_displayed)
3424 fdata = cf->first_displayed;
3427 /* If fdata _still_ isn't set simply give up. */
3428 if (fdata == NULL) {
3432 /* Get the data in that frame. */
3433 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
3434 cf->pd, fdata->cap_len, &err, &err_info)) {
3435 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3436 cf_read_error_message(err, err_info), cf->filename);
3440 /* Record that this frame is the current frame. */
3441 cf->current_frame = fdata;
3442 cf->current_row = row;
3444 /* Create the logical protocol tree. */
3445 if (cf->edt != NULL) {
3446 epan_dissect_free(cf->edt);
3449 /* We don't need the columns here. */
3450 cf->edt = epan_dissect_new(TRUE, TRUE);
3452 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3455 dfilter_macro_build_ftv_cache(cf->edt->tree);
3457 cf_callback_invoke(cf_cb_packet_selected, cf);
3460 /* Unselect the selected packet, if any. */
3462 cf_unselect_packet(capture_file *cf)
3464 /* Destroy the epan_dissect_t for the unselected packet. */
3465 if (cf->edt != NULL) {
3466 epan_dissect_free(cf->edt);
3470 /* No packet is selected. */
3471 cf->current_frame = NULL;
3472 cf->current_row = 0;
3474 cf_callback_invoke(cf_cb_packet_unselected, cf);
3476 /* No protocol tree means no selected field. */
3477 cf_unselect_field(cf);
3480 /* Unset the selected protocol tree field, if any. */
3482 cf_unselect_field(capture_file *cf)
3484 cf->finfo_selected = NULL;
3486 cf_callback_invoke(cf_cb_field_unselected, cf);
3490 * Mark a particular frame.
3493 cf_mark_frame(capture_file *cf, frame_data *frame)
3495 if (! frame->flags.marked) {
3496 frame->flags.marked = TRUE;
3497 if (cf->count > cf->marked_count)
3503 * Unmark a particular frame.
3506 cf_unmark_frame(capture_file *cf, frame_data *frame)
3508 if (frame->flags.marked) {
3509 frame->flags.marked = FALSE;
3510 if (cf->marked_count > 0)
3518 } save_callback_args_t;
3521 * Save a capture to a file, in a particular format, saving either
3522 * all packets, all currently-displayed packets, or all marked packets.
3524 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3525 * up a message box for the failure.
3528 save_packet(capture_file *cf _U_, frame_data *fdata,
3529 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3532 save_callback_args_t *args = argsp;
3533 struct wtap_pkthdr hdr;
3536 /* init the wtap header for saving */
3537 hdr.ts.secs = fdata->abs_ts.secs;
3538 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3539 hdr.caplen = fdata->cap_len;
3540 hdr.len = fdata->pkt_len;
3541 hdr.pkt_encap = fdata->lnk_t;
3543 /* and save the packet */
3544 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3545 cf_write_failure_alert_box(args->fname, err);
3552 * Can this capture file be saved in any format except by copying the raw data?
3555 cf_can_save_as(capture_file *cf)
3559 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
3560 /* To save a file with Wiretap, Wiretap has to handle that format,
3561 and its code to handle that format must be able to write a file
3562 with this file's encapsulation type. */
3563 if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
3564 /* OK, we can write it out in this type. */
3569 /* No, we couldn't save it in any format. */
3574 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3576 gchar *from_filename;
3580 save_callback_args_t callback_args;
3582 cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname);
3584 /* don't write over an existing file. */
3585 /* this should've been already checked by our caller, just to be sure... */
3586 if (file_exists(fname)) {
3587 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3588 "%sCapture file: \"%s\" already exists!%s\n\n"
3589 "Please choose a different filename.",
3590 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3594 packet_range_process_init(range);
3597 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3598 /* We're not filtering packets, and we're saving it in the format
3599 it's already in, so we can just move or copy the raw data. */
3601 if (cf->is_tempfile) {
3602 /* The file being saved is a temporary file from a live
3603 capture, so it doesn't need to stay around under that name;
3604 first, try renaming the capture buffer file to the new name. */
3606 if (ws_rename(cf->filename, fname) == 0) {
3607 /* That succeeded - there's no need to copy the source file. */
3608 from_filename = NULL;
3611 if (errno == EXDEV) {
3612 /* They're on different file systems, so we have to copy the
3615 from_filename = cf->filename;
3617 /* The rename failed, but not because they're on different
3618 file systems - put up an error message. (Or should we
3619 just punt and try to copy? The only reason why I'd
3620 expect the rename to fail and the copy to succeed would
3621 be if we didn't have permission to remove the file from
3622 the temporary directory, and that might be fixable - but
3623 is it worth requiring the user to go off and fix it?) */
3624 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3625 file_rename_error_message(errno), fname);
3631 from_filename = cf->filename;
3634 /* It's a permanent file, so we should copy it, and not remove the
3637 from_filename = cf->filename;
3641 /* Copy the file, if we haven't moved it. */
3642 if (!copy_file_binary_mode(from_filename, fname))
3646 /* Either we're filtering packets, or we're saving in a different
3647 format; we can't do that by copying or moving the capture file,
3648 we have to do it by writing the packets out in Wiretap. */
3649 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3652 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3656 /* XXX - we let the user save a subset of the packets.
3658 If we do that, should we make that file the current file? If so,
3659 it means we can no longer get at the other packets. What does
3662 /* Iterate through the list of packets, processing the packets we were
3665 XXX - we've already called "packet_range_process_init(range)", but
3666 "process_specified_packets()" will do it again. Fortunately,
3667 that's harmless in this case, as we haven't done anything to
3668 "range" since we initialized it. */
3669 callback_args.pdh = pdh;
3670 callback_args.fname = fname;
3671 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3672 TRUE, save_packet, &callback_args)) {
3675 /* Completed successfully. */
3679 /* The user decided to abort the saving.
3680 XXX - remove the output file? */
3684 /* Error while saving. */
3685 wtap_dump_close(pdh, &err);
3689 if (!wtap_dump_close(pdh, &err)) {
3690 cf_close_failure_alert_box(fname, err);
3695 cf_callback_invoke(cf_cb_file_safe_finished, NULL);
3697 if (packet_range_process_all(range)) {
3698 /* We saved the entire capture, not just some packets from it.
3699 Open and read the file we saved it to.
3701 XXX - this is somewhat of a waste; we already have the
3702 packets, all this gets us is updated file type information
3703 (which we could just stuff into "cf"), and having the new
3704 file be the one we have opened and from which we're reading
3705 the data, and it means we have to spend time opening and
3706 reading the file, which could be a significant amount of
3707 time if the file is large. */
3708 cf->user_saved = TRUE;
3710 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3711 /* XXX - report errors if this fails?
3712 What should we return if it fails or is aborted? */
3713 switch (cf_read(cf)) {
3717 /* Just because we got an error, that doesn't mean we were unable
3718 to read any of the file; we handle what we could get from the
3722 case CF_READ_ABORTED:
3723 /* The user bailed out of re-reading the capture file; the
3724 capture file has been closed - just return (without
3725 changing any menu settings; "cf_close()" set them
3726 correctly for the "no capture file open" state). */
3729 cf_callback_invoke(cf_cb_file_safe_reload_finished, NULL);
3735 cf_callback_invoke(cf_cb_file_safe_failed, NULL);
3740 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3741 gboolean for_writing, int file_type)
3744 /* Wiretap error. */
3747 case WTAP_ERR_NOT_REGULAR_FILE:
3748 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3749 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3753 case WTAP_ERR_RANDOM_OPEN_PIPE:
3754 /* Seen only when opening a capture file for reading. */
3755 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3756 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
3760 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3761 /* Seen only when opening a capture file for reading. */
3762 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3763 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
3767 case WTAP_ERR_UNSUPPORTED:
3768 /* Seen only when opening a capture file for reading. */
3769 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3770 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
3772 filename, err_info);
3776 case WTAP_ERR_CANT_WRITE_TO_PIPE:
3777 /* Seen only when opening a capture file for writing. */
3778 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3779 "The file \"%s\" is a pipe, and %s capture files can't be "
3780 "written to a pipe.",
3781 filename, wtap_file_type_string(file_type));
3784 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3785 /* Seen only when opening a capture file for writing. */
3786 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3787 "Wireshark doesn't support writing capture files in that format.");
3790 case WTAP_ERR_UNSUPPORTED_ENCAP:
3792 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3793 "Wireshark can't save this capture in that format.");
3795 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3796 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
3798 filename, err_info);
3803 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3805 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3806 "Wireshark can't save this capture in that format.");
3808 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3809 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
3814 case WTAP_ERR_BAD_RECORD:
3815 /* Seen only when opening a capture file for reading. */
3816 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3817 "The file \"%s\" appears to be damaged or corrupt.\n"
3819 filename, err_info);
3823 case WTAP_ERR_CANT_OPEN:
3825 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3826 "The file \"%s\" could not be created for some unknown reason.",
3829 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3830 "The file \"%s\" could not be opened for some unknown reason.",
3835 case WTAP_ERR_SHORT_READ:
3836 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3837 "The file \"%s\" appears to have been cut short"
3838 " in the middle of a packet or other data.",
3842 case WTAP_ERR_SHORT_WRITE:
3843 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3844 "A full header couldn't be written to the file \"%s\".",
3848 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
3849 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3850 "Gzip compression not supported by this file type.");
3854 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3855 "The file \"%s\" could not be %s: %s.",
3857 for_writing ? "created" : "opened",
3858 wtap_strerror(err));
3863 open_failure_alert_box(filename, err, for_writing);
3868 file_rename_error_message(int err)
3871 static char errmsg_errno[1024+1];
3876 errmsg = "The path to the file \"%s\" doesn't exist.";
3880 errmsg = "You don't have permission to move the capture file to \"%s\".";
3884 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3885 "The file \"%%s\" could not be moved: %s.",
3886 wtap_strerror(err));
3887 errmsg = errmsg_errno;
3894 cf_read_error_message(int err, gchar *err_info)
3896 static char errmsg_errno[1024+1];
3900 case WTAP_ERR_UNSUPPORTED_ENCAP:
3901 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3902 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
3907 case WTAP_ERR_BAD_RECORD:
3908 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3909 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
3910 wtap_strerror(err), err_info);
3915 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3916 "An error occurred while reading from the file \"%%s\": %s.",
3917 wtap_strerror(err));
3920 return errmsg_errno;
3924 cf_write_failure_alert_box(const char *filename, int err)
3927 /* Wiretap error. */
3928 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3929 "An error occurred while writing to the file \"%s\": %s.",
3930 filename, wtap_strerror(err));
3933 write_failure_alert_box(filename, err);
3937 /* Check for write errors - if the file is being written to an NFS server,
3938 a write error may not show up until the file is closed, as NFS clients
3939 might not send writes to the server until the "write()" call finishes,
3940 so that the write may fail on the server but the "write()" may succeed. */
3942 cf_close_failure_alert_box(const char *filename, int err)
3945 /* Wiretap error. */
3948 case WTAP_ERR_CANT_CLOSE:
3949 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3950 "The file \"%s\" couldn't be closed for some unknown reason.",
3954 case WTAP_ERR_SHORT_WRITE:
3955 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3956 "Not all the packets could be written to the file \"%s\".",
3961 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3962 "An error occurred while closing the file \"%s\": %s.",
3963 filename, wtap_strerror(err));
3968 We assume that a close error from the OS is really a write error. */
3969 write_failure_alert_box(filename, err);
3973 /* Reload the current capture file. */
3975 cf_reload(capture_file *cf) {
3977 gboolean is_tempfile;
3980 /* If the file could be opened, "cf_open()" calls "cf_close()"
3981 to get rid of state for the old capture file before filling in state
3982 for the new capture file. "cf_close()" will remove the file if
3983 it's a temporary file; we don't want that to happen (for one thing,
3984 it'd prevent subsequent reopens from working). Remember whether it's
3985 a temporary file, mark it as not being a temporary file, and then
3986 reopen it as the type of file it was.
3988 Also, "cf_close()" will free "cf->filename", so we must make
3989 a copy of it first. */
3990 filename = g_strdup(cf->filename);
3991 is_tempfile = cf->is_tempfile;
3992 cf->is_tempfile = FALSE;
3993 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
3994 switch (cf_read(cf)) {
3998 /* Just because we got an error, that doesn't mean we were unable
3999 to read any of the file; we handle what we could get from the
4003 case CF_READ_ABORTED:
4004 /* The user bailed out of re-reading the capture file; the
4005 capture file has been closed - just free the capture file name
4006 string and return (without changing the last containing
4012 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4013 Instead, the file was left open, so we should restore "cf->is_tempfile"
4016 XXX - change the menu? Presumably "cf_open()" will do that;
4017 make sure it does! */
4018 cf->is_tempfile = is_tempfile;
4020 /* "cf_open()" made a copy of the file name we handed it, so
4021 we should free up our copy. */