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 <epan/column-utils.h>
55 #include "packet-range.h"
61 #include "alert_box.h"
62 #include "simple_dialog.h"
63 #include "main_statusbar.h"
64 #include "progress_dlg.h"
66 #include <epan/prefs.h>
67 #include <epan/dfilter/dfilter.h>
68 #include <epan/epan_dissect.h>
70 #include <epan/dissectors/packet-data.h>
71 #include <epan/dissectors/packet-ber.h>
72 #include <epan/timestamp.h>
73 #include <epan/dfilter/dfilter-macro.h>
74 #include <wsutil/file_util.h>
75 #include <epan/strutil.h>
76 #include <epan/addr_resolv.h>
79 gboolean auto_scroll_live;
82 static guint32 cum_bytes;
83 static nstime_t first_ts;
84 static nstime_t prev_dis_ts;
85 static nstime_t prev_cap_ts;
87 static gulong computed_elapsed;
89 static void cf_reset_state(capture_file *cf);
91 static int read_packet(capture_file *cf, dfilter_t *dfcode,
92 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset);
94 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
95 gboolean refilter, gboolean redissect);
102 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
104 static void match_subtree_text(proto_node *node, gpointer data);
105 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
107 static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
109 static match_result match_ascii(capture_file *cf, frame_data *fdata,
111 static match_result match_unicode(capture_file *cf, frame_data *fdata,
113 static match_result match_binary(capture_file *cf, frame_data *fdata,
115 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
117 static match_result match_marked(capture_file *cf, frame_data *fdata,
119 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
121 static gboolean find_packet(capture_file *cf,
122 match_result (*match_function)(capture_file *, frame_data *, void *),
123 void *criterion, search_direction dir);
125 static void cf_open_failure_alert_box(const char *filename, int err,
126 gchar *err_info, gboolean for_writing,
128 static const char *file_rename_error_message(int err);
129 static void cf_write_failure_alert_box(const char *filename, int err);
130 static void cf_close_failure_alert_box(const char *filename, int err);
131 static void ref_time_packets(capture_file *cf);
132 /* Update the progress bar this many times when reading a file. */
133 #define N_PROGBAR_UPDATES 100
134 /* We read around 200k/100ms don't update the progress bar more often than that */
135 #define MIN_QUANTUM 200000
136 #define MIN_NUMBER_OF_PACKET 1500
138 /* Number of "frame_data" structures per memory chunk.
139 XXX - is this the right number? */
140 #define FRAME_DATA_CHUNK_SIZE 1024
144 * We could probably use g_signal_...() instead of the callbacks below but that
145 * would require linking our CLI programs to libgobject and creating an object
146 * instance for the signals.
149 cf_callback_t cb_fct;
151 } cf_callback_data_t;
153 static GList *cf_callbacks = NULL;
156 cf_callback_invoke(int event, gpointer data)
158 cf_callback_data_t *cb;
159 GList *cb_item = cf_callbacks;
161 /* there should be at least one interested */
162 g_assert(cb_item != NULL);
164 while(cb_item != NULL) {
166 cb->cb_fct(event, data, cb->user_data);
167 cb_item = g_list_next(cb_item);
173 cf_callback_add(cf_callback_t func, gpointer user_data)
175 cf_callback_data_t *cb;
177 cb = g_malloc(sizeof(cf_callback_data_t));
179 cb->user_data = user_data;
181 cf_callbacks = g_list_append(cf_callbacks, cb);
185 cf_callback_remove(cf_callback_t func)
187 cf_callback_data_t *cb;
188 GList *cb_item = cf_callbacks;
190 while(cb_item != NULL) {
192 if(cb->cb_fct == func) {
193 cf_callbacks = g_list_remove(cf_callbacks, cb);
197 cb_item = g_list_next(cb_item);
200 g_assert_not_reached();
204 cf_timestamp_auto_precision(capture_file *cf)
207 int prec = timestamp_get_precision();
210 /* don't try to get the file's precision if none is opened */
211 if(cf->state == FILE_CLOSED) {
215 /* if we are in auto mode, set precision of current file */
216 if(prec == TS_PREC_AUTO ||
217 prec == TS_PREC_AUTO_SEC ||
218 prec == TS_PREC_AUTO_DSEC ||
219 prec == TS_PREC_AUTO_CSEC ||
220 prec == TS_PREC_AUTO_MSEC ||
221 prec == TS_PREC_AUTO_USEC ||
222 prec == TS_PREC_AUTO_NSEC)
224 switch(wtap_file_tsprecision(cf->wth)) {
225 case(WTAP_FILE_TSPREC_SEC):
226 timestamp_set_precision(TS_PREC_AUTO_SEC);
228 case(WTAP_FILE_TSPREC_DSEC):
229 timestamp_set_precision(TS_PREC_AUTO_DSEC);
231 case(WTAP_FILE_TSPREC_CSEC):
232 timestamp_set_precision(TS_PREC_AUTO_CSEC);
234 case(WTAP_FILE_TSPREC_MSEC):
235 timestamp_set_precision(TS_PREC_AUTO_MSEC);
237 case(WTAP_FILE_TSPREC_USEC):
238 timestamp_set_precision(TS_PREC_AUTO_USEC);
240 case(WTAP_FILE_TSPREC_NSEC):
241 timestamp_set_precision(TS_PREC_AUTO_NSEC);
244 g_assert_not_reached();
247 /* Set the column widths of those columns that show the time in
248 "command-line-specified" format. */
249 for (i = 0; i < cf->cinfo.num_cols; i++) {
250 if (col_has_time_fmt(&cf->cinfo, i)) {
251 new_packet_list_resize_column(i);
257 cf_get_computed_elapsed(void)
259 return computed_elapsed;
262 static void reset_elapsed(void)
264 computed_elapsed = 0;
267 static void compute_elapsed(GTimeVal *start_time)
272 g_get_current_time(&time_now);
274 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
275 time_now.tv_usec - start_time->tv_usec;
277 computed_elapsed = (gulong) (delta_time / 1000); /* ms*/
281 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
286 wth = wtap_open_offline(fname, err, &err_info, TRUE);
290 /* The open succeeded. Close whatever capture file we had open,
291 and fill in the information for this file. */
294 /* Cleanup all data structures used for dissection. */
295 cleanup_dissection();
296 /* Initialize all data structures used for dissection. */
299 /* We're about to start reading the file. */
300 cf->state = FILE_READ_IN_PROGRESS;
305 /* Set the file name because we need it to set the follow stream filter.
306 XXX - is that still true? We need it for other reasons, though,
308 cf->filename = g_strdup(fname);
310 /* Indicate whether it's a permanent or temporary file. */
311 cf->is_tempfile = is_tempfile;
313 /* If it's a temporary capture buffer file, mark it as not saved. */
314 cf->user_saved = !is_tempfile;
318 cf->cd_t = wtap_file_type(cf->wth);
320 cf->displayed_count = 0;
321 cf->marked_count = 0;
322 cf->ignored_count = 0;
323 cf->ref_time_count = 0;
324 cf->drops_known = FALSE;
326 cf->snap = wtap_snapshot_length(cf->wth);
328 /* Snapshot length not known. */
329 cf->has_snap = FALSE;
330 cf->snap = WTAP_MAX_PACKET_SIZE;
334 /* Allocate a frame_data_sequence for the frames in this file */
335 cf->frames = new_frame_data_sequence();
337 nstime_set_zero(&cf->elapsed_time);
338 nstime_set_unset(&first_ts);
339 nstime_set_unset(&prev_dis_ts);
340 nstime_set_unset(&prev_cap_ts);
343 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
344 cf_timestamp_auto_precision(cf);
346 new_packet_list_queue_draw();
347 fileset_file_opened(fname);
349 if(cf->cd_t == WTAP_FILE_BER) {
350 /* tell the BER dissector the file name */
351 ber_set_filename(cf->filename);
354 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
355 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
360 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
366 * Reset the state for the currently closed file, but don't do the
367 * UI callbacks; this is for use in "cf_open()", where we don't
368 * want the UI to go from "file open" to "file closed" back to
369 * "file open", we want it to go from "old file open" to "new file
370 * open and being read".
373 cf_reset_state(capture_file *cf)
375 /* Die if we're in the middle of reading a file. */
376 g_assert(cf->state != FILE_READ_IN_PROGRESS);
382 /* We have no file open... */
383 if (cf->filename != NULL) {
384 /* If it's a temporary file, remove it. */
386 ws_unlink(cf->filename);
387 g_free(cf->filename);
390 /* ...which means we have nothing to save. */
391 cf->user_saved = FALSE;
393 dfilter_free(cf->rfcode);
395 if (cf->frames != NULL) {
396 free_frame_data_sequence(cf->frames);
399 #ifdef WANT_PACKET_EDITOR
400 if (cf->edited_frames) {
401 g_tree_destroy(cf->edited_frames);
402 cf->edited_frames = NULL;
405 cf_unselect_packet(cf); /* nothing to select */
406 cf->first_displayed = 0;
407 cf->last_displayed = 0;
409 /* No frames, no frame selected, no field in that frame selected. */
411 cf->current_frame = 0;
413 cf->finfo_selected = NULL;
415 /* Clear the packet list. */
416 new_packet_list_freeze();
417 new_packet_list_clear();
418 new_packet_list_thaw();
421 nstime_set_zero(&cf->elapsed_time);
423 reset_tap_listeners();
425 /* We have no file open. */
426 cf->state = FILE_CLOSED;
428 fileset_file_closed();
431 /* Reset everything to a pristine state */
433 cf_close(capture_file *cf)
435 /* do GUI things even if file is already closed,
436 * e.g. to cleanup things if a capture couldn't be started */
437 cf_callback_invoke(cf_cb_file_closing, cf);
439 /* close things, if not already closed before */
440 if(cf->state != FILE_CLOSED) {
441 color_filters_cleanup();
443 cleanup_dissection();
446 cf_callback_invoke(cf_cb_file_closed, cf);
449 /* an out of memory exception occured, wait for a user button press to exit */
450 static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
456 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
460 progbar_val = (gfloat) file_pos / (gfloat) size;
461 if (progbar_val > 1.0) {
463 /* The file probably grew while we were reading it.
464 * Update file size, and try again.
466 size = wtap_file_size(cf->wth, NULL);
469 progbar_val = (gfloat) file_pos / (gfloat) size;
471 /* If it's still > 1, either "wtap_file_size()" failed (in which
472 * case there's not much we can do about it), or the file
473 * *shrank* (in which case there's not much we can do about
474 * it); just clip the progress value at 1.0.
476 if (progbar_val > 1.0f)
480 g_snprintf(status_str, status_size,
481 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
482 file_pos / 1024, size / 1024);
488 cf_read(capture_file *cf, gboolean from_save)
492 const gchar *name_ptr;
494 char errmsg_errno[1024+1];
497 progdlg_t *volatile progbar = NULL;
499 volatile gint64 size;
500 volatile float progbar_val;
502 gchar status_str[100];
503 volatile gint64 progbar_nextstep;
504 volatile gint64 progbar_quantum;
506 gboolean filtering_tap_listeners;
508 volatile int count = 0;
510 volatile int displayed_once = 0;
514 /* Compile the current display filter.
515 * We assume this will not fail since cf->dfilter is only set in
516 * cf_filter IFF the filter was valid.
518 compiled = dfilter_compile(cf->dfilter, &dfcode);
519 g_assert(!cf->dfilter || (compiled && dfcode));
521 /* Do we have any tap listeners with filters? */
522 filtering_tap_listeners = have_filtering_tap_listeners();
524 /* Get the union of the flags for all tap listeners. */
525 tap_flags = union_of_tap_listener_flags();
527 reset_tap_listeners();
529 name_ptr = get_basename(cf->filename);
531 if (from_save == FALSE)
532 cf_callback_invoke(cf_cb_file_read_started, cf);
534 cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr);
536 /* Find the size of the file. */
537 size = wtap_file_size(cf->wth, NULL);
539 /* Update the progress bar when it gets to this value. */
540 progbar_nextstep = 0;
541 /* When we reach the value that triggers a progress bar update,
542 bump that value by this amount. */
544 progbar_quantum = size/N_PROGBAR_UPDATES;
545 if (progbar_quantum < MIN_QUANTUM)
546 progbar_quantum = MIN_QUANTUM;
549 /* Progress so far. */
552 /* The packet list window will be empty untill the file is completly loaded */
553 new_packet_list_freeze();
556 g_get_current_time(&start_time);
558 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
561 file_pos = wtap_read_so_far(cf->wth);
563 /* Create the progress bar if necessary.
564 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
566 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
567 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
568 if (from_save == FALSE)
569 progbar = delayed_create_progress_dlg("Loading", name_ptr,
570 TRUE, &stop_flag, &start_time, progbar_val);
572 progbar = delayed_create_progress_dlg("Saving", name_ptr,
573 TRUE, &stop_flag, &start_time, progbar_val);
576 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
577 when we update it, we have to run the GTK+ main loop to get it
578 to repaint what's pending, and doing so may involve an "ioctl()"
579 to see if there's any pending input from an X server, and doing
580 that for every packet can be costly, especially on a big file. */
581 if (file_pos >= progbar_nextstep) {
582 if (progbar != NULL) {
583 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
584 /* update the packet bar content on the first run or frequently on very large files */
586 if (progbar_quantum > 500000 || displayed_once == 0) {
587 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
589 packets_bar_update();
592 #endif /* HAVE_LIBPCAP */
593 update_progress_dlg(progbar, progbar_val, status_str);
595 progbar_nextstep += progbar_quantum;
600 /* Well, the user decided to abort the read. He/She will be warned and
601 it might be enough for him/her to work with the already loaded
603 This is especially true for very large capture files, where you don't
604 want to wait loading the whole file (which may last minutes or even
605 hours even on fast machines) just to see that it was the wrong file. */
609 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
611 CATCH(OutOfMemoryError) {
614 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
615 "%sOut Of Memory!%s\n"
617 "Sorry, but Wireshark has to terminate now!\n"
619 "Some infos / workarounds can be found at:\n"
620 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
621 simple_dialog_primary_start(), simple_dialog_primary_end());
622 /* we have to terminate, as we cannot recover from the memory error */
623 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
625 main_window_update();
626 /* XXX - how to avoid a busy wait? */
634 /* Cleanup and release all dfilter resources */
636 dfilter_free(dfcode);
639 /* We're done reading the file; destroy the progress bar if it was created. */
641 destroy_progress_dlg(progbar);
643 /* We're done reading sequentially through the file. */
644 cf->state = FILE_READ_DONE;
646 /* Close the sequential I/O side, to free up memory it requires. */
647 wtap_sequential_close(cf->wth);
649 /* Allow the protocol dissectors to free up memory that they
650 * don't need after the sequential run-through of the packets. */
651 postseq_cleanup_all_protocols();
653 /* compute the time it took to load the file */
654 compute_elapsed(&start_time);
656 /* Set the file encapsulation type now; we don't know what it is until
657 we've looked at all the packets, as we don't know until then whether
658 there's more than one type (and thus whether it's
659 WTAP_ENCAP_PER_PACKET). */
660 cf->lnk_t = wtap_file_encap(cf->wth);
662 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
665 new_packet_list_thaw();
666 if (from_save == FALSE)
667 cf_callback_invoke(cf_cb_file_read_finished, cf);
669 cf_callback_invoke(cf_cb_file_save_finished, cf);
671 /* If we have any displayed packets to select, select the first of those
672 packets by making the first row the selected row. */
673 if (cf->first_displayed != 0){
674 new_packet_list_select_first_row();
678 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
679 "%sFile loading was cancelled!%s\n"
681 "The remaining packets in the file were discarded.\n"
683 "As a lot of packets from the original file will be missing,\n"
684 "remember to be careful when saving the current content to a file.\n",
685 simple_dialog_primary_start(), simple_dialog_primary_end());
686 return CF_READ_ERROR;
690 /* Put up a message box noting that the read failed somewhere along
691 the line. Don't throw out the stuff we managed to read, though,
695 case WTAP_ERR_UNSUPPORTED_ENCAP:
696 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
697 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
700 errmsg = errmsg_errno;
703 case WTAP_ERR_CANT_READ:
704 errmsg = "An attempt to read from the capture file failed for"
705 " some unknown reason.";
708 case WTAP_ERR_SHORT_READ:
709 errmsg = "The capture file appears to have been cut short"
710 " in the middle of a packet.";
713 case WTAP_ERR_BAD_RECORD:
714 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
715 "The capture file appears to be damaged or corrupt.\n(%s)",
718 errmsg = errmsg_errno;
721 case WTAP_ERR_DECOMPRESS:
722 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
723 "The compressed capture file appears to be damaged or corrupt.\n"
726 errmsg = errmsg_errno;
730 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
731 "An error occurred while reading the"
732 " capture file: %s.", wtap_strerror(err));
733 errmsg = errmsg_errno;
736 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
737 return CF_READ_ERROR;
744 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
746 cf_status_t cf_status;
748 cf_status = cf_open(cf, fname, is_tempfile, err);
753 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
755 gint64 data_offset = 0;
757 volatile int newly_displayed_packets = 0;
759 gboolean filtering_tap_listeners;
763 /* Compile the current display filter.
764 * We assume this will not fail since cf->dfilter is only set in
765 * cf_filter IFF the filter was valid.
767 compiled = dfilter_compile(cf->dfilter, &dfcode);
768 g_assert(!cf->dfilter || (compiled && dfcode));
770 /* Do we have any tap listeners with filters? */
771 filtering_tap_listeners = have_filtering_tap_listeners();
773 /* Get the union of the flags for all tap listeners. */
774 tap_flags = union_of_tap_listener_flags();
778 new_packet_list_check_end();
779 /* Don't freeze/thaw the list when doing live capture */
780 /*new_packet_list_freeze();*/
782 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
784 while (to_read != 0) {
785 wtap_cleareof(cf->wth);
786 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
789 if (cf->state == FILE_READ_ABORTED) {
790 /* Well, the user decided to exit Wireshark. Break out of the
791 loop, and let the code below (which is called even if there
792 aren't any packets left to read) exit. */
796 if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
797 data_offset) != -1) {
798 newly_displayed_packets++;
801 CATCH(OutOfMemoryError) {
804 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
805 "%sOut Of Memory!%s\n"
807 "Sorry, but Wireshark has to terminate now!\n"
809 "The capture file is not lost, it can be found at:\n"
812 "Some infos / workarounds can be found at:\n"
813 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
814 simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
815 /* we have to terminate, as we cannot recover from the memory error */
816 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
818 main_window_update();
819 /* XXX - how to avoid a busy wait? */
822 /* Don't freeze/thaw the list when doing live capture */
823 /*new_packet_list_thaw();*/
824 return CF_READ_ABORTED;
830 /* Cleanup and release all dfilter resources */
832 dfilter_free(dfcode);
835 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
836 cf->count, cf->state, *err);*/
838 /* Don't freeze/thaw the list when doing live capture */
839 /*new_packet_list_thaw();*/
840 /* With the new packet list the first packet
841 * isn't automatically selected.
843 if(!cf->current_frame)
844 new_packet_list_select_first_row();
846 /* moving to the end of the packet list - if the user requested so and
847 we have some new packets. */
848 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
849 new_packet_list_moveto_end();
851 if (cf->state == FILE_READ_ABORTED) {
852 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
853 so that our caller can kill off the capture child process;
854 this will cause an EOF on the pipe from the child, so
855 "cf_finish_tail()" will be called, and it will clean up
857 return CF_READ_ABORTED;
858 } else if (*err != 0) {
859 /* We got an error reading the capture file.
860 XXX - pop up a dialog box instead? */
861 g_warning("Error \"%s\" while reading: \"%s\"\n",
862 wtap_strerror(*err), cf->filename);
864 return CF_READ_ERROR;
870 cf_fake_continue_tail(capture_file *cf) {
871 cf->state = FILE_READ_DONE;
875 cf_finish_tail(capture_file *cf, int *err)
880 gboolean filtering_tap_listeners;
884 /* Compile the current display filter.
885 * We assume this will not fail since cf->dfilter is only set in
886 * cf_filter IFF the filter was valid.
888 compiled = dfilter_compile(cf->dfilter, &dfcode);
889 g_assert(!cf->dfilter || (compiled && dfcode));
891 /* Do we have any tap listeners with filters? */
892 filtering_tap_listeners = have_filtering_tap_listeners();
894 /* Get the union of the flags for all tap listeners. */
895 tap_flags = union_of_tap_listener_flags();
897 if(cf->wth == NULL) {
899 return CF_READ_ERROR;
902 new_packet_list_check_end();
903 /* Don't freeze/thaw the list when doing live capture */
904 /*new_packet_list_freeze();*/
906 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
907 if (cf->state == FILE_READ_ABORTED) {
908 /* Well, the user decided to abort the read. Break out of the
909 loop, and let the code below (which is called even if there
910 aren't any packets left to read) exit. */
913 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
916 /* Cleanup and release all dfilter resources */
918 dfilter_free(dfcode);
921 /* Don't freeze/thaw the list when doing live capture */
922 /*new_packet_list_thaw();*/
924 if (cf->state == FILE_READ_ABORTED) {
925 /* Well, the user decided to abort the read. We're only called
926 when the child capture process closes the pipe to us (meaning
927 it's probably exited), so we can just close the capture
928 file; we return CF_READ_ABORTED so our caller can do whatever
929 is appropriate when that happens. */
931 return CF_READ_ABORTED;
934 if (auto_scroll_live && cf->count != 0)
935 new_packet_list_moveto_end();
937 /* We're done reading sequentially through the file. */
938 cf->state = FILE_READ_DONE;
940 /* We're done reading sequentially through the file; close the
941 sequential I/O side, to free up memory it requires. */
942 wtap_sequential_close(cf->wth);
944 /* Allow the protocol dissectors to free up memory that they
945 * don't need after the sequential run-through of the packets. */
946 postseq_cleanup_all_protocols();
948 /* Set the file encapsulation type now; we don't know what it is until
949 we've looked at all the packets, as we don't know until then whether
950 there's more than one type (and thus whether it's
951 WTAP_ENCAP_PER_PACKET). */
952 cf->lnk_t = wtap_file_encap(cf->wth);
955 /* We got an error reading the capture file.
956 XXX - pop up a dialog box? */
957 return CF_READ_ERROR;
962 #endif /* HAVE_LIBPCAP */
965 cf_get_display_name(capture_file *cf)
967 const gchar *displayname;
969 /* Return a name to use in displays */
970 if (!cf->is_tempfile) {
971 /* Get the last component of the file name, and use that. */
973 displayname = get_basename(cf->filename);
975 displayname="(No file)";
978 /* The file we read is a temporary file from a live capture;
979 we don't mention its name. */
981 displayname = cf->source;
983 displayname = "(Untitled)";
989 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
995 cf->source = g_strdup(source);
997 cf->source = g_strdup("");
1001 const gchar *cf_get_tempfile_source(capture_file *cf) {
1009 /* XXX - use a macro instead? */
1011 cf_get_packet_count(capture_file *cf)
1016 /* XXX - use a macro instead? */
1018 cf_set_packet_count(capture_file *cf, int packet_count)
1020 cf->count = packet_count;
1023 /* XXX - use a macro instead? */
1025 cf_is_tempfile(capture_file *cf)
1027 return cf->is_tempfile;
1030 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1032 cf->is_tempfile = is_tempfile;
1036 /* XXX - use a macro instead? */
1037 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1039 cf->drops_known = drops_known;
1042 /* XXX - use a macro instead? */
1043 void cf_set_drops(capture_file *cf, guint32 drops)
1048 /* XXX - use a macro instead? */
1049 gboolean cf_get_drops_known(capture_file *cf)
1051 return cf->drops_known;
1054 /* XXX - use a macro instead? */
1055 guint32 cf_get_drops(capture_file *cf)
1060 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1062 cf->rfcode = rfcode;
1066 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1067 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1069 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1071 gboolean add_to_packet_list)
1073 gboolean create_proto_tree = FALSE;
1078 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1080 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1081 &first_ts, &prev_dis_ts, &prev_cap_ts);
1084 + we have a display filter and are re-applying it;
1085 + we have tap listeners with filters;
1086 + we have tap listeners that require a protocol tree;
1088 allocate a protocol tree root node, so that we'll construct
1089 a protocol tree against which a filter expression can be
1091 if ((dfcode != NULL && refilter) ||
1092 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1093 create_proto_tree = TRUE;
1095 /* Dissect the frame. */
1096 epan_dissect_init(&edt, create_proto_tree, FALSE);
1098 if (dfcode != NULL && refilter) {
1099 epan_dissect_prime_dfilter(&edt, dfcode);
1102 tap_queue_init(&edt);
1103 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1104 tap_push_tapped_queue(&edt);
1106 /* If we have a display filter, apply it if we're refiltering, otherwise
1107 leave the "passed_dfilter" flag alone.
1109 If we don't have a display filter, set "passed_dfilter" to 1. */
1110 if (dfcode != NULL) {
1112 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1115 fdata->flags.passed_dfilter = 1;
1117 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1118 cf->displayed_count++;
1120 if (add_to_packet_list) {
1121 /* We fill the needed columns from new_packet_list */
1122 row = new_packet_list_append(cinfo, fdata, &edt.pi);
1125 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1127 frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1129 /* If we haven't yet seen the first frame, this is it.
1131 XXX - we must do this before we add the row to the display,
1132 as, if the display's GtkCList's selection mode is
1133 GTK_SELECTION_BROWSE, when the first entry is added to it,
1134 "cf_select_packet()" will be called, and it will fetch the row
1135 data for the 0th row, and will get a null pointer rather than
1136 "fdata", as "gtk_clist_append()" won't yet have returned and
1137 thus "gtk_clist_set_row_data()" won't yet have been called.
1139 We thus need to leave behind bread crumbs so that
1140 "cf_select_packet()" can find this frame. See the comment
1141 in "cf_select_packet()". */
1142 if (cf->first_displayed == 0)
1143 cf->first_displayed = fdata->num;
1145 /* This is the last frame we've seen so far. */
1146 cf->last_displayed = fdata->num;
1149 epan_dissect_cleanup(&edt);
1153 /* read in a new packet */
1154 /* returns the row of the new packet in the packet list or -1 if not displayed */
1156 read_packet(capture_file *cf, dfilter_t *dfcode,
1157 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1159 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1160 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1161 const guchar *buf = wtap_buf_ptr(cf->wth);
1168 /* The frame number of this packet is one more than the count of
1169 frames in this packet. */
1170 framenum = cf->count + 1;
1172 frame_data_init(&fdlocal, framenum, phdr, offset, cum_bytes);
1177 epan_dissect_init(&edt, TRUE, FALSE);
1178 epan_dissect_prime_dfilter(&edt, cf->rfcode);
1179 epan_dissect_run(&edt, pseudo_header, buf, &fdlocal, NULL);
1180 passed = dfilter_apply_edt(cf->rfcode, &edt);
1181 epan_dissect_cleanup(&edt);
1185 /* This does a shallow copy of fdlocal, which is good enough. */
1186 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1189 cf->f_datalen = offset + fdlocal.cap_len;
1191 if (!cf->redissecting) {
1192 row = add_packet_to_packet_list(fdata, cf, dfcode,
1193 filtering_tap_listeners, tap_flags,
1194 pseudo_header, buf, TRUE, TRUE);
1202 cf_merge_files(char **out_filenamep, int in_file_count,
1203 char *const *in_filenames, int file_type, gboolean do_append)
1205 merge_in_file_t *in_files;
1211 int open_err, read_err, write_err, close_err;
1215 char errmsg_errno[1024+1];
1217 gboolean got_read_error = FALSE, got_write_error = FALSE;
1219 progdlg_t *progbar = NULL;
1221 gint64 f_len, file_pos;
1223 GTimeVal start_time;
1224 gchar status_str[100];
1225 gint64 progbar_nextstep;
1226 gint64 progbar_quantum;
1228 /* open the input files */
1229 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1230 &open_err, &err_info, &err_fileno)) {
1232 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1237 if (*out_filenamep != NULL) {
1238 out_filename = *out_filenamep;
1239 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1243 out_fd = create_tempfile(&tmpname, "wireshark");
1246 out_filename = g_strdup(tmpname);
1247 *out_filenamep = out_filename;
1251 merge_close_in_files(in_file_count, in_files);
1253 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1257 pdh = wtap_dump_fdopen(out_fd, file_type,
1258 merge_select_frame_type(in_file_count, in_files),
1259 merge_max_snapshot_length(in_file_count, in_files),
1260 FALSE /* compressed */, &open_err);
1263 merge_close_in_files(in_file_count, in_files);
1265 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1270 /* Get the sum of the sizes of all the files. */
1272 for (i = 0; i < in_file_count; i++)
1273 f_len += in_files[i].size;
1275 /* Update the progress bar when it gets to this value. */
1276 progbar_nextstep = 0;
1277 /* When we reach the value that triggers a progress bar update,
1278 bump that value by this amount. */
1279 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1280 /* Progress so far. */
1284 g_get_current_time(&start_time);
1286 /* do the merge (or append) */
1289 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1292 wth = merge_read_packet(in_file_count, in_files, &read_err,
1296 got_read_error = TRUE;
1300 /* Get the sum of the data offsets in all of the files. */
1302 for (i = 0; i < in_file_count; i++)
1303 data_offset += in_files[i].data_offset;
1305 /* Create the progress bar if necessary.
1306 We check on every iteration of the loop, so that it takes no
1307 longer than the standard time to create it (otherwise, for a
1308 large file, we might take considerably longer than that standard
1309 time in order to get to the next progress bar step). */
1310 if (progbar == NULL) {
1311 progbar = delayed_create_progress_dlg("Merging", "files",
1312 FALSE, &stop_flag, &start_time, progbar_val);
1315 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1316 when we update it, we have to run the GTK+ main loop to get it
1317 to repaint what's pending, and doing so may involve an "ioctl()"
1318 to see if there's any pending input from an X server, and doing
1319 that for every packet can be costly, especially on a big file. */
1320 if (data_offset >= progbar_nextstep) {
1321 /* Get the sum of the seek positions in all of the files. */
1323 for (i = 0; i < in_file_count; i++)
1324 file_pos += wtap_read_so_far(in_files[i].wth);
1325 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1326 if (progbar_val > 1.0f) {
1327 /* Some file probably grew while we were reading it.
1328 That "shouldn't happen", so we'll just clip the progress
1332 if (progbar != NULL) {
1333 g_snprintf(status_str, sizeof(status_str),
1334 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1335 file_pos / 1024, f_len / 1024);
1336 update_progress_dlg(progbar, progbar_val, status_str);
1338 progbar_nextstep += progbar_quantum;
1342 /* Well, the user decided to abort the merge. */
1346 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1347 wtap_buf_ptr(wth), &write_err)) {
1348 got_write_error = TRUE;
1353 /* We're done merging the files; destroy the progress bar if it was created. */
1354 if (progbar != NULL)
1355 destroy_progress_dlg(progbar);
1357 merge_close_in_files(in_file_count, in_files);
1358 if (!got_read_error && !got_write_error) {
1359 if (!wtap_dump_close(pdh, &write_err))
1360 got_write_error = TRUE;
1362 wtap_dump_close(pdh, &close_err);
1364 if (got_read_error) {
1366 * Find the file on which we got the error, and report the error.
1368 for (i = 0; i < in_file_count; i++) {
1369 if (in_files[i].state == GOT_ERROR) {
1370 /* Put up a message box noting that a read failed somewhere along
1374 case WTAP_ERR_UNSUPPORTED_ENCAP:
1375 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1376 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1379 errmsg = errmsg_errno;
1382 case WTAP_ERR_CANT_READ:
1383 errmsg = "An attempt to read from the capture file %s failed for"
1384 " some unknown reason.";
1387 case WTAP_ERR_SHORT_READ:
1388 errmsg = "The capture file %s appears to have been cut short"
1389 " in the middle of a packet.";
1392 case WTAP_ERR_BAD_RECORD:
1393 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1394 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1397 errmsg = errmsg_errno;
1400 case WTAP_ERR_DECOMPRESS:
1401 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1402 "The compressed capture file %%s appears to be damaged or corrupt.\n"
1405 errmsg = errmsg_errno;
1409 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1410 "An error occurred while reading the"
1411 " capture file %%s: %s.", wtap_strerror(read_err));
1412 errmsg = errmsg_errno;
1415 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
1420 if (got_write_error) {
1421 /* Put up an alert box for the write error. */
1422 cf_write_failure_alert_box(out_filename, write_err);
1425 if (got_read_error || got_write_error || stop_flag) {
1426 /* Callers aren't expected to treat an error or an explicit abort
1427 differently - we put up error dialogs ourselves, so they don't
1435 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1437 const char *filter_new = dftext ? dftext : "";
1438 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1440 GTimeVal start_time;
1442 /* if new filter equals old one, do nothing unless told to do so */
1443 if (!force && strcmp(filter_new, filter_old) == 0) {
1449 if (dftext == NULL) {
1450 /* The new filter is an empty filter (i.e., display all packets).
1451 * so leave dfcode==NULL
1455 * We have a filter; make a copy of it (as we'll be saving it),
1456 * and try to compile it.
1458 dftext = g_strdup(dftext);
1459 if (!dfilter_compile(dftext, &dfcode)) {
1460 /* The attempt failed; report an error. */
1461 gchar *safe_dftext = simple_dialog_format_message(dftext);
1462 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1464 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1467 "The following display filter isn't a valid display filter:\n%s\n"
1468 "See the help for a description of the display filter syntax.",
1469 simple_dialog_primary_start(), safe_dfilter_error_msg,
1470 simple_dialog_primary_end(), safe_dftext);
1471 g_free(safe_dfilter_error_msg);
1472 g_free(safe_dftext);
1478 if (dfcode == NULL) {
1479 /* Yes - free the filter text, and set it to null. */
1485 /* We have a valid filter. Replace the current filter. */
1486 g_free(cf->dfilter);
1487 cf->dfilter = dftext;
1488 g_get_current_time(&start_time);
1491 /* Now rescan the packet list, applying the new filter, but not
1492 throwing away information constructed on a previous pass. */
1493 if (dftext == NULL) {
1494 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1496 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1499 /* Cleanup and release all dfilter resources */
1500 dfilter_free(dfcode);
1506 cf_reftime_packets(capture_file *cf)
1509 ref_time_packets(cf);
1513 cf_redissect_packets(capture_file *cf)
1515 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1519 cf_read_frame_r(capture_file *cf, frame_data *fdata,
1520 union wtap_pseudo_header *pseudo_header, guint8 *pd)
1524 char errmsg_errno[1024+1];
1526 #ifdef WANT_PACKET_EDITOR
1527 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1528 if (G_UNLIKELY(fdata->file_off == -1)) {
1529 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1532 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "fdata->file_off == -1, but can't find modified frame!");
1536 *pseudo_header = frame->ph;
1537 memcpy(pd, frame->pd, fdata->cap_len);
1542 if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
1543 fdata->cap_len, &err, &err_info)) {
1546 case WTAP_ERR_UNSUPPORTED_ENCAP:
1547 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1548 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1553 case WTAP_ERR_BAD_RECORD:
1554 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1555 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
1556 wtap_strerror(err), err_info);
1561 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1562 "An error occurred while reading from the file \"%%s\": %s.",
1563 wtap_strerror(err));
1566 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg_errno, cf->filename);
1573 cf_read_frame(capture_file *cf, frame_data *fdata)
1575 return cf_read_frame_r(cf, fdata, &cf->pseudo_header, cf->pd);
1578 /* Rescan the list of packets, reconstructing the CList.
1580 "action" describes why we're doing this; it's used in the progress
1583 "action_item" describes what we're doing; it's used in the progress
1586 "refilter" is TRUE if we need to re-evaluate the filter expression.
1588 "redissect" is TRUE if we need to make the dissectors reconstruct
1589 any state information they have (because a preference that affects
1590 some dissector has changed, meaning some dissector might construct
1591 its state differently from the way it was constructed the last time). */
1593 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1594 gboolean refilter, gboolean redissect)
1596 /* Rescan packets new packet list */
1599 progdlg_t *progbar = NULL;
1602 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1603 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1604 gboolean selected_frame_seen;
1606 GTimeVal start_time;
1607 gchar status_str[100];
1608 int progbar_nextstep;
1609 int progbar_quantum;
1611 gboolean filtering_tap_listeners;
1613 gboolean add_to_packet_list = FALSE;
1616 /* Compile the current display filter.
1617 * We assume this will not fail since cf->dfilter is only set in
1618 * cf_filter IFF the filter was valid.
1620 compiled = dfilter_compile(cf->dfilter, &dfcode);
1621 g_assert(!cf->dfilter || (compiled && dfcode));
1623 /* Do we have any tap listeners with filters? */
1624 filtering_tap_listeners = have_filtering_tap_listeners();
1626 /* Get the union of the flags for all tap listeners. */
1627 tap_flags = union_of_tap_listener_flags();
1629 reset_tap_listeners();
1630 /* Which frame, if any, is the currently selected frame?
1631 XXX - should the selected frame or the focus frame be the "current"
1632 frame, that frame being the one from which "Find Frame" searches
1634 selected_frame = cf->current_frame;
1636 /* Mark frame num as not found */
1637 selected_frame_num = -1;
1639 /* Freeze the packet list while we redo it, so we don't get any
1640 screen updates while it happens. */
1641 new_packet_list_freeze();
1644 /* We need to re-initialize all the state information that protocols
1645 keep, because some preference that controls a dissector has changed,
1646 which might cause the state information to be constructed differently
1647 by that dissector. */
1649 /* We might receive new packets while redissecting, and we don't
1650 want to dissect those before their time. */
1651 cf->redissecting = TRUE;
1653 /* Cleanup all data structures used for dissection. */
1654 cleanup_dissection();
1655 /* Initialize all data structures used for dissection. */
1658 /* We need to redissect the packets so we have to discard our old
1659 * packet list store. */
1660 new_packet_list_clear();
1661 add_to_packet_list = TRUE;
1664 /* We don't yet know which will be the first and last frames displayed. */
1665 cf->first_displayed = 0;
1666 cf->last_displayed = 0;
1668 /* We currently don't display any packets */
1669 cf->displayed_count = 0;
1671 /* Iterate through the list of frames. Call a routine for each frame
1672 to check whether it should be displayed and, if so, add it to
1673 the display list. */
1674 nstime_set_unset(&first_ts);
1675 nstime_set_unset(&prev_dis_ts);
1676 nstime_set_unset(&prev_cap_ts);
1679 /* Update the progress bar when it gets to this value. */
1680 progbar_nextstep = 0;
1681 /* When we reach the value that triggers a progress bar update,
1682 bump that value by this amount. */
1683 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1684 /* Count of packets at which we've looked. */
1686 /* Progress so far. */
1690 g_get_current_time(&start_time);
1692 /* no previous row yet */
1693 prev_frame_num = -1;
1696 preceding_frame_num = -1;
1697 preceding_frame = NULL;
1698 following_frame_num = -1;
1699 following_frame = NULL;
1701 selected_frame_seen = FALSE;
1703 for (framenum = 1; framenum <= cf->count; framenum++) {
1704 fdata = frame_data_sequence_find(cf->frames, framenum);
1706 /* Create the progress bar if necessary.
1707 We check on every iteration of the loop, so that it takes no
1708 longer than the standard time to create it (otherwise, for a
1709 large file, we might take considerably longer than that standard
1710 time in order to get to the next progress bar step). */
1711 if (progbar == NULL)
1712 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1713 &stop_flag, &start_time,
1716 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1717 when we update it, we have to run the GTK+ main loop to get it
1718 to repaint what's pending, and doing so may involve an "ioctl()"
1719 to see if there's any pending input from an X server, and doing
1720 that for every packet can be costly, especially on a big file. */
1721 if (count >= progbar_nextstep) {
1722 /* let's not divide by zero. I should never be started
1723 * with count == 0, so let's assert that
1725 g_assert(cf->count > 0);
1726 progbar_val = (gfloat) count / cf->count;
1728 if (progbar != NULL) {
1729 g_snprintf(status_str, sizeof(status_str),
1730 "%4u of %u frames", count, cf->count);
1731 update_progress_dlg(progbar, progbar_val, status_str);
1734 progbar_nextstep += progbar_quantum;
1738 /* Well, the user decided to abort the filtering. Just stop.
1740 XXX - go back to the previous filter? Users probably just
1741 want not to wait for a filtering operation to finish;
1742 unless we cancel by having no filter, reverting to the
1743 previous filter will probably be even more expensive than
1744 continuing the filtering, as it involves going back to the
1745 beginning and filtering, and even with no filter we currently
1746 have to re-generate the entire clist, which is also expensive.
1748 I'm not sure what Network Monitor does, but it doesn't appear
1749 to give you an unfiltered display if you cancel. */
1756 /* Since all state for the frame was destroyed, mark the frame
1757 * as not visited, free the GSList referring to the state
1758 * data (the per-frame data itself was freed by
1759 * "init_dissection()"), and null out the GSList pointer. */
1760 fdata->flags.visited = 0;
1761 frame_data_cleanup(fdata);
1764 if (!cf_read_frame(cf, fdata))
1765 break; /* error reading the frame */
1767 /* If the previous frame is displayed, and we haven't yet seen the
1768 selected frame, remember that frame - it's the closest one we've
1769 yet seen before the selected frame. */
1770 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1771 preceding_frame_num = prev_frame_num;
1772 preceding_frame = prev_frame;
1774 add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1775 tap_flags, &cf->pseudo_header, cf->pd,
1777 add_to_packet_list);
1779 /* If this frame is displayed, and this is the first frame we've
1780 seen displayed after the selected frame, remember this frame -
1781 it's the closest one we've yet seen at or after the selected
1783 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1784 following_frame_num = fdata->num;
1785 following_frame = fdata;
1787 if (fdata == selected_frame) {
1788 selected_frame_seen = TRUE;
1789 if (fdata->flags.passed_dfilter)
1790 selected_frame_num = fdata->num;
1793 /* Remember this frame - it'll be the previous frame
1794 on the next pass through the loop. */
1795 prev_frame_num = fdata->num;
1799 /* We are done redissecting the packet list. */
1800 cf->redissecting = FALSE;
1803 /* Clear out what remains of the visited flags and per-frame data
1806 XXX - that may cause various forms of bogosity when dissecting
1807 these frames, as they won't have been seen by this sequential
1808 pass, but the only alternative I see is to keep scanning them
1809 even though the user requested that the scan stop, and that
1810 would leave the user stuck with an Wireshark grinding on
1811 until it finishes. Should we just stick them with that? */
1812 for (; framenum <= cf->count; framenum++) {
1813 fdata = frame_data_sequence_find(cf->frames, framenum);
1814 fdata->flags.visited = 0;
1815 frame_data_cleanup(fdata);
1819 /* We're done filtering the packets; destroy the progress bar if it
1821 if (progbar != NULL)
1822 destroy_progress_dlg(progbar);
1824 /* Unfreeze the packet list. */
1825 if (!add_to_packet_list)
1826 new_packet_list_recreate_visible_rows();
1828 /* Compute the time it took to filter the file */
1829 compute_elapsed(&start_time);
1831 new_packet_list_thaw();
1833 if (selected_frame_num == -1) {
1834 /* The selected frame didn't pass the filter. */
1835 if (selected_frame == NULL) {
1836 /* That's because there *was* no selected frame. Make the first
1837 displayed frame the current frame. */
1838 selected_frame_num = 0;
1840 /* Find the nearest displayed frame to the selected frame (whether
1841 it's before or after that frame) and make that the current frame.
1842 If the next and previous displayed frames are equidistant from the
1843 selected frame, choose the next one. */
1844 g_assert(following_frame == NULL ||
1845 following_frame->num >= selected_frame->num);
1846 g_assert(preceding_frame == NULL ||
1847 preceding_frame->num <= selected_frame->num);
1848 if (following_frame == NULL) {
1849 /* No frame after the selected frame passed the filter, so we
1850 have to select the last displayed frame before the selected
1852 selected_frame_num = preceding_frame_num;
1853 selected_frame = preceding_frame;
1854 } else if (preceding_frame == NULL) {
1855 /* No frame before the selected frame passed the filter, so we
1856 have to select the first displayed frame after the selected
1858 selected_frame_num = following_frame_num;
1859 selected_frame = following_frame;
1861 /* Frames before and after the selected frame passed the filter, so
1862 we'll select the previous frame */
1863 selected_frame_num = preceding_frame_num;
1864 selected_frame = preceding_frame;
1869 if (selected_frame_num == -1) {
1870 /* There are no frames displayed at all. */
1871 cf_unselect_packet(cf);
1873 /* Either the frame that was selected passed the filter, or we've
1874 found the nearest displayed frame to that frame. Select it, make
1875 it the focus row, and make it visible. */
1876 /* Set to invalid to force update of packet list and packet details */
1877 cf->current_row = -1;
1878 if (selected_frame_num == 0) {
1879 new_packet_list_select_first_row();
1881 if (!new_packet_list_select_row_from_data(selected_frame)) {
1882 /* We didn't find a row corresponding to this frame.
1883 This means that the frame isn't being displayed currently,
1884 so we can't select it. */
1885 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
1886 "%sEnd of capture exceeded!%s\n\n"
1887 "The capture file is probably not fully dissected.",
1888 simple_dialog_primary_start(), simple_dialog_primary_end());
1893 /* Cleanup and release all dfilter resources */
1894 dfilter_free(dfcode);
1899 * Scan trough all frame data and recalculate the ref time
1900 * without rereading the file.
1901 * XXX - do we need a progres bar or is this fast enough?
1904 ref_time_packets(capture_file *cf)
1909 nstime_set_unset(&first_ts);
1910 nstime_set_unset(&prev_dis_ts);
1913 for (framenum = 1; framenum <= cf->count; framenum++) {
1914 fdata = frame_data_sequence_find(cf->frames, framenum);
1916 /* just add some value here until we know if it is being displayed or not */
1917 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1923 /* If we don't have the time stamp of the first packet in the
1924 capture, it's because this is the first packet. Save the time
1925 stamp of this packet as the time stamp of the first packet. */
1926 if (nstime_is_unset(&first_ts)) {
1927 first_ts = fdata->abs_ts;
1929 /* if this frames is marked as a reference time frame, reset
1930 firstsec and firstusec to this frame */
1931 if(fdata->flags.ref_time){
1932 first_ts = fdata->abs_ts;
1935 /* If we don't have the time stamp of the previous displayed packet,
1936 it's because this is the first displayed packet. Save the time
1937 stamp of this packet as the time stamp of the previous displayed
1939 if (nstime_is_unset(&prev_dis_ts)) {
1940 prev_dis_ts = fdata->abs_ts;
1943 /* Get the time elapsed between the first packet and this packet. */
1944 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
1946 /* If it's greater than the current elapsed time, set the elapsed time
1947 to it (we check for "greater than" so as not to be confused by
1948 time moving backwards). */
1949 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
1950 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
1951 cf->elapsed_time = fdata->rel_ts;
1954 /* Get the time elapsed between the previous displayed packet and
1956 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
1958 prev_dis_ts = fdata->abs_ts;
1963 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
1964 /* This frame either passed the display filter list or is marked as
1965 a time reference frame. All time reference frames are displayed
1966 even if they dont pass the display filter */
1967 if(fdata->flags.ref_time){
1968 /* if this was a TIME REF frame we should reset the cum_bytes field */
1969 cum_bytes = fdata->pkt_len;
1970 fdata->cum_bytes = cum_bytes;
1972 /* increase cum_bytes with this packets length */
1973 cum_bytes += fdata->pkt_len;
1986 process_specified_packets(capture_file *cf, packet_range_t *range,
1987 const char *string1, const char *string2, gboolean terminate_is_stop,
1988 gboolean (*callback)(capture_file *, frame_data *,
1989 union wtap_pseudo_header *, const guint8 *, void *),
1990 void *callback_args)
1994 union wtap_pseudo_header pseudo_header;
1995 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1996 psp_return_t ret = PSP_FINISHED;
1998 progdlg_t *progbar = NULL;
2001 gboolean progbar_stop_flag;
2002 GTimeVal progbar_start_time;
2003 gchar progbar_status_str[100];
2004 int progbar_nextstep;
2005 int progbar_quantum;
2006 range_process_e process_this;
2008 /* Update the progress bar when it gets to this value. */
2009 progbar_nextstep = 0;
2010 /* When we reach the value that triggers a progress bar update,
2011 bump that value by this amount. */
2012 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2013 /* Count of packets at which we've looked. */
2015 /* Progress so far. */
2018 progbar_stop_flag = FALSE;
2019 g_get_current_time(&progbar_start_time);
2021 packet_range_process_init(range);
2023 /* Iterate through all the packets, printing the packets that
2024 were selected by the current display filter. */
2025 for (framenum = 1; framenum <= cf->count; framenum++) {
2026 fdata = frame_data_sequence_find(cf->frames, framenum);
2028 /* Create the progress bar if necessary.
2029 We check on every iteration of the loop, so that it takes no
2030 longer than the standard time to create it (otherwise, for a
2031 large file, we might take considerably longer than that standard
2032 time in order to get to the next progress bar step). */
2033 if (progbar == NULL)
2034 progbar = delayed_create_progress_dlg(string1, string2,
2037 &progbar_start_time,
2040 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2041 when we update it, we have to run the GTK+ main loop to get it
2042 to repaint what's pending, and doing so may involve an "ioctl()"
2043 to see if there's any pending input from an X server, and doing
2044 that for every packet can be costly, especially on a big file. */
2045 if (progbar_count >= progbar_nextstep) {
2046 /* let's not divide by zero. I should never be started
2047 * with count == 0, so let's assert that
2049 g_assert(cf->count > 0);
2050 progbar_val = (gfloat) progbar_count / cf->count;
2052 if (progbar != NULL) {
2053 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2054 "%4u of %u packets", progbar_count, cf->count);
2055 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2058 progbar_nextstep += progbar_quantum;
2061 if (progbar_stop_flag) {
2062 /* Well, the user decided to abort the operation. Just stop,
2063 and arrange to return PSP_STOPPED to our caller, so they know
2064 it was stopped explicitly. */
2071 /* do we have to process this packet? */
2072 process_this = packet_range_process_packet(range, fdata);
2073 if (process_this == range_process_next) {
2074 /* this packet uninteresting, continue with next one */
2076 } else if (process_this == range_processing_finished) {
2077 /* all interesting packets processed, stop the loop */
2081 /* Get the packet */
2082 if (!cf_read_frame_r(cf, fdata, &pseudo_header, pd)) {
2083 /* Attempt to get the packet failed. */
2087 /* Process the packet */
2088 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
2089 /* Callback failed. We assume it reported the error appropriately. */
2095 /* We're done printing the packets; destroy the progress bar if
2097 if (progbar != NULL)
2098 destroy_progress_dlg(progbar);
2104 gboolean construct_protocol_tree;
2106 } retap_callback_args_t;
2109 retap_packet(capture_file *cf _U_, frame_data *fdata,
2110 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2113 retap_callback_args_t *args = argsp;
2116 epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
2117 tap_queue_init(&edt);
2118 epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
2119 tap_push_tapped_queue(&edt);
2120 epan_dissect_cleanup(&edt);
2126 cf_retap_packets(capture_file *cf)
2128 packet_range_t range;
2129 retap_callback_args_t callback_args;
2130 gboolean filtering_tap_listeners;
2133 /* Do we have any tap listeners with filters? */
2134 filtering_tap_listeners = have_filtering_tap_listeners();
2136 tap_flags = union_of_tap_listener_flags();
2138 /* If any tap listeners have filters, or require the protocol tree,
2139 construct the protocol tree. */
2140 callback_args.construct_protocol_tree = filtering_tap_listeners ||
2141 (tap_flags & TL_REQUIRES_PROTO_TREE);
2143 /* If any tap listeners require the columns, construct them. */
2144 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2146 /* Reset the tap listeners. */
2147 reset_tap_listeners();
2149 /* Iterate through the list of packets, dissecting all packets and
2150 re-running the taps. */
2151 packet_range_init(&range);
2152 packet_range_process_init(&range);
2153 switch (process_specified_packets(cf, &range, "Recalculating statistics on",
2154 "all packets", TRUE, retap_packet,
2157 /* Completed successfully. */
2161 /* Well, the user decided to abort the refiltering.
2162 Return CF_READ_ABORTED so our caller knows they did that. */
2163 return CF_READ_ABORTED;
2166 /* Error while retapping. */
2167 return CF_READ_ERROR;
2170 g_assert_not_reached();
2175 print_args_t *print_args;
2176 gboolean print_header_line;
2177 char *header_line_buf;
2178 int header_line_buf_len;
2179 gboolean print_formfeed;
2180 gboolean print_separator;
2184 } print_callback_args_t;
2187 print_packet(capture_file *cf, frame_data *fdata,
2188 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2191 print_callback_args_t *args = argsp;
2198 gboolean proto_tree_needed;
2199 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2200 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2202 /* Create the protocol tree, and make it visible, if we're printing
2203 the dissection or the hex data.
2204 XXX - do we need it if we're just printing the hex data? */
2206 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2207 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2209 /* Fill in the column information if we're printing the summary
2211 if (args->print_args->print_summary) {
2212 col_custom_prime_edt(&edt, &cf->cinfo);
2213 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2214 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2216 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2218 if (args->print_formfeed) {
2219 if (!new_page(args->print_args->stream))
2222 if (args->print_separator) {
2223 if (!print_line(args->print_args->stream, 0, ""))
2229 * We generate bookmarks, if the output format supports them.
2230 * The name is "__frameN__".
2232 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2234 if (args->print_args->print_summary) {
2235 if (args->print_header_line) {
2236 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2238 args->print_header_line = FALSE; /* we might not need to print any more */
2240 cp = &args->line_buf[0];
2242 for (i = 0; i < cf->cinfo.num_cols; i++) {
2243 /* Find the length of the string for this column. */
2244 column_len = (int) strlen(cf->cinfo.col_data[i]);
2245 if (args->col_widths[i] > column_len)
2246 column_len = args->col_widths[i];
2248 /* Make sure there's room in the line buffer for the column; if not,
2249 double its length. */
2250 line_len += column_len + 1; /* "+1" for space */
2251 if (line_len > args->line_buf_len) {
2252 cp_off = (int) (cp - args->line_buf);
2253 args->line_buf_len = 2 * line_len;
2254 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2255 cp = args->line_buf + cp_off;
2258 /* Right-justify the packet number column. */
2259 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2260 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
2262 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
2264 if (i != cf->cinfo.num_cols - 1)
2270 * Generate a bookmark, using the summary line as the title.
2272 if (!print_bookmark(args->print_args->stream, bookmark_name,
2276 if (!print_line(args->print_args->stream, 0, args->line_buf))
2280 * Generate a bookmark, using "Frame N" as the title, as we're not
2281 * printing the summary line.
2283 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2284 if (!print_bookmark(args->print_args->stream, bookmark_name,
2287 } /* if (print_summary) */
2289 if (args->print_args->print_dissections != print_dissections_none) {
2290 if (args->print_args->print_summary) {
2291 /* Separate the summary line from the tree with a blank line. */
2292 if (!print_line(args->print_args->stream, 0, ""))
2296 /* Print the information in that tree. */
2297 if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
2300 /* Print a blank line if we print anything after this (aka more than one packet). */
2301 args->print_separator = TRUE;
2303 /* Print a header line if we print any more packet summaries */
2304 args->print_header_line = TRUE;
2307 if (args->print_args->print_hex) {
2308 /* Print the full packet data as hex. */
2309 if (!print_hex_data(args->print_args->stream, &edt))
2312 /* Print a blank line if we print anything after this (aka more than one packet). */
2313 args->print_separator = TRUE;
2315 /* Print a header line if we print any more packet summaries */
2316 args->print_header_line = TRUE;
2317 } /* if (args->print_args->print_dissections != print_dissections_none) */
2319 epan_dissect_cleanup(&edt);
2321 /* do we want to have a formfeed between each packet from now on? */
2322 if(args->print_args->print_formfeed) {
2323 args->print_formfeed = TRUE;
2329 epan_dissect_cleanup(&edt);
2334 cf_print_packets(capture_file *cf, print_args_t *print_args)
2337 print_callback_args_t callback_args;
2345 callback_args.print_args = print_args;
2346 callback_args.print_header_line = TRUE;
2347 callback_args.header_line_buf = NULL;
2348 callback_args.header_line_buf_len = 256;
2349 callback_args.print_formfeed = FALSE;
2350 callback_args.print_separator = FALSE;
2351 callback_args.line_buf = NULL;
2352 callback_args.line_buf_len = 256;
2353 callback_args.col_widths = NULL;
2355 if (!print_preamble(print_args->stream, cf->filename)) {
2356 destroy_print_stream(print_args->stream);
2357 return CF_PRINT_WRITE_ERROR;
2360 if (print_args->print_summary) {
2361 /* We're printing packet summaries. Allocate the header line buffer
2362 and get the column widths. */
2363 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2365 /* Find the widths for each of the columns - maximum of the
2366 width of the title and the width of the data - and construct
2367 a buffer with a line containing the column titles. */
2368 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2369 cp = &callback_args.header_line_buf[0];
2371 for (i = 0; i < cf->cinfo.num_cols; i++) {
2372 /* Don't pad the last column. */
2373 if (i == cf->cinfo.num_cols - 1)
2374 callback_args.col_widths[i] = 0;
2376 callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
2377 data_width = get_column_char_width(get_column_format(i));
2378 if (data_width > callback_args.col_widths[i])
2379 callback_args.col_widths[i] = data_width;
2382 /* Find the length of the string for this column. */
2383 column_len = (int) strlen(cf->cinfo.col_title[i]);
2384 if (callback_args.col_widths[i] > column_len)
2385 column_len = callback_args.col_widths[i];
2387 /* Make sure there's room in the line buffer for the column; if not,
2388 double its length. */
2389 line_len += column_len + 1; /* "+1" for space */
2390 if (line_len > callback_args.header_line_buf_len) {
2391 cp_off = (int) (cp - callback_args.header_line_buf);
2392 callback_args.header_line_buf_len = 2 * line_len;
2393 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2394 callback_args.header_line_buf_len + 1);
2395 cp = callback_args.header_line_buf + cp_off;
2398 /* Right-justify the packet number column. */
2399 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2400 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2402 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2404 if (i != cf->cinfo.num_cols - 1)
2409 /* Now start out the main line buffer with the same length as the
2410 header line buffer. */
2411 callback_args.line_buf_len = callback_args.header_line_buf_len;
2412 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2413 } /* if (print_summary) */
2415 /* Iterate through the list of packets, printing the packets we were
2417 ret = process_specified_packets(cf, &print_args->range, "Printing",
2418 "selected packets", TRUE, print_packet,
2421 g_free(callback_args.header_line_buf);
2422 g_free(callback_args.line_buf);
2423 g_free(callback_args.col_widths);
2428 /* Completed successfully. */
2432 /* Well, the user decided to abort the printing.
2434 XXX - note that what got generated before they did that
2435 will get printed if we're piping to a print program; we'd
2436 have to write to a file and then hand that to the print
2437 program to make it actually not print anything. */
2441 /* Error while printing.
2443 XXX - note that what got generated before they did that
2444 will get printed if we're piping to a print program; we'd
2445 have to write to a file and then hand that to the print
2446 program to make it actually not print anything. */
2447 destroy_print_stream(print_args->stream);
2448 return CF_PRINT_WRITE_ERROR;
2451 if (!print_finale(print_args->stream)) {
2452 destroy_print_stream(print_args->stream);
2453 return CF_PRINT_WRITE_ERROR;
2456 if (!destroy_print_stream(print_args->stream))
2457 return CF_PRINT_WRITE_ERROR;
2463 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2464 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2470 /* Create the protocol tree, but don't fill in the column information. */
2471 epan_dissect_init(&edt, TRUE, TRUE);
2472 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2474 /* Write out the information in that tree. */
2475 proto_tree_write_pdml(&edt, fh);
2477 epan_dissect_cleanup(&edt);
2483 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2488 fh = ws_fopen(print_args->file, "w");
2490 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2492 write_pdml_preamble(fh, cf->filename);
2495 return CF_PRINT_WRITE_ERROR;
2498 /* Iterate through the list of packets, printing the packets we were
2500 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2501 "selected packets", TRUE,
2502 write_pdml_packet, fh);
2507 /* Completed successfully. */
2511 /* Well, the user decided to abort the printing. */
2515 /* Error while printing. */
2517 return CF_PRINT_WRITE_ERROR;
2520 write_pdml_finale(fh);
2523 return CF_PRINT_WRITE_ERROR;
2526 /* XXX - check for an error */
2533 write_psml_packet(capture_file *cf, frame_data *fdata,
2534 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2539 gboolean proto_tree_needed;
2541 /* Fill in the column information, only create the protocol tree
2542 if having custom columns. */
2543 proto_tree_needed = have_custom_cols(&cf->cinfo);
2544 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2545 col_custom_prime_edt(&edt, &cf->cinfo);
2546 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2547 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2549 /* Write out the information in that tree. */
2550 proto_tree_write_psml(&edt, fh);
2552 epan_dissect_cleanup(&edt);
2558 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2563 fh = ws_fopen(print_args->file, "w");
2565 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2567 write_psml_preamble(fh);
2570 return CF_PRINT_WRITE_ERROR;
2573 /* Iterate through the list of packets, printing the packets we were
2575 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2576 "selected packets", TRUE,
2577 write_psml_packet, fh);
2582 /* Completed successfully. */
2586 /* Well, the user decided to abort the printing. */
2590 /* Error while printing. */
2592 return CF_PRINT_WRITE_ERROR;
2595 write_psml_finale(fh);
2598 return CF_PRINT_WRITE_ERROR;
2601 /* XXX - check for an error */
2608 write_csv_packet(capture_file *cf, frame_data *fdata,
2609 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2614 gboolean proto_tree_needed;
2616 /* Fill in the column information, only create the protocol tree
2617 if having custom columns. */
2618 proto_tree_needed = have_custom_cols(&cf->cinfo);
2619 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2620 col_custom_prime_edt(&edt, &cf->cinfo);
2621 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2622 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2624 /* Write out the information in that tree. */
2625 proto_tree_write_csv(&edt, fh);
2627 epan_dissect_cleanup(&edt);
2633 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2638 fh = ws_fopen(print_args->file, "w");
2640 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2642 write_csv_preamble(fh);
2645 return CF_PRINT_WRITE_ERROR;
2648 /* Iterate through the list of packets, printing the packets we were
2650 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2651 "selected packets", TRUE,
2652 write_csv_packet, fh);
2657 /* Completed successfully. */
2661 /* Well, the user decided to abort the printing. */
2665 /* Error while printing. */
2667 return CF_PRINT_WRITE_ERROR;
2670 write_csv_finale(fh);
2673 return CF_PRINT_WRITE_ERROR;
2676 /* XXX - check for an error */
2683 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
2684 union wtap_pseudo_header *pseudo_header _U_,
2685 const guint8 *pd, void *argsp)
2689 proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh);
2694 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2699 fh = ws_fopen(print_args->file, "w");
2702 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2704 write_carrays_preamble(fh);
2708 return CF_PRINT_WRITE_ERROR;
2711 /* Iterate through the list of packets, printing the packets we were
2713 ret = process_specified_packets(cf, &print_args->range,
2715 "selected packets", TRUE,
2716 write_carrays_packet, fh);
2719 /* Completed successfully. */
2722 /* Well, the user decided to abort the printing. */
2725 /* Error while printing. */
2727 return CF_PRINT_WRITE_ERROR;
2730 write_carrays_finale(fh);
2734 return CF_PRINT_WRITE_ERROR;
2742 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2743 search_direction dir)
2747 mdata.string = string;
2748 mdata.string_len = strlen(string);
2749 return find_packet(cf, match_protocol_tree, &mdata, dir);
2753 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2755 mdata->frame_matched = FALSE;
2756 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2757 mdata->string_len = strlen(mdata->string);
2759 /* Iterate through all the nodes looking for matching text */
2760 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2761 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2765 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2767 match_data *mdata = criterion;
2770 /* Load the frame's data. */
2771 if (!cf_read_frame(cf, fdata)) {
2772 /* Attempt to get the packet failed. */
2776 /* Construct the protocol tree, including the displayed text */
2777 epan_dissect_init(&edt, TRUE, TRUE);
2778 /* We don't need the column information */
2779 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2781 /* Iterate through all the nodes, seeing if they have text that matches. */
2783 mdata->frame_matched = FALSE;
2784 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2785 epan_dissect_cleanup(&edt);
2786 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2790 match_subtree_text(proto_node *node, gpointer data)
2792 match_data *mdata = (match_data*) data;
2793 const gchar *string = mdata->string;
2794 size_t string_len = mdata->string_len;
2795 capture_file *cf = mdata->cf;
2796 field_info *fi = PNODE_FINFO(node);
2797 gchar label_str[ITEM_LABEL_LENGTH];
2804 g_assert(fi && "dissection with an invisible proto tree?");
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;
2842 /* Recurse into the subtree, if it exists */
2843 if (node->first_child != NULL)
2844 proto_tree_children_foreach(node, match_subtree_text, mdata);
2848 cf_find_packet_summary_line(capture_file *cf, const char *string,
2849 search_direction dir)
2853 mdata.string = string;
2854 mdata.string_len = strlen(string);
2855 return find_packet(cf, match_summary_line, &mdata, dir);
2859 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2861 match_data *mdata = criterion;
2862 const gchar *string = mdata->string;
2863 size_t string_len = mdata->string_len;
2865 const char *info_column;
2866 size_t info_column_len;
2867 match_result result = MR_NOTMATCHED;
2873 /* Load the frame's data. */
2874 if (!cf_read_frame(cf, fdata)) {
2875 /* Attempt to get the packet failed. */
2879 /* Don't bother constructing the protocol tree */
2880 epan_dissect_init(&edt, FALSE, FALSE);
2881 /* Get the column information */
2882 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2884 /* Find the Info column */
2885 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2886 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2887 /* Found it. See if we match. */
2888 info_column = edt.pi.cinfo->col_data[colx];
2889 info_column_len = strlen(info_column);
2890 for (i = 0; i < info_column_len; i++) {
2891 c_char = info_column[i];
2893 c_char = toupper(c_char);
2894 if (c_char == string[c_match]) {
2896 if (c_match == string_len) {
2897 result = MR_MATCHED;
2906 epan_dissect_cleanup(&edt);
2913 } cbs_t; /* "Counted byte string" */
2916 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
2917 search_direction dir)
2922 info.data_len = string_size;
2924 /* String or hex search? */
2926 /* String search - what type of string? */
2927 switch (cf->scs_type) {
2929 case SCS_ASCII_AND_UNICODE:
2930 return find_packet(cf, match_ascii_and_unicode, &info, dir);
2933 return find_packet(cf, match_ascii, &info, dir);
2936 return find_packet(cf, match_unicode, &info, dir);
2939 g_assert_not_reached();
2943 return find_packet(cf, match_binary, &info, dir);
2947 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2949 cbs_t *info = criterion;
2950 const guint8 *ascii_text = info->data;
2951 size_t textlen = info->data_len;
2952 match_result result;
2958 /* Load the frame's data. */
2959 if (!cf_read_frame(cf, fdata)) {
2960 /* Attempt to get the packet failed. */
2964 result = MR_NOTMATCHED;
2965 buf_len = fdata->pkt_len;
2966 for (i = 0; i < buf_len; i++) {
2969 c_char = toupper(c_char);
2971 if (c_char == ascii_text[c_match]) {
2973 if (c_match == textlen) {
2974 result = MR_MATCHED;
2975 cf->search_pos = i; /* Save the position of the last character
2976 for highlighting the field. */
2987 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2989 cbs_t *info = criterion;
2990 const guint8 *ascii_text = info->data;
2991 size_t textlen = info->data_len;
2992 match_result result;
2998 /* Load the frame's data. */
2999 if (!cf_read_frame(cf, fdata)) {
3000 /* Attempt to get the packet failed. */
3004 result = MR_NOTMATCHED;
3005 buf_len = fdata->pkt_len;
3006 for (i = 0; i < buf_len; i++) {
3009 c_char = toupper(c_char);
3010 if (c_char == ascii_text[c_match]) {
3012 if (c_match == textlen) {
3013 result = MR_MATCHED;
3014 cf->search_pos = i; /* Save the position of the last character
3015 for highlighting the field. */
3025 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3027 cbs_t *info = criterion;
3028 const guint8 *ascii_text = info->data;
3029 size_t textlen = info->data_len;
3030 match_result result;
3036 /* Load the frame's data. */
3037 if (!cf_read_frame(cf, fdata)) {
3038 /* Attempt to get the packet failed. */
3042 result = MR_NOTMATCHED;
3043 buf_len = fdata->pkt_len;
3044 for (i = 0; i < buf_len; i++) {
3047 c_char = toupper(c_char);
3048 if (c_char == ascii_text[c_match]) {
3051 if (c_match == textlen) {
3052 result = MR_MATCHED;
3053 cf->search_pos = i; /* Save the position of the last character
3054 for highlighting the field. */
3064 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3066 cbs_t *info = criterion;
3067 const guint8 *binary_data = info->data;
3068 size_t datalen = info->data_len;
3069 match_result result;
3074 /* Load the frame's data. */
3075 if (!cf_read_frame(cf, fdata)) {
3076 /* Attempt to get the packet failed. */
3080 result = MR_NOTMATCHED;
3081 buf_len = fdata->pkt_len;
3082 for (i = 0; i < buf_len; i++) {
3083 if (cf->pd[i] == binary_data[c_match]) {
3085 if (c_match == datalen) {
3086 result = MR_MATCHED;
3087 cf->search_pos = i; /* Save the position of the last character
3088 for highlighting the field. */
3098 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3099 search_direction dir)
3101 return find_packet(cf, match_dfilter, sfcode, dir);
3105 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3106 search_direction dir)
3111 if (!dfilter_compile(filter, &sfcode)) {
3113 * XXX - this shouldn't happen, as the filter string is machine
3118 if (sfcode == NULL) {
3120 * XXX - this shouldn't happen, as the filter string is machine
3125 result = find_packet(cf, match_dfilter, sfcode, dir);
3126 dfilter_free(sfcode);
3131 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3133 dfilter_t *sfcode = criterion;
3135 match_result result;
3137 /* Load the frame's data. */
3138 if (!cf_read_frame(cf, fdata)) {
3139 /* Attempt to get the packet failed. */
3143 epan_dissect_init(&edt, TRUE, FALSE);
3144 epan_dissect_prime_dfilter(&edt, sfcode);
3145 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3146 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3147 epan_dissect_cleanup(&edt);
3152 cf_find_packet_marked(capture_file *cf, search_direction dir)
3154 return find_packet(cf, match_marked, NULL, dir);
3158 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3160 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3164 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3166 return find_packet(cf, match_time_reference, NULL, dir);
3170 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3172 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3176 find_packet(capture_file *cf,
3177 match_result (*match_function)(capture_file *, frame_data *, void *),
3178 void *criterion, search_direction dir)
3180 frame_data *start_fd;
3183 frame_data *new_fd = NULL;
3184 progdlg_t *progbar = NULL;
3189 GTimeVal start_time;
3190 gchar status_str[100];
3191 int progbar_nextstep;
3192 int progbar_quantum;
3194 match_result result;
3196 start_fd = cf->current_frame;
3197 if (start_fd != NULL) {
3198 /* Iterate through the list of packets, starting at the packet we've
3199 picked, calling a routine to run the filter on the packet, see if
3200 it matches, and stop if so. */
3202 framenum = start_fd->num;
3204 /* Update the progress bar when it gets to this value. */
3205 progbar_nextstep = 0;
3206 /* When we reach the value that triggers a progress bar update,
3207 bump that value by this amount. */
3208 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3209 /* Progress so far. */
3213 g_get_current_time(&start_time);
3215 title = cf->sfilter?cf->sfilter:"";
3217 /* Create the progress bar if necessary.
3218 We check on every iteration of the loop, so that it takes no
3219 longer than the standard time to create it (otherwise, for a
3220 large file, we might take considerably longer than that standard
3221 time in order to get to the next progress bar step). */
3222 if (progbar == NULL)
3223 progbar = delayed_create_progress_dlg("Searching", title,
3224 FALSE, &stop_flag, &start_time, progbar_val);
3226 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3227 when we update it, we have to run the GTK+ main loop to get it
3228 to repaint what's pending, and doing so may involve an "ioctl()"
3229 to see if there's any pending input from an X server, and doing
3230 that for every packet can be costly, especially on a big file. */
3231 if (count >= progbar_nextstep) {
3232 /* let's not divide by zero. I should never be started
3233 * with count == 0, so let's assert that
3235 g_assert(cf->count > 0);
3237 progbar_val = (gfloat) count / cf->count;
3239 if (progbar != NULL) {
3240 g_snprintf(status_str, sizeof(status_str),
3241 "%4u of %u packets", count, cf->count);
3242 update_progress_dlg(progbar, progbar_val, status_str);
3245 progbar_nextstep += progbar_quantum;
3249 /* Well, the user decided to abort the search. Go back to the
3250 frame where we started. */
3255 /* Go past the current frame. */
3256 if (dir == SD_BACKWARD) {
3257 /* Go on to the previous frame. */
3258 if (framenum == 1) {
3260 * XXX - other apps have a bit more of a detailed message
3261 * for this, and instead of offering "OK" and "Cancel",
3262 * they offer things such as "Continue" and "Cancel";
3263 * we need an API for popping up alert boxes with
3264 * {Verb} and "Cancel".
3267 if (prefs.gui_find_wrap)
3269 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3270 framenum = cf->count; /* wrap around */
3274 statusbar_push_temporary_msg("Search reached the beginning.");
3275 framenum = start_fd->num; /* stay on previous packet */
3280 /* Go on to the next frame. */
3281 if (framenum == cf->count) {
3282 if (prefs.gui_find_wrap)
3284 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3285 framenum = 1; /* wrap around */
3289 statusbar_push_temporary_msg("Search reached the end.");
3290 framenum = start_fd->num; /* stay on previous packet */
3295 fdata = frame_data_sequence_find(cf->frames, framenum);
3299 /* Is this packet in the display? */
3300 if (fdata->flags.passed_dfilter) {
3301 /* Yes. Does it match the search criterion? */
3302 result = (*match_function)(cf, fdata, criterion);
3303 if (result == MR_ERROR) {
3304 /* Error; our caller has reported the error. Go back to the frame
3305 where we started. */
3308 } else if (result == MR_MATCHED) {
3309 /* Yes. Go to the new frame. */
3315 if (fdata == start_fd) {
3316 /* We're back to the frame we were on originally, and that frame
3317 doesn't match the search filter. The search failed. */
3322 /* We're done scanning the packets; destroy the progress bar if it
3324 if (progbar != NULL)
3325 destroy_progress_dlg(progbar);
3328 if (new_fd != NULL) {
3329 /* Find and select */
3330 cf->search_in_progress = TRUE;
3331 found = new_packet_list_select_row_from_data(new_fd);
3332 cf->search_in_progress = FALSE;
3333 cf->search_pos = 0; /* Reset the position */
3335 /* We didn't find a row corresponding to this frame.
3336 This means that the frame isn't being displayed currently,
3337 so we can't select it. */
3338 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3339 "%sEnd of capture exceeded!%s\n\n"
3340 "The capture file is probably not fully dissected.",
3341 simple_dialog_primary_start(), simple_dialog_primary_end());
3344 return TRUE; /* success */
3346 return FALSE; /* failure */
3350 cf_goto_frame(capture_file *cf, guint fnumber)
3354 fdata = frame_data_sequence_find(cf->frames, fnumber);
3356 if (fdata == NULL) {
3357 /* we didn't find a packet with that packet number */
3358 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3359 return FALSE; /* we failed to go to that packet */
3361 if (!fdata->flags.passed_dfilter) {
3362 /* that packet currently isn't displayed */
3363 /* XXX - add it to the set of displayed packets? */
3364 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3365 return FALSE; /* we failed to go to that packet */
3368 if (!new_packet_list_select_row_from_data(fdata)) {
3369 /* We didn't find a row corresponding to this frame.
3370 This means that the frame isn't being displayed currently,
3371 so we can't select it. */
3372 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3373 "%sEnd of capture exceeded!%s\n\n"
3374 "The capture file is probably not fully dissected.",
3375 simple_dialog_primary_start(), simple_dialog_primary_end());
3378 return TRUE; /* we got to that packet */
3382 cf_goto_top_frame(void)
3384 /* Find and select */
3385 new_packet_list_select_first_row();
3386 return TRUE; /* we got to that packet */
3390 cf_goto_bottom_frame(void)
3392 /* Find and select */
3393 new_packet_list_select_last_row();
3394 return TRUE; /* we got to that packet */
3398 * Go to frame specified by currently selected protocol tree item.
3401 cf_goto_framenum(capture_file *cf)
3403 header_field_info *hfinfo;
3406 if (cf->finfo_selected) {
3407 hfinfo = cf->finfo_selected->hfinfo;
3409 if (hfinfo->type == FT_FRAMENUM) {
3410 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3412 return cf_goto_frame(cf, framenum);
3419 /* Select the packet on a given row. */
3421 cf_select_packet(capture_file *cf, int row)
3425 /* Get the frame data struct pointer for this frame */
3426 fdata = new_packet_list_get_row_data(row);
3428 if (fdata == NULL) {
3429 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3430 the first entry is added to it by "real_insert_row()", that row
3431 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3432 our version and the vanilla GTK+ version).
3434 This means that a "select-row" signal is emitted; this causes
3435 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3438 "cf_select_packet()" fetches, above, the data associated with the
3439 row that was selected; however, as "gtk_clist_append()", which
3440 called "real_insert_row()", hasn't yet returned, we haven't yet
3441 associated any data with that row, so we get back a null pointer.
3443 We can't assume that there's only one frame in the frame list,
3444 either, as we may be filtering the display.
3446 We therefore assume that, if "row" is 0, i.e. the first row
3447 is being selected, and "cf->first_displayed" equals
3448 "cf->last_displayed", i.e. there's only one frame being
3449 displayed, that frame is the frame we want.
3451 This means we have to set "cf->first_displayed" and
3452 "cf->last_displayed" before adding the row to the
3453 GtkCList; see the comment in "add_packet_to_packet_list()". */
3455 if (row == 0 && cf->first_displayed == cf->last_displayed)
3456 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3459 /* If fdata _still_ isn't set simply give up. */
3460 if (fdata == NULL) {
3464 /* Get the data in that frame. */
3465 if (!cf_read_frame (cf, fdata)) {
3469 /* Record that this frame is the current frame. */
3470 cf->current_frame = fdata;
3471 cf->current_row = row;
3473 /* Create the logical protocol tree. */
3474 if (cf->edt != NULL)
3475 epan_dissect_free(cf->edt);
3477 /* We don't need the columns here. */
3478 cf->edt = epan_dissect_new(TRUE, TRUE);
3480 tap_build_interesting(cf->edt);
3481 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3484 dfilter_macro_build_ftv_cache(cf->edt->tree);
3486 cf_callback_invoke(cf_cb_packet_selected, cf);
3489 /* Unselect the selected packet, if any. */
3491 cf_unselect_packet(capture_file *cf)
3493 /* Destroy the epan_dissect_t for the unselected packet. */
3494 if (cf->edt != NULL) {
3495 epan_dissect_free(cf->edt);
3499 /* No packet is selected. */
3500 cf->current_frame = NULL;
3501 cf->current_row = 0;
3503 cf_callback_invoke(cf_cb_packet_unselected, cf);
3505 /* No protocol tree means no selected field. */
3506 cf_unselect_field(cf);
3509 /* Unset the selected protocol tree field, if any. */
3511 cf_unselect_field(capture_file *cf)
3513 cf->finfo_selected = NULL;
3515 cf_callback_invoke(cf_cb_field_unselected, cf);
3519 * Mark a particular frame.
3522 cf_mark_frame(capture_file *cf, frame_data *frame)
3524 if (! frame->flags.marked) {
3525 frame->flags.marked = TRUE;
3526 if (cf->count > cf->marked_count)
3532 * Unmark a particular frame.
3535 cf_unmark_frame(capture_file *cf, frame_data *frame)
3537 if (frame->flags.marked) {
3538 frame->flags.marked = FALSE;
3539 if (cf->marked_count > 0)
3545 * Ignore a particular frame.
3548 cf_ignore_frame(capture_file *cf, frame_data *frame)
3550 if (! frame->flags.ignored) {
3551 frame->flags.ignored = TRUE;
3552 if (cf->count > cf->ignored_count)
3553 cf->ignored_count++;
3558 * Un-ignore a particular frame.
3561 cf_unignore_frame(capture_file *cf, frame_data *frame)
3563 if (frame->flags.ignored) {
3564 frame->flags.ignored = FALSE;
3565 if (cf->ignored_count > 0)
3566 cf->ignored_count--;
3573 } save_callback_args_t;
3576 * Save a capture to a file, in a particular format, saving either
3577 * all packets, all currently-displayed packets, or all marked packets.
3579 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3580 * up a message box for the failure.
3583 save_packet(capture_file *cf _U_, frame_data *fdata,
3584 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3587 save_callback_args_t *args = argsp;
3588 struct wtap_pkthdr hdr;
3591 /* init the wtap header for saving */
3592 hdr.ts.secs = fdata->abs_ts.secs;
3593 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3594 hdr.caplen = fdata->cap_len;
3595 hdr.len = fdata->pkt_len;
3596 hdr.pkt_encap = fdata->lnk_t;
3598 /* and save the packet */
3599 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3600 cf_write_failure_alert_box(args->fname, err);
3607 * Can this capture file be saved in any format except by copying the raw data?
3610 cf_can_save_as(capture_file *cf)
3614 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
3615 /* To save a file with Wiretap, Wiretap has to handle that format,
3616 and its code to handle that format must be able to write a file
3617 with this file's encapsulation type. */
3618 if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
3619 /* OK, we can write it out in this type. */
3624 /* No, we couldn't save it in any format. */
3629 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3631 gchar *from_filename;
3635 save_callback_args_t callback_args;
3637 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
3639 /* don't write over an existing file. */
3640 /* this should've been already checked by our caller, just to be sure... */
3641 if (file_exists(fname)) {
3642 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3643 "%sCapture file: \"%s\" already exists!%s\n\n"
3644 "Please choose a different filename.",
3645 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3649 packet_range_process_init(range);
3651 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3652 /* We're not filtering packets, and we're saving it in the format
3653 it's already in, so we can just move or copy the raw data. */
3655 if (cf->is_tempfile) {
3656 /* The file being saved is a temporary file from a live
3657 capture, so it doesn't need to stay around under that name;
3658 first, try renaming the capture buffer file to the new name. */
3660 if (ws_rename(cf->filename, fname) == 0) {
3661 /* That succeeded - there's no need to copy the source file. */
3662 from_filename = NULL;
3665 if (errno == EXDEV) {
3666 /* They're on different file systems, so we have to copy the
3669 from_filename = cf->filename;
3671 /* The rename failed, but not because they're on different
3672 file systems - put up an error message. (Or should we
3673 just punt and try to copy? The only reason why I'd
3674 expect the rename to fail and the copy to succeed would
3675 be if we didn't have permission to remove the file from
3676 the temporary directory, and that might be fixable - but
3677 is it worth requiring the user to go off and fix it?) */
3678 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3679 file_rename_error_message(errno), fname);
3685 from_filename = cf->filename;
3688 /* It's a permanent file, so we should copy it, and not remove the
3691 from_filename = cf->filename;
3695 /* Copy the file, if we haven't moved it. */
3696 if (!copy_file_binary_mode(from_filename, fname))
3700 /* Either we're filtering packets, or we're saving in a different
3701 format; we can't do that by copying or moving the capture file,
3702 we have to do it by writing the packets out in Wiretap. */
3703 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3706 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3710 /* XXX - we let the user save a subset of the packets.
3712 If we do that, should we make that file the current file? If so,
3713 it means we can no longer get at the other packets. What does
3716 /* Iterate through the list of packets, processing the packets we were
3719 XXX - we've already called "packet_range_process_init(range)", but
3720 "process_specified_packets()" will do it again. Fortunately,
3721 that's harmless in this case, as we haven't done anything to
3722 "range" since we initialized it. */
3723 callback_args.pdh = pdh;
3724 callback_args.fname = fname;
3725 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3726 TRUE, save_packet, &callback_args)) {
3729 /* Completed successfully. */
3733 /* The user decided to abort the saving.
3734 XXX - remove the output file? */
3738 /* Error while saving. */
3739 wtap_dump_close(pdh, &err);
3743 if (!wtap_dump_close(pdh, &err)) {
3744 cf_close_failure_alert_box(fname, err);
3749 cf_callback_invoke(cf_cb_file_save_finished, NULL);
3751 if (packet_range_process_all(range)) {
3752 /* We saved the entire capture, not just some packets from it.
3753 Open and read the file we saved it to.
3755 XXX - this is somewhat of a waste; we already have the
3756 packets, all this gets us is updated file type information
3757 (which we could just stuff into "cf"), and having the new
3758 file be the one we have opened and from which we're reading
3759 the data, and it means we have to spend time opening and
3760 reading the file, which could be a significant amount of
3761 time if the file is large. */
3762 cf->user_saved = TRUE;
3764 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3765 /* XXX - report errors if this fails?
3766 What should we return if it fails or is aborted? */
3768 switch (cf_read(cf, TRUE)) {
3772 /* Just because we got an error, that doesn't mean we were unable
3773 to read any of the file; we handle what we could get from the
3777 case CF_READ_ABORTED:
3778 /* The user bailed out of re-reading the capture file; the
3779 capture file has been closed - just return (without
3780 changing any menu settings; "cf_close()" set them
3781 correctly for the "no capture file open" state). */
3784 cf_callback_invoke(cf_cb_file_save_reload_finished, cf);
3790 cf_callback_invoke(cf_cb_file_save_failed, NULL);
3795 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3796 gboolean for_writing, int file_type)
3799 /* Wiretap error. */
3802 case WTAP_ERR_NOT_REGULAR_FILE:
3803 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3804 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3808 case WTAP_ERR_RANDOM_OPEN_PIPE:
3809 /* Seen only when opening a capture file for reading. */
3810 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3811 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
3815 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3816 /* Seen only when opening a capture file for reading. */
3817 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3818 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
3822 case WTAP_ERR_UNSUPPORTED:
3823 /* Seen only when opening a capture file for reading. */
3824 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3825 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
3827 filename, err_info);
3831 case WTAP_ERR_CANT_WRITE_TO_PIPE:
3832 /* Seen only when opening a capture file for writing. */
3833 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3834 "The file \"%s\" is a pipe, and %s capture files can't be "
3835 "written to a pipe.",
3836 filename, wtap_file_type_string(file_type));
3839 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3840 /* Seen only when opening a capture file for writing. */
3841 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3842 "Wireshark doesn't support writing capture files in that format.");
3845 case WTAP_ERR_UNSUPPORTED_ENCAP:
3847 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3848 "Wireshark can't save this capture in that format.");
3850 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3851 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
3853 filename, err_info);
3858 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3860 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3861 "Wireshark can't save this capture in that format.");
3863 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3864 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
3869 case WTAP_ERR_BAD_RECORD:
3870 /* Seen only when opening a capture file for reading. */
3871 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3872 "The file \"%s\" appears to be damaged or corrupt.\n"
3874 filename, err_info);
3878 case WTAP_ERR_CANT_OPEN:
3880 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3881 "The file \"%s\" could not be created for some unknown reason.",
3884 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3885 "The file \"%s\" could not be opened for some unknown reason.",
3890 case WTAP_ERR_SHORT_READ:
3891 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3892 "The file \"%s\" appears to have been cut short"
3893 " in the middle of a packet or other data.",
3897 case WTAP_ERR_SHORT_WRITE:
3898 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3899 "A full header couldn't be written to the file \"%s\".",
3903 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
3904 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3905 "Gzip compression not supported by this file type.");
3908 case WTAP_ERR_DECOMPRESS:
3909 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3910 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
3911 "(%s)", filename, err_info);
3916 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3917 "The file \"%s\" could not be %s: %s.",
3919 for_writing ? "created" : "opened",
3920 wtap_strerror(err));
3925 open_failure_alert_box(filename, err, for_writing);
3930 file_rename_error_message(int err)
3933 static char errmsg_errno[1024+1];
3938 errmsg = "The path to the file \"%s\" doesn't exist.";
3942 errmsg = "You don't have permission to move the capture file to \"%s\".";
3946 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3947 "The file \"%%s\" could not be moved: %s.",
3948 wtap_strerror(err));
3949 errmsg = errmsg_errno;
3956 cf_write_failure_alert_box(const char *filename, int err)
3959 /* Wiretap error. */
3960 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3961 "An error occurred while writing to the file \"%s\": %s.",
3962 filename, wtap_strerror(err));
3965 write_failure_alert_box(filename, err);
3969 /* Check for write errors - if the file is being written to an NFS server,
3970 a write error may not show up until the file is closed, as NFS clients
3971 might not send writes to the server until the "write()" call finishes,
3972 so that the write may fail on the server but the "write()" may succeed. */
3974 cf_close_failure_alert_box(const char *filename, int err)
3977 /* Wiretap error. */
3980 case WTAP_ERR_CANT_CLOSE:
3981 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3982 "The file \"%s\" couldn't be closed for some unknown reason.",
3986 case WTAP_ERR_SHORT_WRITE:
3987 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3988 "Not all the packets could be written to the file \"%s\".",
3993 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3994 "An error occurred while closing the file \"%s\": %s.",
3995 filename, wtap_strerror(err));
4000 We assume that a close error from the OS is really a write error. */
4001 write_failure_alert_box(filename, err);
4005 /* Reload the current capture file. */
4007 cf_reload(capture_file *cf) {
4009 gboolean is_tempfile;
4012 /* If the file could be opened, "cf_open()" calls "cf_close()"
4013 to get rid of state for the old capture file before filling in state
4014 for the new capture file. "cf_close()" will remove the file if
4015 it's a temporary file; we don't want that to happen (for one thing,
4016 it'd prevent subsequent reopens from working). Remember whether it's
4017 a temporary file, mark it as not being a temporary file, and then
4018 reopen it as the type of file it was.
4020 Also, "cf_close()" will free "cf->filename", so we must make
4021 a copy of it first. */
4022 filename = g_strdup(cf->filename);
4023 is_tempfile = cf->is_tempfile;
4024 cf->is_tempfile = FALSE;
4025 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4026 switch (cf_read(cf, FALSE)) {
4030 /* Just because we got an error, that doesn't mean we were unable
4031 to read any of the file; we handle what we could get from the
4035 case CF_READ_ABORTED:
4036 /* The user bailed out of re-reading the capture file; the
4037 capture file has been closed - just free the capture file name
4038 string and return (without changing the last containing
4044 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4045 Instead, the file was left open, so we should restore "cf->is_tempfile"
4048 XXX - change the menu? Presumably "cf_open()" will do that;
4049 make sure it does! */
4050 cf->is_tempfile = is_tempfile;
4052 /* "cf_open()" made a copy of the file name we handed it, so
4053 we should free up our copy. */
4063 * indent-tabs-mode: nil
4066 * ex: set shiftwidth=2 tabstop=8 expandtab
4067 * :indentSize=2:tabSize=8:noTabs=true: