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_close_failure_alert_box(const char *filename, int err);
130 static void ref_time_packets(capture_file *cf);
131 /* Update the progress bar this many times when reading a file. */
132 #define N_PROGBAR_UPDATES 100
133 /* We read around 200k/100ms don't update the progress bar more often than that */
134 #define MIN_QUANTUM 200000
135 #define MIN_NUMBER_OF_PACKET 1500
137 /* Number of "frame_data" structures per memory chunk.
138 XXX - is this the right number? */
139 #define FRAME_DATA_CHUNK_SIZE 1024
143 * We could probably use g_signal_...() instead of the callbacks below but that
144 * would require linking our CLI programs to libgobject and creating an object
145 * instance for the signals.
148 cf_callback_t cb_fct;
150 } cf_callback_data_t;
152 static GList *cf_callbacks = NULL;
155 cf_callback_invoke(int event, gpointer data)
157 cf_callback_data_t *cb;
158 GList *cb_item = cf_callbacks;
160 /* there should be at least one interested */
161 g_assert(cb_item != NULL);
163 while(cb_item != NULL) {
165 cb->cb_fct(event, data, cb->user_data);
166 cb_item = g_list_next(cb_item);
172 cf_callback_add(cf_callback_t func, gpointer user_data)
174 cf_callback_data_t *cb;
176 cb = g_malloc(sizeof(cf_callback_data_t));
178 cb->user_data = user_data;
180 cf_callbacks = g_list_append(cf_callbacks, cb);
184 cf_callback_remove(cf_callback_t func)
186 cf_callback_data_t *cb;
187 GList *cb_item = cf_callbacks;
189 while(cb_item != NULL) {
191 if(cb->cb_fct == func) {
192 cf_callbacks = g_list_remove(cf_callbacks, cb);
196 cb_item = g_list_next(cb_item);
199 g_assert_not_reached();
203 cf_timestamp_auto_precision(capture_file *cf)
206 int prec = timestamp_get_precision();
209 /* don't try to get the file's precision if none is opened */
210 if(cf->state == FILE_CLOSED) {
214 /* if we are in auto mode, set precision of current file */
215 if(prec == TS_PREC_AUTO ||
216 prec == TS_PREC_AUTO_SEC ||
217 prec == TS_PREC_AUTO_DSEC ||
218 prec == TS_PREC_AUTO_CSEC ||
219 prec == TS_PREC_AUTO_MSEC ||
220 prec == TS_PREC_AUTO_USEC ||
221 prec == TS_PREC_AUTO_NSEC)
223 switch(wtap_file_tsprecision(cf->wth)) {
224 case(WTAP_FILE_TSPREC_SEC):
225 timestamp_set_precision(TS_PREC_AUTO_SEC);
227 case(WTAP_FILE_TSPREC_DSEC):
228 timestamp_set_precision(TS_PREC_AUTO_DSEC);
230 case(WTAP_FILE_TSPREC_CSEC):
231 timestamp_set_precision(TS_PREC_AUTO_CSEC);
233 case(WTAP_FILE_TSPREC_MSEC):
234 timestamp_set_precision(TS_PREC_AUTO_MSEC);
236 case(WTAP_FILE_TSPREC_USEC):
237 timestamp_set_precision(TS_PREC_AUTO_USEC);
239 case(WTAP_FILE_TSPREC_NSEC):
240 timestamp_set_precision(TS_PREC_AUTO_NSEC);
243 g_assert_not_reached();
246 /* Set the column widths of those columns that show the time in
247 "command-line-specified" format. */
248 for (i = 0; i < cf->cinfo.num_cols; i++) {
249 if (col_has_time_fmt(&cf->cinfo, i)) {
250 new_packet_list_resize_column(i);
256 cf_get_computed_elapsed(void)
258 return computed_elapsed;
261 static void reset_elapsed(void)
263 computed_elapsed = 0;
266 static void compute_elapsed(GTimeVal *start_time)
271 g_get_current_time(&time_now);
273 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
274 time_now.tv_usec - start_time->tv_usec;
276 computed_elapsed = (gulong) (delta_time / 1000); /* ms*/
280 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
285 wth = wtap_open_offline(fname, err, &err_info, TRUE);
289 /* The open succeeded. Close whatever capture file we had open,
290 and fill in the information for this file. */
293 /* Cleanup all data structures used for dissection. */
294 cleanup_dissection();
295 /* Initialize all data structures used for dissection. */
298 /* We're about to start reading the file. */
299 cf->state = FILE_READ_IN_PROGRESS;
304 /* Set the file name because we need it to set the follow stream filter.
305 XXX - is that still true? We need it for other reasons, though,
307 cf->filename = g_strdup(fname);
309 /* Indicate whether it's a permanent or temporary file. */
310 cf->is_tempfile = is_tempfile;
312 /* If it's a temporary capture buffer file, mark it as not saved. */
313 cf->user_saved = !is_tempfile;
317 cf->cd_t = wtap_file_type(cf->wth);
319 cf->displayed_count = 0;
320 cf->marked_count = 0;
321 cf->ignored_count = 0;
322 cf->ref_time_count = 0;
323 cf->drops_known = FALSE;
325 cf->snap = wtap_snapshot_length(cf->wth);
327 /* Snapshot length not known. */
328 cf->has_snap = FALSE;
329 cf->snap = WTAP_MAX_PACKET_SIZE;
333 /* Allocate a frame_data_sequence for the frames in this file */
334 cf->frames = new_frame_data_sequence();
336 nstime_set_zero(&cf->elapsed_time);
337 nstime_set_unset(&first_ts);
338 nstime_set_unset(&prev_dis_ts);
339 nstime_set_unset(&prev_cap_ts);
342 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
343 cf_timestamp_auto_precision(cf);
345 new_packet_list_queue_draw();
346 fileset_file_opened(fname);
348 if(cf->cd_t == WTAP_FILE_BER) {
349 /* tell the BER dissector the file name */
350 ber_set_filename(cf->filename);
353 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
354 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
359 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
365 * Reset the state for the currently closed file, but don't do the
366 * UI callbacks; this is for use in "cf_open()", where we don't
367 * want the UI to go from "file open" to "file closed" back to
368 * "file open", we want it to go from "old file open" to "new file
369 * open and being read".
372 cf_reset_state(capture_file *cf)
374 /* Die if we're in the middle of reading a file. */
375 g_assert(cf->state != FILE_READ_IN_PROGRESS);
381 /* We have no file open... */
382 if (cf->filename != NULL) {
383 /* If it's a temporary file, remove it. */
385 ws_unlink(cf->filename);
386 g_free(cf->filename);
389 /* ...which means we have nothing to save. */
390 cf->user_saved = FALSE;
392 dfilter_free(cf->rfcode);
394 if (cf->frames != NULL) {
395 free_frame_data_sequence(cf->frames);
398 #ifdef WANT_PACKET_EDITOR
399 if (cf->edited_frames) {
400 g_tree_destroy(cf->edited_frames);
401 cf->edited_frames = NULL;
404 cf_unselect_packet(cf); /* nothing to select */
405 cf->first_displayed = 0;
406 cf->last_displayed = 0;
408 /* No frames, no frame selected, no field in that frame selected. */
410 cf->current_frame = 0;
412 cf->finfo_selected = NULL;
414 /* Clear the packet list. */
415 new_packet_list_freeze();
416 new_packet_list_clear();
417 new_packet_list_thaw();
420 nstime_set_zero(&cf->elapsed_time);
422 reset_tap_listeners();
424 /* We have no file open. */
425 cf->state = FILE_CLOSED;
427 fileset_file_closed();
430 /* Reset everything to a pristine state */
432 cf_close(capture_file *cf)
434 /* do GUI things even if file is already closed,
435 * e.g. to cleanup things if a capture couldn't be started */
436 cf_callback_invoke(cf_cb_file_closing, cf);
438 /* close things, if not already closed before */
439 if(cf->state != FILE_CLOSED) {
440 color_filters_cleanup();
442 cleanup_dissection();
445 cf_callback_invoke(cf_cb_file_closed, cf);
448 /* an out of memory exception occured, wait for a user button press to exit */
449 static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
455 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
459 progbar_val = (gfloat) file_pos / (gfloat) size;
460 if (progbar_val > 1.0) {
462 /* The file probably grew while we were reading it.
463 * Update file size, and try again.
465 size = wtap_file_size(cf->wth, NULL);
468 progbar_val = (gfloat) file_pos / (gfloat) size;
470 /* If it's still > 1, either "wtap_file_size()" failed (in which
471 * case there's not much we can do about it), or the file
472 * *shrank* (in which case there's not much we can do about
473 * it); just clip the progress value at 1.0.
475 if (progbar_val > 1.0f)
479 g_snprintf(status_str, status_size,
480 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
481 file_pos / 1024, size / 1024);
487 cf_read(capture_file *cf, gboolean from_save)
491 const gchar *name_ptr;
493 char errmsg_errno[1024+1];
496 progdlg_t *volatile progbar = NULL;
498 volatile gint64 size;
499 volatile float progbar_val;
501 gchar status_str[100];
502 volatile gint64 progbar_nextstep;
503 volatile gint64 progbar_quantum;
505 gboolean filtering_tap_listeners;
507 volatile int count = 0;
509 volatile int displayed_once = 0;
513 /* Compile the current display filter.
514 * We assume this will not fail since cf->dfilter is only set in
515 * cf_filter IFF the filter was valid.
517 compiled = dfilter_compile(cf->dfilter, &dfcode);
518 g_assert(!cf->dfilter || (compiled && dfcode));
520 /* Do we have any tap listeners with filters? */
521 filtering_tap_listeners = have_filtering_tap_listeners();
523 /* Get the union of the flags for all tap listeners. */
524 tap_flags = union_of_tap_listener_flags();
526 reset_tap_listeners();
528 name_ptr = get_basename(cf->filename);
530 if (from_save == FALSE)
531 cf_callback_invoke(cf_cb_file_read_started, cf);
533 cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr);
535 /* Find the size of the file. */
536 size = wtap_file_size(cf->wth, NULL);
538 /* Update the progress bar when it gets to this value. */
539 progbar_nextstep = 0;
540 /* When we reach the value that triggers a progress bar update,
541 bump that value by this amount. */
543 progbar_quantum = size/N_PROGBAR_UPDATES;
544 if (progbar_quantum < MIN_QUANTUM)
545 progbar_quantum = MIN_QUANTUM;
548 /* Progress so far. */
551 /* The packet list window will be empty untill the file is completly loaded */
552 new_packet_list_freeze();
555 g_get_current_time(&start_time);
557 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
560 file_pos = wtap_read_so_far(cf->wth);
562 /* Create the progress bar if necessary.
563 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
565 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
566 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
567 if (from_save == FALSE)
568 progbar = delayed_create_progress_dlg("Loading", name_ptr,
569 TRUE, &stop_flag, &start_time, progbar_val);
571 progbar = delayed_create_progress_dlg("Saving", name_ptr,
572 TRUE, &stop_flag, &start_time, progbar_val);
575 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
576 when we update it, we have to run the GTK+ main loop to get it
577 to repaint what's pending, and doing so may involve an "ioctl()"
578 to see if there's any pending input from an X server, and doing
579 that for every packet can be costly, especially on a big file. */
580 if (file_pos >= progbar_nextstep) {
581 if (progbar != NULL) {
582 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
583 /* update the packet bar content on the first run or frequently on very large files */
585 if (progbar_quantum > 500000 || displayed_once == 0) {
586 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
588 packets_bar_update();
591 #endif /* HAVE_LIBPCAP */
592 update_progress_dlg(progbar, progbar_val, status_str);
594 progbar_nextstep += progbar_quantum;
599 /* Well, the user decided to abort the read. He/She will be warned and
600 it might be enough for him/her to work with the already loaded
602 This is especially true for very large capture files, where you don't
603 want to wait loading the whole file (which may last minutes or even
604 hours even on fast machines) just to see that it was the wrong file. */
608 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
610 CATCH(OutOfMemoryError) {
613 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
614 "%sOut Of Memory!%s\n"
616 "Sorry, but Wireshark has to terminate now!\n"
618 "Some infos / workarounds can be found at:\n"
619 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
620 simple_dialog_primary_start(), simple_dialog_primary_end());
621 /* we have to terminate, as we cannot recover from the memory error */
622 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
624 main_window_update();
625 /* XXX - how to avoid a busy wait? */
633 /* Cleanup and release all dfilter resources */
635 dfilter_free(dfcode);
638 /* We're done reading the file; destroy the progress bar if it was created. */
640 destroy_progress_dlg(progbar);
642 /* We're done reading sequentially through the file. */
643 cf->state = FILE_READ_DONE;
645 /* Close the sequential I/O side, to free up memory it requires. */
646 wtap_sequential_close(cf->wth);
648 /* Allow the protocol dissectors to free up memory that they
649 * don't need after the sequential run-through of the packets. */
650 postseq_cleanup_all_protocols();
652 /* compute the time it took to load the file */
653 compute_elapsed(&start_time);
655 /* Set the file encapsulation type now; we don't know what it is until
656 we've looked at all the packets, as we don't know until then whether
657 there's more than one type (and thus whether it's
658 WTAP_ENCAP_PER_PACKET). */
659 cf->lnk_t = wtap_file_encap(cf->wth);
661 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
664 new_packet_list_thaw();
665 if (from_save == FALSE)
666 cf_callback_invoke(cf_cb_file_read_finished, cf);
668 cf_callback_invoke(cf_cb_file_save_finished, cf);
670 /* If we have any displayed packets to select, select the first of those
671 packets by making the first row the selected row. */
672 if (cf->first_displayed != 0){
673 new_packet_list_select_first_row();
677 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
678 "%sFile loading was cancelled!%s\n"
680 "The remaining packets in the file were discarded.\n"
682 "As a lot of packets from the original file will be missing,\n"
683 "remember to be careful when saving the current content to a file.\n",
684 simple_dialog_primary_start(), simple_dialog_primary_end());
685 return CF_READ_ERROR;
689 /* Put up a message box noting that the read failed somewhere along
690 the line. Don't throw out the stuff we managed to read, though,
694 case WTAP_ERR_UNSUPPORTED_ENCAP:
695 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
696 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
699 errmsg = errmsg_errno;
702 case WTAP_ERR_CANT_READ:
703 errmsg = "An attempt to read from the capture file failed for"
704 " some unknown reason.";
707 case WTAP_ERR_SHORT_READ:
708 errmsg = "The capture file appears to have been cut short"
709 " in the middle of a packet.";
712 case WTAP_ERR_BAD_FILE:
713 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
714 "The capture file appears to be damaged or corrupt.\n(%s)",
717 errmsg = errmsg_errno;
720 case WTAP_ERR_DECOMPRESS:
721 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
722 "The compressed capture file appears to be damaged or corrupt.\n"
725 errmsg = errmsg_errno;
729 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
730 "An error occurred while reading the"
731 " capture file: %s.", wtap_strerror(err));
732 errmsg = errmsg_errno;
735 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
736 return CF_READ_ERROR;
743 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
745 cf_status_t cf_status;
747 cf_status = cf_open(cf, fname, is_tempfile, err);
752 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
754 gint64 data_offset = 0;
756 volatile int newly_displayed_packets = 0;
758 gboolean filtering_tap_listeners;
762 /* Compile the current display filter.
763 * We assume this will not fail since cf->dfilter is only set in
764 * cf_filter IFF the filter was valid.
766 compiled = dfilter_compile(cf->dfilter, &dfcode);
767 g_assert(!cf->dfilter || (compiled && dfcode));
769 /* Do we have any tap listeners with filters? */
770 filtering_tap_listeners = have_filtering_tap_listeners();
772 /* Get the union of the flags for all tap listeners. */
773 tap_flags = union_of_tap_listener_flags();
777 new_packet_list_check_end();
778 /* Don't freeze/thaw the list when doing live capture */
779 /*new_packet_list_freeze();*/
781 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
783 while (to_read != 0) {
784 wtap_cleareof(cf->wth);
785 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
788 if (cf->state == FILE_READ_ABORTED) {
789 /* Well, the user decided to exit Wireshark. Break out of the
790 loop, and let the code below (which is called even if there
791 aren't any packets left to read) exit. */
795 if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
796 data_offset) != -1) {
797 newly_displayed_packets++;
800 CATCH(OutOfMemoryError) {
803 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
804 "%sOut Of Memory!%s\n"
806 "Sorry, but Wireshark has to terminate now!\n"
808 "The capture file is not lost, it can be found at:\n"
811 "Some infos / workarounds can be found at:\n"
812 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
813 simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
814 /* we have to terminate, as we cannot recover from the memory error */
815 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
817 main_window_update();
818 /* XXX - how to avoid a busy wait? */
821 /* Don't freeze/thaw the list when doing live capture */
822 /*new_packet_list_thaw();*/
823 return CF_READ_ABORTED;
829 /* Cleanup and release all dfilter resources */
831 dfilter_free(dfcode);
834 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
835 cf->count, cf->state, *err);*/
837 /* Don't freeze/thaw the list when doing live capture */
838 /*new_packet_list_thaw();*/
839 /* With the new packet list the first packet
840 * isn't automatically selected.
842 if(!cf->current_frame)
843 new_packet_list_select_first_row();
845 /* moving to the end of the packet list - if the user requested so and
846 we have some new packets. */
847 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
848 new_packet_list_moveto_end();
850 if (cf->state == FILE_READ_ABORTED) {
851 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
852 so that our caller can kill off the capture child process;
853 this will cause an EOF on the pipe from the child, so
854 "cf_finish_tail()" will be called, and it will clean up
856 return CF_READ_ABORTED;
857 } else if (*err != 0) {
858 /* We got an error reading the capture file.
859 XXX - pop up a dialog box instead? */
860 g_warning("Error \"%s\" while reading: \"%s\"\n",
861 wtap_strerror(*err), cf->filename);
863 return CF_READ_ERROR;
869 cf_fake_continue_tail(capture_file *cf) {
870 cf->state = FILE_READ_DONE;
874 cf_finish_tail(capture_file *cf, int *err)
879 gboolean filtering_tap_listeners;
883 /* Compile the current display filter.
884 * We assume this will not fail since cf->dfilter is only set in
885 * cf_filter IFF the filter was valid.
887 compiled = dfilter_compile(cf->dfilter, &dfcode);
888 g_assert(!cf->dfilter || (compiled && dfcode));
890 /* Do we have any tap listeners with filters? */
891 filtering_tap_listeners = have_filtering_tap_listeners();
893 /* Get the union of the flags for all tap listeners. */
894 tap_flags = union_of_tap_listener_flags();
896 if(cf->wth == NULL) {
898 return CF_READ_ERROR;
901 new_packet_list_check_end();
902 /* Don't freeze/thaw the list when doing live capture */
903 /*new_packet_list_freeze();*/
905 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
906 if (cf->state == FILE_READ_ABORTED) {
907 /* Well, the user decided to abort the read. Break out of the
908 loop, and let the code below (which is called even if there
909 aren't any packets left to read) exit. */
912 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
915 /* Cleanup and release all dfilter resources */
917 dfilter_free(dfcode);
920 /* Don't freeze/thaw the list when doing live capture */
921 /*new_packet_list_thaw();*/
923 if (cf->state == FILE_READ_ABORTED) {
924 /* Well, the user decided to abort the read. We're only called
925 when the child capture process closes the pipe to us (meaning
926 it's probably exited), so we can just close the capture
927 file; we return CF_READ_ABORTED so our caller can do whatever
928 is appropriate when that happens. */
930 return CF_READ_ABORTED;
933 if (auto_scroll_live && cf->count != 0)
934 new_packet_list_moveto_end();
936 /* We're done reading sequentially through the file. */
937 cf->state = FILE_READ_DONE;
939 /* We're done reading sequentially through the file; close the
940 sequential I/O side, to free up memory it requires. */
941 wtap_sequential_close(cf->wth);
943 /* Allow the protocol dissectors to free up memory that they
944 * don't need after the sequential run-through of the packets. */
945 postseq_cleanup_all_protocols();
947 /* Set the file encapsulation type now; we don't know what it is until
948 we've looked at all the packets, as we don't know until then whether
949 there's more than one type (and thus whether it's
950 WTAP_ENCAP_PER_PACKET). */
951 cf->lnk_t = wtap_file_encap(cf->wth);
954 /* We got an error reading the capture file.
955 XXX - pop up a dialog box? */
956 return CF_READ_ERROR;
961 #endif /* HAVE_LIBPCAP */
964 cf_get_display_name(capture_file *cf)
966 const gchar *displayname;
968 /* Return a name to use in displays */
969 if (!cf->is_tempfile) {
970 /* Get the last component of the file name, and use that. */
972 displayname = get_basename(cf->filename);
974 displayname="(No file)";
977 /* The file we read is a temporary file from a live capture;
978 we don't mention its name. */
980 displayname = cf->source;
982 displayname = "(Untitled)";
988 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
994 cf->source = g_strdup(source);
996 cf->source = g_strdup("");
1000 const gchar *cf_get_tempfile_source(capture_file *cf) {
1008 /* XXX - use a macro instead? */
1010 cf_get_packet_count(capture_file *cf)
1015 /* XXX - use a macro instead? */
1017 cf_set_packet_count(capture_file *cf, int packet_count)
1019 cf->count = packet_count;
1022 /* XXX - use a macro instead? */
1024 cf_is_tempfile(capture_file *cf)
1026 return cf->is_tempfile;
1029 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1031 cf->is_tempfile = is_tempfile;
1035 /* XXX - use a macro instead? */
1036 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1038 cf->drops_known = drops_known;
1041 /* XXX - use a macro instead? */
1042 void cf_set_drops(capture_file *cf, guint32 drops)
1047 /* XXX - use a macro instead? */
1048 gboolean cf_get_drops_known(capture_file *cf)
1050 return cf->drops_known;
1053 /* XXX - use a macro instead? */
1054 guint32 cf_get_drops(capture_file *cf)
1059 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1061 cf->rfcode = rfcode;
1065 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1066 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1068 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1070 gboolean add_to_packet_list)
1072 gboolean create_proto_tree = FALSE;
1077 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1079 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1080 &first_ts, &prev_dis_ts, &prev_cap_ts);
1083 + we have a display filter and are re-applying it;
1084 + we have tap listeners with filters;
1085 + we have tap listeners that require a protocol tree;
1087 allocate a protocol tree root node, so that we'll construct
1088 a protocol tree against which a filter expression can be
1090 if ((dfcode != NULL && refilter) ||
1091 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1092 create_proto_tree = TRUE;
1094 /* Dissect the frame. */
1095 epan_dissect_init(&edt, create_proto_tree, FALSE);
1097 if (dfcode != NULL && refilter) {
1098 epan_dissect_prime_dfilter(&edt, dfcode);
1101 tap_queue_init(&edt);
1102 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1103 tap_push_tapped_queue(&edt);
1105 /* If we have a display filter, apply it if we're refiltering, otherwise
1106 leave the "passed_dfilter" flag alone.
1108 If we don't have a display filter, set "passed_dfilter" to 1. */
1109 if (dfcode != NULL) {
1111 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1114 fdata->flags.passed_dfilter = 1;
1116 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1117 cf->displayed_count++;
1119 if (add_to_packet_list) {
1120 /* We fill the needed columns from new_packet_list */
1121 row = new_packet_list_append(cinfo, fdata, &edt.pi);
1124 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1126 frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1128 /* If we haven't yet seen the first frame, this is it.
1130 XXX - we must do this before we add the row to the display,
1131 as, if the display's GtkCList's selection mode is
1132 GTK_SELECTION_BROWSE, when the first entry is added to it,
1133 "cf_select_packet()" will be called, and it will fetch the row
1134 data for the 0th row, and will get a null pointer rather than
1135 "fdata", as "gtk_clist_append()" won't yet have returned and
1136 thus "gtk_clist_set_row_data()" won't yet have been called.
1138 We thus need to leave behind bread crumbs so that
1139 "cf_select_packet()" can find this frame. See the comment
1140 in "cf_select_packet()". */
1141 if (cf->first_displayed == 0)
1142 cf->first_displayed = fdata->num;
1144 /* This is the last frame we've seen so far. */
1145 cf->last_displayed = fdata->num;
1148 epan_dissect_cleanup(&edt);
1152 /* read in a new packet */
1153 /* returns the row of the new packet in the packet list or -1 if not displayed */
1155 read_packet(capture_file *cf, dfilter_t *dfcode,
1156 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1158 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1159 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1160 const guchar *buf = wtap_buf_ptr(cf->wth);
1167 /* The frame number of this packet is one more than the count of
1168 frames in this packet. */
1169 framenum = cf->count + 1;
1171 frame_data_init(&fdlocal, framenum, phdr, offset, cum_bytes);
1176 epan_dissect_init(&edt, TRUE, FALSE);
1177 epan_dissect_prime_dfilter(&edt, cf->rfcode);
1178 epan_dissect_run(&edt, pseudo_header, buf, &fdlocal, NULL);
1179 passed = dfilter_apply_edt(cf->rfcode, &edt);
1180 epan_dissect_cleanup(&edt);
1184 /* This does a shallow copy of fdlocal, which is good enough. */
1185 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1188 cf->f_datalen = offset + fdlocal.cap_len;
1190 if (!cf->redissecting) {
1191 row = add_packet_to_packet_list(fdata, cf, dfcode,
1192 filtering_tap_listeners, tap_flags,
1193 pseudo_header, buf, TRUE, TRUE);
1201 cf_merge_files(char **out_filenamep, int in_file_count,
1202 char *const *in_filenames, int file_type, gboolean do_append)
1204 merge_in_file_t *in_files, *in_file;
1209 int open_err, read_err, write_err, close_err;
1213 char errmsg_errno[1024+1];
1215 gboolean got_read_error = FALSE, got_write_error = FALSE;
1217 progdlg_t *progbar = NULL;
1219 gint64 f_len, file_pos;
1221 GTimeVal start_time;
1222 gchar status_str[100];
1223 gint64 progbar_nextstep;
1224 gint64 progbar_quantum;
1226 /* open the input files */
1227 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1228 &open_err, &err_info, &err_fileno)) {
1230 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1235 if (*out_filenamep != NULL) {
1236 out_filename = *out_filenamep;
1237 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1241 out_fd = create_tempfile(&tmpname, "wireshark");
1244 out_filename = g_strdup(tmpname);
1245 *out_filenamep = out_filename;
1249 merge_close_in_files(in_file_count, in_files);
1251 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1255 pdh = wtap_dump_fdopen(out_fd, file_type,
1256 merge_select_frame_type(in_file_count, in_files),
1257 merge_max_snapshot_length(in_file_count, in_files),
1258 FALSE /* compressed */, &open_err);
1261 merge_close_in_files(in_file_count, in_files);
1263 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1268 /* Get the sum of the sizes of all the files. */
1270 for (i = 0; i < in_file_count; i++)
1271 f_len += in_files[i].size;
1273 /* Update the progress bar when it gets to this value. */
1274 progbar_nextstep = 0;
1275 /* When we reach the value that triggers a progress bar update,
1276 bump that value by this amount. */
1277 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1278 /* Progress so far. */
1282 g_get_current_time(&start_time);
1284 /* do the merge (or append) */
1287 in_file = merge_append_read_packet(in_file_count, in_files, &read_err,
1290 in_file = merge_read_packet(in_file_count, in_files, &read_err,
1292 if (in_file == NULL) {
1297 if (read_err != 0) {
1298 /* I/O error reading from in_file */
1299 got_read_error = TRUE;
1303 /* Get the sum of the data offsets in all of the files. */
1305 for (i = 0; i < in_file_count; i++)
1306 data_offset += in_files[i].data_offset;
1308 /* Create the progress bar if necessary.
1309 We check on every iteration of the loop, so that it takes no
1310 longer than the standard time to create it (otherwise, for a
1311 large file, we might take considerably longer than that standard
1312 time in order to get to the next progress bar step). */
1313 if (progbar == NULL) {
1314 progbar = delayed_create_progress_dlg("Merging", "files",
1315 FALSE, &stop_flag, &start_time, progbar_val);
1318 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1319 when we update it, we have to run the GTK+ main loop to get it
1320 to repaint what's pending, and doing so may involve an "ioctl()"
1321 to see if there's any pending input from an X server, and doing
1322 that for every packet can be costly, especially on a big file. */
1323 if (data_offset >= progbar_nextstep) {
1324 /* Get the sum of the seek positions in all of the files. */
1326 for (i = 0; i < in_file_count; i++)
1327 file_pos += wtap_read_so_far(in_files[i].wth);
1328 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1329 if (progbar_val > 1.0f) {
1330 /* Some file probably grew while we were reading it.
1331 That "shouldn't happen", so we'll just clip the progress
1335 if (progbar != NULL) {
1336 g_snprintf(status_str, sizeof(status_str),
1337 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1338 file_pos / 1024, f_len / 1024);
1339 update_progress_dlg(progbar, progbar_val, status_str);
1341 progbar_nextstep += progbar_quantum;
1345 /* Well, the user decided to abort the merge. */
1349 if (!wtap_dump(pdh, wtap_phdr(in_file->wth), wtap_pseudoheader(in_file->wth),
1350 wtap_buf_ptr(in_file->wth), &write_err)) {
1351 got_write_error = TRUE;
1356 /* We're done merging the files; destroy the progress bar if it was created. */
1357 if (progbar != NULL)
1358 destroy_progress_dlg(progbar);
1360 merge_close_in_files(in_file_count, in_files);
1361 if (!got_read_error && !got_write_error) {
1362 if (!wtap_dump_close(pdh, &write_err))
1363 got_write_error = TRUE;
1365 wtap_dump_close(pdh, &close_err);
1367 if (got_read_error) {
1369 * Find the file on which we got the error, and report the error.
1371 for (i = 0; i < in_file_count; i++) {
1372 if (in_files[i].state == GOT_ERROR) {
1373 /* Put up a message box noting that a read failed somewhere along
1377 case WTAP_ERR_UNSUPPORTED_ENCAP:
1378 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1379 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1382 errmsg = errmsg_errno;
1385 case WTAP_ERR_CANT_READ:
1386 errmsg = "An attempt to read from the capture file %s failed for"
1387 " some unknown reason.";
1390 case WTAP_ERR_SHORT_READ:
1391 errmsg = "The capture file %s appears to have been cut short"
1392 " in the middle of a packet.";
1395 case WTAP_ERR_BAD_FILE:
1396 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1397 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1400 errmsg = errmsg_errno;
1403 case WTAP_ERR_DECOMPRESS:
1404 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1405 "The compressed capture file %%s appears to be damaged or corrupt.\n"
1408 errmsg = errmsg_errno;
1412 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1413 "An error occurred while reading the"
1414 " capture file %%s: %s.", wtap_strerror(read_err));
1415 errmsg = errmsg_errno;
1418 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
1423 if (got_write_error) {
1424 /* Put up an alert box for the write error. */
1425 if (write_err < 0) {
1426 /* Wiretap error. */
1427 switch (write_err) {
1429 case WTAP_ERR_UNSUPPORTED_ENCAP:
1431 * This is a problem with the particular frame we're writing;
1432 * note that, and give the frame number.
1434 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1435 "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.",
1436 in_file->packet_num, in_file->filename,
1437 wtap_file_type_string(file_type));
1441 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1442 "An error occurred while writing to the file \"%s\": %s.",
1443 out_filename, wtap_strerror(write_err));
1448 write_failure_alert_box(out_filename, write_err);
1452 if (got_read_error || got_write_error || stop_flag) {
1453 /* Callers aren't expected to treat an error or an explicit abort
1454 differently - we put up error dialogs ourselves, so they don't
1462 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1464 const char *filter_new = dftext ? dftext : "";
1465 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1467 GTimeVal start_time;
1469 /* if new filter equals old one, do nothing unless told to do so */
1470 if (!force && strcmp(filter_new, filter_old) == 0) {
1476 if (dftext == NULL) {
1477 /* The new filter is an empty filter (i.e., display all packets).
1478 * so leave dfcode==NULL
1482 * We have a filter; make a copy of it (as we'll be saving it),
1483 * and try to compile it.
1485 dftext = g_strdup(dftext);
1486 if (!dfilter_compile(dftext, &dfcode)) {
1487 /* The attempt failed; report an error. */
1488 gchar *safe_dftext = simple_dialog_format_message(dftext);
1489 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1491 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1494 "The following display filter isn't a valid display filter:\n%s\n"
1495 "See the help for a description of the display filter syntax.",
1496 simple_dialog_primary_start(), safe_dfilter_error_msg,
1497 simple_dialog_primary_end(), safe_dftext);
1498 g_free(safe_dfilter_error_msg);
1499 g_free(safe_dftext);
1505 if (dfcode == NULL) {
1506 /* Yes - free the filter text, and set it to null. */
1512 /* We have a valid filter. Replace the current filter. */
1513 g_free(cf->dfilter);
1514 cf->dfilter = dftext;
1515 g_get_current_time(&start_time);
1518 /* Now rescan the packet list, applying the new filter, but not
1519 throwing away information constructed on a previous pass. */
1520 if (dftext == NULL) {
1521 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1523 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1526 /* Cleanup and release all dfilter resources */
1527 dfilter_free(dfcode);
1533 cf_reftime_packets(capture_file *cf)
1536 ref_time_packets(cf);
1540 cf_redissect_packets(capture_file *cf)
1542 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1546 cf_read_frame_r(capture_file *cf, frame_data *fdata,
1547 union wtap_pseudo_header *pseudo_header, guint8 *pd)
1551 char errmsg_errno[1024+1];
1553 #ifdef WANT_PACKET_EDITOR
1554 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1555 if (G_UNLIKELY(fdata->file_off == -1)) {
1556 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1559 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "fdata->file_off == -1, but can't find modified frame!");
1563 *pseudo_header = frame->ph;
1564 memcpy(pd, frame->pd, fdata->cap_len);
1569 if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
1570 fdata->cap_len, &err, &err_info)) {
1573 case WTAP_ERR_UNSUPPORTED_ENCAP:
1574 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1575 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1580 case WTAP_ERR_BAD_FILE:
1581 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1582 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
1583 wtap_strerror(err), err_info);
1588 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1589 "An error occurred while reading from the file \"%%s\": %s.",
1590 wtap_strerror(err));
1593 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg_errno, cf->filename);
1600 cf_read_frame(capture_file *cf, frame_data *fdata)
1602 return cf_read_frame_r(cf, fdata, &cf->pseudo_header, cf->pd);
1605 /* Rescan the list of packets, reconstructing the CList.
1607 "action" describes why we're doing this; it's used in the progress
1610 "action_item" describes what we're doing; it's used in the progress
1613 "refilter" is TRUE if we need to re-evaluate the filter expression.
1615 "redissect" is TRUE if we need to make the dissectors reconstruct
1616 any state information they have (because a preference that affects
1617 some dissector has changed, meaning some dissector might construct
1618 its state differently from the way it was constructed the last time). */
1620 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1621 gboolean refilter, gboolean redissect)
1623 /* Rescan packets new packet list */
1626 progdlg_t *progbar = NULL;
1629 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1630 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1631 gboolean selected_frame_seen;
1633 GTimeVal start_time;
1634 gchar status_str[100];
1635 int progbar_nextstep;
1636 int progbar_quantum;
1638 gboolean filtering_tap_listeners;
1640 gboolean add_to_packet_list = FALSE;
1643 /* Compile the current display filter.
1644 * We assume this will not fail since cf->dfilter is only set in
1645 * cf_filter IFF the filter was valid.
1647 compiled = dfilter_compile(cf->dfilter, &dfcode);
1648 g_assert(!cf->dfilter || (compiled && dfcode));
1650 /* Do we have any tap listeners with filters? */
1651 filtering_tap_listeners = have_filtering_tap_listeners();
1653 /* Get the union of the flags for all tap listeners. */
1654 tap_flags = union_of_tap_listener_flags();
1656 reset_tap_listeners();
1657 /* Which frame, if any, is the currently selected frame?
1658 XXX - should the selected frame or the focus frame be the "current"
1659 frame, that frame being the one from which "Find Frame" searches
1661 selected_frame = cf->current_frame;
1663 /* Mark frame num as not found */
1664 selected_frame_num = -1;
1666 /* Freeze the packet list while we redo it, so we don't get any
1667 screen updates while it happens. */
1668 new_packet_list_freeze();
1671 /* We need to re-initialize all the state information that protocols
1672 keep, because some preference that controls a dissector has changed,
1673 which might cause the state information to be constructed differently
1674 by that dissector. */
1676 /* We might receive new packets while redissecting, and we don't
1677 want to dissect those before their time. */
1678 cf->redissecting = TRUE;
1680 /* Cleanup all data structures used for dissection. */
1681 cleanup_dissection();
1682 /* Initialize all data structures used for dissection. */
1685 /* We need to redissect the packets so we have to discard our old
1686 * packet list store. */
1687 new_packet_list_clear();
1688 add_to_packet_list = TRUE;
1691 /* We don't yet know which will be the first and last frames displayed. */
1692 cf->first_displayed = 0;
1693 cf->last_displayed = 0;
1695 /* We currently don't display any packets */
1696 cf->displayed_count = 0;
1698 /* Iterate through the list of frames. Call a routine for each frame
1699 to check whether it should be displayed and, if so, add it to
1700 the display list. */
1701 nstime_set_unset(&first_ts);
1702 nstime_set_unset(&prev_dis_ts);
1703 nstime_set_unset(&prev_cap_ts);
1706 /* Update the progress bar when it gets to this value. */
1707 progbar_nextstep = 0;
1708 /* When we reach the value that triggers a progress bar update,
1709 bump that value by this amount. */
1710 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1711 /* Count of packets at which we've looked. */
1713 /* Progress so far. */
1717 g_get_current_time(&start_time);
1719 /* no previous row yet */
1720 prev_frame_num = -1;
1723 preceding_frame_num = -1;
1724 preceding_frame = NULL;
1725 following_frame_num = -1;
1726 following_frame = NULL;
1728 selected_frame_seen = FALSE;
1730 for (framenum = 1; framenum <= cf->count; framenum++) {
1731 fdata = frame_data_sequence_find(cf->frames, framenum);
1733 /* Create the progress bar if necessary.
1734 We check on every iteration of the loop, so that it takes no
1735 longer than the standard time to create it (otherwise, for a
1736 large file, we might take considerably longer than that standard
1737 time in order to get to the next progress bar step). */
1738 if (progbar == NULL)
1739 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1740 &stop_flag, &start_time,
1743 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1744 when we update it, we have to run the GTK+ main loop to get it
1745 to repaint what's pending, and doing so may involve an "ioctl()"
1746 to see if there's any pending input from an X server, and doing
1747 that for every packet can be costly, especially on a big file. */
1748 if (count >= progbar_nextstep) {
1749 /* let's not divide by zero. I should never be started
1750 * with count == 0, so let's assert that
1752 g_assert(cf->count > 0);
1753 progbar_val = (gfloat) count / cf->count;
1755 if (progbar != NULL) {
1756 g_snprintf(status_str, sizeof(status_str),
1757 "%4u of %u frames", count, cf->count);
1758 update_progress_dlg(progbar, progbar_val, status_str);
1761 progbar_nextstep += progbar_quantum;
1765 /* Well, the user decided to abort the filtering. Just stop.
1767 XXX - go back to the previous filter? Users probably just
1768 want not to wait for a filtering operation to finish;
1769 unless we cancel by having no filter, reverting to the
1770 previous filter will probably be even more expensive than
1771 continuing the filtering, as it involves going back to the
1772 beginning and filtering, and even with no filter we currently
1773 have to re-generate the entire clist, which is also expensive.
1775 I'm not sure what Network Monitor does, but it doesn't appear
1776 to give you an unfiltered display if you cancel. */
1783 /* Since all state for the frame was destroyed, mark the frame
1784 * as not visited, free the GSList referring to the state
1785 * data (the per-frame data itself was freed by
1786 * "init_dissection()"), and null out the GSList pointer. */
1787 fdata->flags.visited = 0;
1788 frame_data_cleanup(fdata);
1791 if (!cf_read_frame(cf, fdata))
1792 break; /* error reading the frame */
1794 /* If the previous frame is displayed, and we haven't yet seen the
1795 selected frame, remember that frame - it's the closest one we've
1796 yet seen before the selected frame. */
1797 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1798 preceding_frame_num = prev_frame_num;
1799 preceding_frame = prev_frame;
1801 add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1802 tap_flags, &cf->pseudo_header, cf->pd,
1804 add_to_packet_list);
1806 /* If this frame is displayed, and this is the first frame we've
1807 seen displayed after the selected frame, remember this frame -
1808 it's the closest one we've yet seen at or after the selected
1810 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1811 following_frame_num = fdata->num;
1812 following_frame = fdata;
1814 if (fdata == selected_frame) {
1815 selected_frame_seen = TRUE;
1816 if (fdata->flags.passed_dfilter)
1817 selected_frame_num = fdata->num;
1820 /* Remember this frame - it'll be the previous frame
1821 on the next pass through the loop. */
1822 prev_frame_num = fdata->num;
1826 /* We are done redissecting the packet list. */
1827 cf->redissecting = FALSE;
1830 /* Clear out what remains of the visited flags and per-frame data
1833 XXX - that may cause various forms of bogosity when dissecting
1834 these frames, as they won't have been seen by this sequential
1835 pass, but the only alternative I see is to keep scanning them
1836 even though the user requested that the scan stop, and that
1837 would leave the user stuck with an Wireshark grinding on
1838 until it finishes. Should we just stick them with that? */
1839 for (; framenum <= cf->count; framenum++) {
1840 fdata = frame_data_sequence_find(cf->frames, framenum);
1841 fdata->flags.visited = 0;
1842 frame_data_cleanup(fdata);
1846 /* We're done filtering the packets; destroy the progress bar if it
1848 if (progbar != NULL)
1849 destroy_progress_dlg(progbar);
1851 /* Unfreeze the packet list. */
1852 if (!add_to_packet_list)
1853 new_packet_list_recreate_visible_rows();
1855 /* Compute the time it took to filter the file */
1856 compute_elapsed(&start_time);
1858 new_packet_list_thaw();
1860 if (selected_frame_num == -1) {
1861 /* The selected frame didn't pass the filter. */
1862 if (selected_frame == NULL) {
1863 /* That's because there *was* no selected frame. Make the first
1864 displayed frame the current frame. */
1865 selected_frame_num = 0;
1867 /* Find the nearest displayed frame to the selected frame (whether
1868 it's before or after that frame) and make that the current frame.
1869 If the next and previous displayed frames are equidistant from the
1870 selected frame, choose the next one. */
1871 g_assert(following_frame == NULL ||
1872 following_frame->num >= selected_frame->num);
1873 g_assert(preceding_frame == NULL ||
1874 preceding_frame->num <= selected_frame->num);
1875 if (following_frame == NULL) {
1876 /* No frame after the selected frame passed the filter, so we
1877 have to select the last displayed frame before the selected
1879 selected_frame_num = preceding_frame_num;
1880 selected_frame = preceding_frame;
1881 } else if (preceding_frame == NULL) {
1882 /* No frame before the selected frame passed the filter, so we
1883 have to select the first displayed frame after the selected
1885 selected_frame_num = following_frame_num;
1886 selected_frame = following_frame;
1888 /* Frames before and after the selected frame passed the filter, so
1889 we'll select the previous frame */
1890 selected_frame_num = preceding_frame_num;
1891 selected_frame = preceding_frame;
1896 if (selected_frame_num == -1) {
1897 /* There are no frames displayed at all. */
1898 cf_unselect_packet(cf);
1900 /* Either the frame that was selected passed the filter, or we've
1901 found the nearest displayed frame to that frame. Select it, make
1902 it the focus row, and make it visible. */
1903 /* Set to invalid to force update of packet list and packet details */
1904 cf->current_row = -1;
1905 if (selected_frame_num == 0) {
1906 new_packet_list_select_first_row();
1908 if (!new_packet_list_select_row_from_data(selected_frame)) {
1909 /* We didn't find a row corresponding to this frame.
1910 This means that the frame isn't being displayed currently,
1911 so we can't select it. */
1912 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
1913 "%sEnd of capture exceeded!%s\n\n"
1914 "The capture file is probably not fully dissected.",
1915 simple_dialog_primary_start(), simple_dialog_primary_end());
1920 /* Cleanup and release all dfilter resources */
1921 dfilter_free(dfcode);
1926 * Scan trough all frame data and recalculate the ref time
1927 * without rereading the file.
1928 * XXX - do we need a progres bar or is this fast enough?
1931 ref_time_packets(capture_file *cf)
1936 nstime_set_unset(&first_ts);
1937 nstime_set_unset(&prev_dis_ts);
1940 for (framenum = 1; framenum <= cf->count; framenum++) {
1941 fdata = frame_data_sequence_find(cf->frames, framenum);
1943 /* just add some value here until we know if it is being displayed or not */
1944 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1950 /* If we don't have the time stamp of the first packet in the
1951 capture, it's because this is the first packet. Save the time
1952 stamp of this packet as the time stamp of the first packet. */
1953 if (nstime_is_unset(&first_ts)) {
1954 first_ts = fdata->abs_ts;
1956 /* if this frames is marked as a reference time frame, reset
1957 firstsec and firstusec to this frame */
1958 if(fdata->flags.ref_time){
1959 first_ts = fdata->abs_ts;
1962 /* If we don't have the time stamp of the previous displayed packet,
1963 it's because this is the first displayed packet. Save the time
1964 stamp of this packet as the time stamp of the previous displayed
1966 if (nstime_is_unset(&prev_dis_ts)) {
1967 prev_dis_ts = fdata->abs_ts;
1970 /* Get the time elapsed between the first packet and this packet. */
1971 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
1973 /* If it's greater than the current elapsed time, set the elapsed time
1974 to it (we check for "greater than" so as not to be confused by
1975 time moving backwards). */
1976 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
1977 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
1978 cf->elapsed_time = fdata->rel_ts;
1981 /* If this frame is displayed, get the time elapsed between the
1982 previous displayed packet and this packet. */
1983 if( fdata->flags.passed_dfilter ) {
1984 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
1985 prev_dis_ts = fdata->abs_ts;
1991 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
1992 /* This frame either passed the display filter list or is marked as
1993 a time reference frame. All time reference frames are displayed
1994 even if they dont pass the display filter */
1995 if(fdata->flags.ref_time){
1996 /* if this was a TIME REF frame we should reset the cum_bytes field */
1997 cum_bytes = fdata->pkt_len;
1998 fdata->cum_bytes = cum_bytes;
2000 /* increase cum_bytes with this packets length */
2001 cum_bytes += fdata->pkt_len;
2014 process_specified_packets(capture_file *cf, packet_range_t *range,
2015 const char *string1, const char *string2, gboolean terminate_is_stop,
2016 gboolean (*callback)(capture_file *, frame_data *,
2017 union wtap_pseudo_header *, const guint8 *, void *),
2018 void *callback_args)
2022 union wtap_pseudo_header pseudo_header;
2023 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
2024 psp_return_t ret = PSP_FINISHED;
2026 progdlg_t *progbar = NULL;
2029 gboolean progbar_stop_flag;
2030 GTimeVal progbar_start_time;
2031 gchar progbar_status_str[100];
2032 int progbar_nextstep;
2033 int progbar_quantum;
2034 range_process_e process_this;
2036 /* Update the progress bar when it gets to this value. */
2037 progbar_nextstep = 0;
2038 /* When we reach the value that triggers a progress bar update,
2039 bump that value by this amount. */
2040 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2041 /* Count of packets at which we've looked. */
2043 /* Progress so far. */
2046 progbar_stop_flag = FALSE;
2047 g_get_current_time(&progbar_start_time);
2049 packet_range_process_init(range);
2051 /* Iterate through all the packets, printing the packets that
2052 were selected by the current display filter. */
2053 for (framenum = 1; framenum <= cf->count; framenum++) {
2054 fdata = frame_data_sequence_find(cf->frames, framenum);
2056 /* Create the progress bar if necessary.
2057 We check on every iteration of the loop, so that it takes no
2058 longer than the standard time to create it (otherwise, for a
2059 large file, we might take considerably longer than that standard
2060 time in order to get to the next progress bar step). */
2061 if (progbar == NULL)
2062 progbar = delayed_create_progress_dlg(string1, string2,
2065 &progbar_start_time,
2068 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2069 when we update it, we have to run the GTK+ main loop to get it
2070 to repaint what's pending, and doing so may involve an "ioctl()"
2071 to see if there's any pending input from an X server, and doing
2072 that for every packet can be costly, especially on a big file. */
2073 if (progbar_count >= progbar_nextstep) {
2074 /* let's not divide by zero. I should never be started
2075 * with count == 0, so let's assert that
2077 g_assert(cf->count > 0);
2078 progbar_val = (gfloat) progbar_count / cf->count;
2080 if (progbar != NULL) {
2081 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2082 "%4u of %u packets", progbar_count, cf->count);
2083 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2086 progbar_nextstep += progbar_quantum;
2089 if (progbar_stop_flag) {
2090 /* Well, the user decided to abort the operation. Just stop,
2091 and arrange to return PSP_STOPPED to our caller, so they know
2092 it was stopped explicitly. */
2099 /* do we have to process this packet? */
2100 process_this = packet_range_process_packet(range, fdata);
2101 if (process_this == range_process_next) {
2102 /* this packet uninteresting, continue with next one */
2104 } else if (process_this == range_processing_finished) {
2105 /* all interesting packets processed, stop the loop */
2109 /* Get the packet */
2110 if (!cf_read_frame_r(cf, fdata, &pseudo_header, pd)) {
2111 /* Attempt to get the packet failed. */
2115 /* Process the packet */
2116 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
2117 /* Callback failed. We assume it reported the error appropriately. */
2123 /* We're done printing the packets; destroy the progress bar if
2125 if (progbar != NULL)
2126 destroy_progress_dlg(progbar);
2132 gboolean construct_protocol_tree;
2134 } retap_callback_args_t;
2137 retap_packet(capture_file *cf _U_, frame_data *fdata,
2138 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2141 retap_callback_args_t *args = argsp;
2144 epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
2145 tap_queue_init(&edt);
2146 epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
2147 tap_push_tapped_queue(&edt);
2148 epan_dissect_cleanup(&edt);
2154 cf_retap_packets(capture_file *cf)
2156 packet_range_t range;
2157 retap_callback_args_t callback_args;
2158 gboolean filtering_tap_listeners;
2161 /* Do we have any tap listeners with filters? */
2162 filtering_tap_listeners = have_filtering_tap_listeners();
2164 tap_flags = union_of_tap_listener_flags();
2166 /* If any tap listeners have filters, or require the protocol tree,
2167 construct the protocol tree. */
2168 callback_args.construct_protocol_tree = filtering_tap_listeners ||
2169 (tap_flags & TL_REQUIRES_PROTO_TREE);
2171 /* If any tap listeners require the columns, construct them. */
2172 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2174 /* Reset the tap listeners. */
2175 reset_tap_listeners();
2177 /* Iterate through the list of packets, dissecting all packets and
2178 re-running the taps. */
2179 packet_range_init(&range);
2180 packet_range_process_init(&range);
2181 switch (process_specified_packets(cf, &range, "Recalculating statistics on",
2182 "all packets", TRUE, retap_packet,
2185 /* Completed successfully. */
2189 /* Well, the user decided to abort the refiltering.
2190 Return CF_READ_ABORTED so our caller knows they did that. */
2191 return CF_READ_ABORTED;
2194 /* Error while retapping. */
2195 return CF_READ_ERROR;
2198 g_assert_not_reached();
2203 print_args_t *print_args;
2204 gboolean print_header_line;
2205 char *header_line_buf;
2206 int header_line_buf_len;
2207 gboolean print_formfeed;
2208 gboolean print_separator;
2212 } print_callback_args_t;
2215 print_packet(capture_file *cf, frame_data *fdata,
2216 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2219 print_callback_args_t *args = argsp;
2226 gboolean proto_tree_needed;
2227 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2228 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2230 /* Create the protocol tree, and make it visible, if we're printing
2231 the dissection or the hex data.
2232 XXX - do we need it if we're just printing the hex data? */
2234 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2235 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2237 /* Fill in the column information if we're printing the summary
2239 if (args->print_args->print_summary) {
2240 col_custom_prime_edt(&edt, &cf->cinfo);
2241 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2242 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2244 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2246 if (args->print_formfeed) {
2247 if (!new_page(args->print_args->stream))
2250 if (args->print_separator) {
2251 if (!print_line(args->print_args->stream, 0, ""))
2257 * We generate bookmarks, if the output format supports them.
2258 * The name is "__frameN__".
2260 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2262 if (args->print_args->print_summary) {
2263 if (args->print_header_line) {
2264 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2266 args->print_header_line = FALSE; /* we might not need to print any more */
2268 cp = &args->line_buf[0];
2270 for (i = 0; i < cf->cinfo.num_cols; i++) {
2271 /* Find the length of the string for this column. */
2272 column_len = (int) strlen(cf->cinfo.col_data[i]);
2273 if (args->col_widths[i] > column_len)
2274 column_len = args->col_widths[i];
2276 /* Make sure there's room in the line buffer for the column; if not,
2277 double its length. */
2278 line_len += column_len + 1; /* "+1" for space */
2279 if (line_len > args->line_buf_len) {
2280 cp_off = (int) (cp - args->line_buf);
2281 args->line_buf_len = 2 * line_len;
2282 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2283 cp = args->line_buf + cp_off;
2286 /* Right-justify the packet number column. */
2287 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2288 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
2290 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
2292 if (i != cf->cinfo.num_cols - 1)
2298 * Generate a bookmark, using the summary line as the title.
2300 if (!print_bookmark(args->print_args->stream, bookmark_name,
2304 if (!print_line(args->print_args->stream, 0, args->line_buf))
2308 * Generate a bookmark, using "Frame N" as the title, as we're not
2309 * printing the summary line.
2311 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2312 if (!print_bookmark(args->print_args->stream, bookmark_name,
2315 } /* if (print_summary) */
2317 if (args->print_args->print_dissections != print_dissections_none) {
2318 if (args->print_args->print_summary) {
2319 /* Separate the summary line from the tree with a blank line. */
2320 if (!print_line(args->print_args->stream, 0, ""))
2324 /* Print the information in that tree. */
2325 if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
2328 /* Print a blank line if we print anything after this (aka more than one packet). */
2329 args->print_separator = TRUE;
2331 /* Print a header line if we print any more packet summaries */
2332 args->print_header_line = TRUE;
2335 if (args->print_args->print_hex) {
2336 /* Print the full packet data as hex. */
2337 if (!print_hex_data(args->print_args->stream, &edt))
2340 /* Print a blank line if we print anything after this (aka more than one packet). */
2341 args->print_separator = TRUE;
2343 /* Print a header line if we print any more packet summaries */
2344 args->print_header_line = TRUE;
2345 } /* if (args->print_args->print_dissections != print_dissections_none) */
2347 epan_dissect_cleanup(&edt);
2349 /* do we want to have a formfeed between each packet from now on? */
2350 if(args->print_args->print_formfeed) {
2351 args->print_formfeed = TRUE;
2357 epan_dissect_cleanup(&edt);
2362 cf_print_packets(capture_file *cf, print_args_t *print_args)
2365 print_callback_args_t callback_args;
2373 callback_args.print_args = print_args;
2374 callback_args.print_header_line = TRUE;
2375 callback_args.header_line_buf = NULL;
2376 callback_args.header_line_buf_len = 256;
2377 callback_args.print_formfeed = FALSE;
2378 callback_args.print_separator = FALSE;
2379 callback_args.line_buf = NULL;
2380 callback_args.line_buf_len = 256;
2381 callback_args.col_widths = NULL;
2383 if (!print_preamble(print_args->stream, cf->filename)) {
2384 destroy_print_stream(print_args->stream);
2385 return CF_PRINT_WRITE_ERROR;
2388 if (print_args->print_summary) {
2389 /* We're printing packet summaries. Allocate the header line buffer
2390 and get the column widths. */
2391 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2393 /* Find the widths for each of the columns - maximum of the
2394 width of the title and the width of the data - and construct
2395 a buffer with a line containing the column titles. */
2396 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2397 cp = &callback_args.header_line_buf[0];
2399 for (i = 0; i < cf->cinfo.num_cols; i++) {
2400 /* Don't pad the last column. */
2401 if (i == cf->cinfo.num_cols - 1)
2402 callback_args.col_widths[i] = 0;
2404 callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
2405 data_width = get_column_char_width(get_column_format(i));
2406 if (data_width > callback_args.col_widths[i])
2407 callback_args.col_widths[i] = data_width;
2410 /* Find the length of the string for this column. */
2411 column_len = (int) strlen(cf->cinfo.col_title[i]);
2412 if (callback_args.col_widths[i] > column_len)
2413 column_len = callback_args.col_widths[i];
2415 /* Make sure there's room in the line buffer for the column; if not,
2416 double its length. */
2417 line_len += column_len + 1; /* "+1" for space */
2418 if (line_len > callback_args.header_line_buf_len) {
2419 cp_off = (int) (cp - callback_args.header_line_buf);
2420 callback_args.header_line_buf_len = 2 * line_len;
2421 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2422 callback_args.header_line_buf_len + 1);
2423 cp = callback_args.header_line_buf + cp_off;
2426 /* Right-justify the packet number column. */
2427 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2428 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2430 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2432 if (i != cf->cinfo.num_cols - 1)
2437 /* Now start out the main line buffer with the same length as the
2438 header line buffer. */
2439 callback_args.line_buf_len = callback_args.header_line_buf_len;
2440 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2441 } /* if (print_summary) */
2443 /* Iterate through the list of packets, printing the packets we were
2445 ret = process_specified_packets(cf, &print_args->range, "Printing",
2446 "selected packets", TRUE, print_packet,
2449 g_free(callback_args.header_line_buf);
2450 g_free(callback_args.line_buf);
2451 g_free(callback_args.col_widths);
2456 /* Completed successfully. */
2460 /* Well, the user decided to abort the printing.
2462 XXX - note that what got generated before they did that
2463 will get printed if we're piping to a print program; we'd
2464 have to write to a file and then hand that to the print
2465 program to make it actually not print anything. */
2469 /* Error while printing.
2471 XXX - note that what got generated before they did that
2472 will get printed if we're piping to a print program; we'd
2473 have to write to a file and then hand that to the print
2474 program to make it actually not print anything. */
2475 destroy_print_stream(print_args->stream);
2476 return CF_PRINT_WRITE_ERROR;
2479 if (!print_finale(print_args->stream)) {
2480 destroy_print_stream(print_args->stream);
2481 return CF_PRINT_WRITE_ERROR;
2484 if (!destroy_print_stream(print_args->stream))
2485 return CF_PRINT_WRITE_ERROR;
2491 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2492 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2498 /* Create the protocol tree, but don't fill in the column information. */
2499 epan_dissect_init(&edt, TRUE, TRUE);
2500 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2502 /* Write out the information in that tree. */
2503 proto_tree_write_pdml(&edt, fh);
2505 epan_dissect_cleanup(&edt);
2511 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2516 fh = ws_fopen(print_args->file, "w");
2518 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2520 write_pdml_preamble(fh, cf->filename);
2523 return CF_PRINT_WRITE_ERROR;
2526 /* Iterate through the list of packets, printing the packets we were
2528 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2529 "selected packets", TRUE,
2530 write_pdml_packet, fh);
2535 /* Completed successfully. */
2539 /* Well, the user decided to abort the printing. */
2543 /* Error while printing. */
2545 return CF_PRINT_WRITE_ERROR;
2548 write_pdml_finale(fh);
2551 return CF_PRINT_WRITE_ERROR;
2554 /* XXX - check for an error */
2561 write_psml_packet(capture_file *cf, frame_data *fdata,
2562 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2567 gboolean proto_tree_needed;
2569 /* Fill in the column information, only create the protocol tree
2570 if having custom columns. */
2571 proto_tree_needed = have_custom_cols(&cf->cinfo);
2572 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2573 col_custom_prime_edt(&edt, &cf->cinfo);
2574 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2575 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2577 /* Write out the information in that tree. */
2578 proto_tree_write_psml(&edt, fh);
2580 epan_dissect_cleanup(&edt);
2586 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2591 fh = ws_fopen(print_args->file, "w");
2593 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2595 write_psml_preamble(fh);
2598 return CF_PRINT_WRITE_ERROR;
2601 /* Iterate through the list of packets, printing the packets we were
2603 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2604 "selected packets", TRUE,
2605 write_psml_packet, fh);
2610 /* Completed successfully. */
2614 /* Well, the user decided to abort the printing. */
2618 /* Error while printing. */
2620 return CF_PRINT_WRITE_ERROR;
2623 write_psml_finale(fh);
2626 return CF_PRINT_WRITE_ERROR;
2629 /* XXX - check for an error */
2636 write_csv_packet(capture_file *cf, frame_data *fdata,
2637 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2642 gboolean proto_tree_needed;
2644 /* Fill in the column information, only create the protocol tree
2645 if having custom columns. */
2646 proto_tree_needed = have_custom_cols(&cf->cinfo);
2647 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2648 col_custom_prime_edt(&edt, &cf->cinfo);
2649 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2650 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2652 /* Write out the information in that tree. */
2653 proto_tree_write_csv(&edt, fh);
2655 epan_dissect_cleanup(&edt);
2661 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2666 fh = ws_fopen(print_args->file, "w");
2668 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2670 write_csv_preamble(fh);
2673 return CF_PRINT_WRITE_ERROR;
2676 /* Iterate through the list of packets, printing the packets we were
2678 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2679 "selected packets", TRUE,
2680 write_csv_packet, fh);
2685 /* Completed successfully. */
2689 /* Well, the user decided to abort the printing. */
2693 /* Error while printing. */
2695 return CF_PRINT_WRITE_ERROR;
2698 write_csv_finale(fh);
2701 return CF_PRINT_WRITE_ERROR;
2704 /* XXX - check for an error */
2711 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
2712 union wtap_pseudo_header *pseudo_header,
2713 const guint8 *pd, void *argsp)
2718 epan_dissect_init(&edt, TRUE, TRUE);
2719 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2720 proto_tree_write_carrays(fdata->num, fh, &edt);
2721 epan_dissect_cleanup(&edt);
2727 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2732 fh = ws_fopen(print_args->file, "w");
2735 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2737 write_carrays_preamble(fh);
2741 return CF_PRINT_WRITE_ERROR;
2744 /* Iterate through the list of packets, printing the packets we were
2746 ret = process_specified_packets(cf, &print_args->range,
2748 "selected packets", TRUE,
2749 write_carrays_packet, fh);
2752 /* Completed successfully. */
2755 /* Well, the user decided to abort the printing. */
2758 /* Error while printing. */
2760 return CF_PRINT_WRITE_ERROR;
2763 write_carrays_finale(fh);
2767 return CF_PRINT_WRITE_ERROR;
2775 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2776 search_direction dir)
2780 mdata.string = string;
2781 mdata.string_len = strlen(string);
2782 return find_packet(cf, match_protocol_tree, &mdata, dir);
2786 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2788 mdata->frame_matched = FALSE;
2789 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2790 mdata->string_len = strlen(mdata->string);
2792 /* Iterate through all the nodes looking for matching text */
2793 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2794 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2798 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2800 match_data *mdata = criterion;
2803 /* Load the frame's data. */
2804 if (!cf_read_frame(cf, fdata)) {
2805 /* Attempt to get the packet failed. */
2809 /* Construct the protocol tree, including the displayed text */
2810 epan_dissect_init(&edt, TRUE, TRUE);
2811 /* We don't need the column information */
2812 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2814 /* Iterate through all the nodes, seeing if they have text that matches. */
2816 mdata->frame_matched = FALSE;
2817 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2818 epan_dissect_cleanup(&edt);
2819 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2823 match_subtree_text(proto_node *node, gpointer data)
2825 match_data *mdata = (match_data*) data;
2826 const gchar *string = mdata->string;
2827 size_t string_len = mdata->string_len;
2828 capture_file *cf = mdata->cf;
2829 field_info *fi = PNODE_FINFO(node);
2830 gchar label_str[ITEM_LABEL_LENGTH];
2837 g_assert(fi && "dissection with an invisible proto tree?");
2839 if (mdata->frame_matched) {
2840 /* We already had a match; don't bother doing any more work. */
2844 /* Don't match invisible entries. */
2845 if (PROTO_ITEM_IS_HIDDEN(node))
2848 /* was a free format label produced? */
2850 label_ptr = fi->rep->representation;
2852 /* no, make a generic label */
2853 label_ptr = label_str;
2854 proto_item_fill_label(fi, label_str);
2857 /* Does that label match? */
2858 label_len = strlen(label_ptr);
2859 for (i = 0; i < label_len; i++) {
2860 c_char = label_ptr[i];
2862 c_char = toupper(c_char);
2863 if (c_char == string[c_match]) {
2865 if (c_match == string_len) {
2866 /* No need to look further; we have a match */
2867 mdata->frame_matched = TRUE;
2875 /* Recurse into the subtree, if it exists */
2876 if (node->first_child != NULL)
2877 proto_tree_children_foreach(node, match_subtree_text, mdata);
2881 cf_find_packet_summary_line(capture_file *cf, const char *string,
2882 search_direction dir)
2886 mdata.string = string;
2887 mdata.string_len = strlen(string);
2888 return find_packet(cf, match_summary_line, &mdata, dir);
2892 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2894 match_data *mdata = criterion;
2895 const gchar *string = mdata->string;
2896 size_t string_len = mdata->string_len;
2898 const char *info_column;
2899 size_t info_column_len;
2900 match_result result = MR_NOTMATCHED;
2906 /* Load the frame's data. */
2907 if (!cf_read_frame(cf, fdata)) {
2908 /* Attempt to get the packet failed. */
2912 /* Don't bother constructing the protocol tree */
2913 epan_dissect_init(&edt, FALSE, FALSE);
2914 /* Get the column information */
2915 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2917 /* Find the Info column */
2918 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2919 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2920 /* Found it. See if we match. */
2921 info_column = edt.pi.cinfo->col_data[colx];
2922 info_column_len = strlen(info_column);
2923 for (i = 0; i < info_column_len; i++) {
2924 c_char = info_column[i];
2926 c_char = toupper(c_char);
2927 if (c_char == string[c_match]) {
2929 if (c_match == string_len) {
2930 result = MR_MATCHED;
2939 epan_dissect_cleanup(&edt);
2946 } cbs_t; /* "Counted byte string" */
2949 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
2950 search_direction dir)
2955 info.data_len = string_size;
2957 /* String or hex search? */
2959 /* String search - what type of string? */
2960 switch (cf->scs_type) {
2962 case SCS_ASCII_AND_UNICODE:
2963 return find_packet(cf, match_ascii_and_unicode, &info, dir);
2966 return find_packet(cf, match_ascii, &info, dir);
2969 return find_packet(cf, match_unicode, &info, dir);
2972 g_assert_not_reached();
2976 return find_packet(cf, match_binary, &info, dir);
2980 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2982 cbs_t *info = criterion;
2983 const guint8 *ascii_text = info->data;
2984 size_t textlen = info->data_len;
2985 match_result result;
2991 /* Load the frame's data. */
2992 if (!cf_read_frame(cf, fdata)) {
2993 /* Attempt to get the packet failed. */
2997 result = MR_NOTMATCHED;
2998 buf_len = fdata->pkt_len;
2999 for (i = 0; i < buf_len; i++) {
3002 c_char = toupper(c_char);
3004 if (c_char == ascii_text[c_match]) {
3006 if (c_match == textlen) {
3007 result = MR_MATCHED;
3008 cf->search_pos = i; /* Save the position of the last character
3009 for highlighting the field. */
3020 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
3022 cbs_t *info = criterion;
3023 const guint8 *ascii_text = info->data;
3024 size_t textlen = info->data_len;
3025 match_result result;
3031 /* Load the frame's data. */
3032 if (!cf_read_frame(cf, fdata)) {
3033 /* Attempt to get the packet failed. */
3037 result = MR_NOTMATCHED;
3038 buf_len = fdata->pkt_len;
3039 for (i = 0; i < buf_len; i++) {
3042 c_char = toupper(c_char);
3043 if (c_char == ascii_text[c_match]) {
3045 if (c_match == textlen) {
3046 result = MR_MATCHED;
3047 cf->search_pos = i; /* Save the position of the last character
3048 for highlighting the field. */
3058 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3060 cbs_t *info = criterion;
3061 const guint8 *ascii_text = info->data;
3062 size_t textlen = info->data_len;
3063 match_result result;
3069 /* Load the frame's data. */
3070 if (!cf_read_frame(cf, fdata)) {
3071 /* Attempt to get the packet failed. */
3075 result = MR_NOTMATCHED;
3076 buf_len = fdata->pkt_len;
3077 for (i = 0; i < buf_len; i++) {
3080 c_char = toupper(c_char);
3081 if (c_char == ascii_text[c_match]) {
3084 if (c_match == textlen) {
3085 result = MR_MATCHED;
3086 cf->search_pos = i; /* Save the position of the last character
3087 for highlighting the field. */
3097 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3099 cbs_t *info = criterion;
3100 const guint8 *binary_data = info->data;
3101 size_t datalen = info->data_len;
3102 match_result result;
3107 /* Load the frame's data. */
3108 if (!cf_read_frame(cf, fdata)) {
3109 /* Attempt to get the packet failed. */
3113 result = MR_NOTMATCHED;
3114 buf_len = fdata->pkt_len;
3115 for (i = 0; i < buf_len; i++) {
3116 if (cf->pd[i] == binary_data[c_match]) {
3118 if (c_match == datalen) {
3119 result = MR_MATCHED;
3120 cf->search_pos = i; /* Save the position of the last character
3121 for highlighting the field. */
3131 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3132 search_direction dir)
3134 return find_packet(cf, match_dfilter, sfcode, dir);
3138 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3139 search_direction dir)
3144 if (!dfilter_compile(filter, &sfcode)) {
3146 * XXX - this shouldn't happen, as the filter string is machine
3151 if (sfcode == NULL) {
3153 * XXX - this shouldn't happen, as the filter string is machine
3158 result = find_packet(cf, match_dfilter, sfcode, dir);
3159 dfilter_free(sfcode);
3164 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3166 dfilter_t *sfcode = criterion;
3168 match_result result;
3170 /* Load the frame's data. */
3171 if (!cf_read_frame(cf, fdata)) {
3172 /* Attempt to get the packet failed. */
3176 epan_dissect_init(&edt, TRUE, FALSE);
3177 epan_dissect_prime_dfilter(&edt, sfcode);
3178 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3179 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3180 epan_dissect_cleanup(&edt);
3185 cf_find_packet_marked(capture_file *cf, search_direction dir)
3187 return find_packet(cf, match_marked, NULL, dir);
3191 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3193 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3197 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3199 return find_packet(cf, match_time_reference, NULL, dir);
3203 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3205 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3209 find_packet(capture_file *cf,
3210 match_result (*match_function)(capture_file *, frame_data *, void *),
3211 void *criterion, search_direction dir)
3213 frame_data *start_fd;
3216 frame_data *new_fd = NULL;
3217 progdlg_t *progbar = NULL;
3222 GTimeVal start_time;
3223 gchar status_str[100];
3224 int progbar_nextstep;
3225 int progbar_quantum;
3227 match_result result;
3229 start_fd = cf->current_frame;
3230 if (start_fd != NULL) {
3231 /* Iterate through the list of packets, starting at the packet we've
3232 picked, calling a routine to run the filter on the packet, see if
3233 it matches, and stop if so. */
3235 framenum = start_fd->num;
3237 /* Update the progress bar when it gets to this value. */
3238 progbar_nextstep = 0;
3239 /* When we reach the value that triggers a progress bar update,
3240 bump that value by this amount. */
3241 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3242 /* Progress so far. */
3246 g_get_current_time(&start_time);
3248 title = cf->sfilter?cf->sfilter:"";
3250 /* Create the progress bar if necessary.
3251 We check on every iteration of the loop, so that it takes no
3252 longer than the standard time to create it (otherwise, for a
3253 large file, we might take considerably longer than that standard
3254 time in order to get to the next progress bar step). */
3255 if (progbar == NULL)
3256 progbar = delayed_create_progress_dlg("Searching", title,
3257 FALSE, &stop_flag, &start_time, progbar_val);
3259 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3260 when we update it, we have to run the GTK+ main loop to get it
3261 to repaint what's pending, and doing so may involve an "ioctl()"
3262 to see if there's any pending input from an X server, and doing
3263 that for every packet can be costly, especially on a big file. */
3264 if (count >= progbar_nextstep) {
3265 /* let's not divide by zero. I should never be started
3266 * with count == 0, so let's assert that
3268 g_assert(cf->count > 0);
3270 progbar_val = (gfloat) count / cf->count;
3272 if (progbar != NULL) {
3273 g_snprintf(status_str, sizeof(status_str),
3274 "%4u of %u packets", count, cf->count);
3275 update_progress_dlg(progbar, progbar_val, status_str);
3278 progbar_nextstep += progbar_quantum;
3282 /* Well, the user decided to abort the search. Go back to the
3283 frame where we started. */
3288 /* Go past the current frame. */
3289 if (dir == SD_BACKWARD) {
3290 /* Go on to the previous frame. */
3291 if (framenum == 1) {
3293 * XXX - other apps have a bit more of a detailed message
3294 * for this, and instead of offering "OK" and "Cancel",
3295 * they offer things such as "Continue" and "Cancel";
3296 * we need an API for popping up alert boxes with
3297 * {Verb} and "Cancel".
3300 if (prefs.gui_find_wrap)
3302 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3303 framenum = cf->count; /* wrap around */
3307 statusbar_push_temporary_msg("Search reached the beginning.");
3308 framenum = start_fd->num; /* stay on previous packet */
3313 /* Go on to the next frame. */
3314 if (framenum == cf->count) {
3315 if (prefs.gui_find_wrap)
3317 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3318 framenum = 1; /* wrap around */
3322 statusbar_push_temporary_msg("Search reached the end.");
3323 framenum = start_fd->num; /* stay on previous packet */
3328 fdata = frame_data_sequence_find(cf->frames, framenum);
3332 /* Is this packet in the display? */
3333 if (fdata->flags.passed_dfilter) {
3334 /* Yes. Does it match the search criterion? */
3335 result = (*match_function)(cf, fdata, criterion);
3336 if (result == MR_ERROR) {
3337 /* Error; our caller has reported the error. Go back to the frame
3338 where we started. */
3341 } else if (result == MR_MATCHED) {
3342 /* Yes. Go to the new frame. */
3348 if (fdata == start_fd) {
3349 /* We're back to the frame we were on originally, and that frame
3350 doesn't match the search filter. The search failed. */
3355 /* We're done scanning the packets; destroy the progress bar if it
3357 if (progbar != NULL)
3358 destroy_progress_dlg(progbar);
3361 if (new_fd != NULL) {
3362 /* Find and select */
3363 cf->search_in_progress = TRUE;
3364 found = new_packet_list_select_row_from_data(new_fd);
3365 cf->search_in_progress = FALSE;
3366 cf->search_pos = 0; /* Reset the position */
3368 /* We didn't find a row corresponding to this frame.
3369 This means that the frame isn't being displayed currently,
3370 so we can't select it. */
3371 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3372 "%sEnd of capture exceeded!%s\n\n"
3373 "The capture file is probably not fully dissected.",
3374 simple_dialog_primary_start(), simple_dialog_primary_end());
3377 return TRUE; /* success */
3379 return FALSE; /* failure */
3383 cf_goto_frame(capture_file *cf, guint fnumber)
3387 fdata = frame_data_sequence_find(cf->frames, fnumber);
3389 if (fdata == NULL) {
3390 /* we didn't find a packet with that packet number */
3391 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3392 return FALSE; /* we failed to go to that packet */
3394 if (!fdata->flags.passed_dfilter) {
3395 /* that packet currently isn't displayed */
3396 /* XXX - add it to the set of displayed packets? */
3397 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3398 return FALSE; /* we failed to go to that packet */
3401 if (!new_packet_list_select_row_from_data(fdata)) {
3402 /* We didn't find a row corresponding to this frame.
3403 This means that the frame isn't being displayed currently,
3404 so we can't select it. */
3405 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3406 "%sEnd of capture exceeded!%s\n\n"
3407 "The capture file is probably not fully dissected.",
3408 simple_dialog_primary_start(), simple_dialog_primary_end());
3411 return TRUE; /* we got to that packet */
3415 cf_goto_top_frame(void)
3417 /* Find and select */
3418 new_packet_list_select_first_row();
3419 return TRUE; /* we got to that packet */
3423 cf_goto_bottom_frame(void)
3425 /* Find and select */
3426 new_packet_list_select_last_row();
3427 return TRUE; /* we got to that packet */
3431 * Go to frame specified by currently selected protocol tree item.
3434 cf_goto_framenum(capture_file *cf)
3436 header_field_info *hfinfo;
3439 if (cf->finfo_selected) {
3440 hfinfo = cf->finfo_selected->hfinfo;
3442 if (hfinfo->type == FT_FRAMENUM) {
3443 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3445 return cf_goto_frame(cf, framenum);
3452 /* Select the packet on a given row. */
3454 cf_select_packet(capture_file *cf, int row)
3458 /* Get the frame data struct pointer for this frame */
3459 fdata = new_packet_list_get_row_data(row);
3461 if (fdata == NULL) {
3462 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3463 the first entry is added to it by "real_insert_row()", that row
3464 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3465 our version and the vanilla GTK+ version).
3467 This means that a "select-row" signal is emitted; this causes
3468 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3471 "cf_select_packet()" fetches, above, the data associated with the
3472 row that was selected; however, as "gtk_clist_append()", which
3473 called "real_insert_row()", hasn't yet returned, we haven't yet
3474 associated any data with that row, so we get back a null pointer.
3476 We can't assume that there's only one frame in the frame list,
3477 either, as we may be filtering the display.
3479 We therefore assume that, if "row" is 0, i.e. the first row
3480 is being selected, and "cf->first_displayed" equals
3481 "cf->last_displayed", i.e. there's only one frame being
3482 displayed, that frame is the frame we want.
3484 This means we have to set "cf->first_displayed" and
3485 "cf->last_displayed" before adding the row to the
3486 GtkCList; see the comment in "add_packet_to_packet_list()". */
3488 if (row == 0 && cf->first_displayed == cf->last_displayed)
3489 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3492 /* If fdata _still_ isn't set simply give up. */
3493 if (fdata == NULL) {
3497 /* Get the data in that frame. */
3498 if (!cf_read_frame (cf, fdata)) {
3502 /* Record that this frame is the current frame. */
3503 cf->current_frame = fdata;
3504 cf->current_row = row;
3506 /* Create the logical protocol tree. */
3507 if (cf->edt != NULL)
3508 epan_dissect_free(cf->edt);
3510 /* We don't need the columns here. */
3511 cf->edt = epan_dissect_new(TRUE, TRUE);
3513 tap_build_interesting(cf->edt);
3514 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3517 dfilter_macro_build_ftv_cache(cf->edt->tree);
3519 cf_callback_invoke(cf_cb_packet_selected, cf);
3522 /* Unselect the selected packet, if any. */
3524 cf_unselect_packet(capture_file *cf)
3526 /* Destroy the epan_dissect_t for the unselected packet. */
3527 if (cf->edt != NULL) {
3528 epan_dissect_free(cf->edt);
3532 /* No packet is selected. */
3533 cf->current_frame = NULL;
3534 cf->current_row = 0;
3536 cf_callback_invoke(cf_cb_packet_unselected, cf);
3538 /* No protocol tree means no selected field. */
3539 cf_unselect_field(cf);
3542 /* Unset the selected protocol tree field, if any. */
3544 cf_unselect_field(capture_file *cf)
3546 cf->finfo_selected = NULL;
3548 cf_callback_invoke(cf_cb_field_unselected, cf);
3552 * Mark a particular frame.
3555 cf_mark_frame(capture_file *cf, frame_data *frame)
3557 if (! frame->flags.marked) {
3558 frame->flags.marked = TRUE;
3559 if (cf->count > cf->marked_count)
3565 * Unmark a particular frame.
3568 cf_unmark_frame(capture_file *cf, frame_data *frame)
3570 if (frame->flags.marked) {
3571 frame->flags.marked = FALSE;
3572 if (cf->marked_count > 0)
3578 * Ignore a particular frame.
3581 cf_ignore_frame(capture_file *cf, frame_data *frame)
3583 if (! frame->flags.ignored) {
3584 frame->flags.ignored = TRUE;
3585 if (cf->count > cf->ignored_count)
3586 cf->ignored_count++;
3591 * Un-ignore a particular frame.
3594 cf_unignore_frame(capture_file *cf, frame_data *frame)
3596 if (frame->flags.ignored) {
3597 frame->flags.ignored = FALSE;
3598 if (cf->ignored_count > 0)
3599 cf->ignored_count--;
3607 } save_callback_args_t;
3610 * Save a capture to a file, in a particular format, saving either
3611 * all packets, all currently-displayed packets, or all marked packets.
3613 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3614 * up a message box for the failure.
3617 save_packet(capture_file *cf _U_, frame_data *fdata,
3618 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3621 save_callback_args_t *args = argsp;
3622 struct wtap_pkthdr hdr;
3625 /* init the wtap header for saving */
3626 hdr.ts.secs = fdata->abs_ts.secs;
3627 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3628 hdr.caplen = fdata->cap_len;
3629 hdr.len = fdata->pkt_len;
3630 hdr.pkt_encap = fdata->lnk_t;
3632 /* and save the packet */
3633 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3635 /* Wiretap error. */
3638 case WTAP_ERR_UNSUPPORTED_ENCAP:
3640 * This is a problem with the particular frame we're writing;
3641 * note that, and give the frame number.
3643 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3644 "Frame %u has a network type that can't be saved in a \"%s\" file.",
3645 fdata->num, wtap_file_type_string(args->file_type));
3649 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3650 "An error occurred while writing to the file \"%s\": %s.",
3651 args->fname, wtap_strerror(err));
3656 write_failure_alert_box(args->fname, err);
3664 * Can this capture file be saved in any format except by copying the raw data?
3667 cf_can_save_as(capture_file *cf)
3671 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
3672 /* To save a file with Wiretap, Wiretap has to handle that format,
3673 and its code to handle that format must be able to write a file
3674 with this file's encapsulation type. */
3675 if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
3676 /* OK, we can write it out in this type. */
3681 /* No, we couldn't save it in any format. */
3686 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3688 gchar *from_filename;
3692 save_callback_args_t callback_args;
3694 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
3696 /* don't write over an existing file. */
3697 /* this should've been already checked by our caller, just to be sure... */
3698 if (file_exists(fname)) {
3699 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3700 "%sCapture file: \"%s\" already exists!%s\n\n"
3701 "Please choose a different filename.",
3702 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3706 packet_range_process_init(range);
3708 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3709 /* We're not filtering packets, and we're saving it in the format
3710 it's already in, so we can just move or copy the raw data. */
3712 if (cf->is_tempfile) {
3713 /* The file being saved is a temporary file from a live
3714 capture, so it doesn't need to stay around under that name;
3715 first, try renaming the capture buffer file to the new name. */
3717 if (ws_rename(cf->filename, fname) == 0) {
3718 /* That succeeded - there's no need to copy the source file. */
3719 from_filename = NULL;
3722 if (errno == EXDEV) {
3723 /* They're on different file systems, so we have to copy the
3726 from_filename = cf->filename;
3728 /* The rename failed, but not because they're on different
3729 file systems - put up an error message. (Or should we
3730 just punt and try to copy? The only reason why I'd
3731 expect the rename to fail and the copy to succeed would
3732 be if we didn't have permission to remove the file from
3733 the temporary directory, and that might be fixable - but
3734 is it worth requiring the user to go off and fix it?) */
3735 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3736 file_rename_error_message(errno), fname);
3742 from_filename = cf->filename;
3745 /* It's a permanent file, so we should copy it, and not remove the
3748 from_filename = cf->filename;
3752 /* Copy the file, if we haven't moved it. */
3753 if (!copy_file_binary_mode(from_filename, fname))
3757 /* Either we're filtering packets, or we're saving in a different
3758 format; we can't do that by copying or moving the capture file,
3759 we have to do it by writing the packets out in Wiretap. */
3760 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3763 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3767 /* XXX - we let the user save a subset of the packets.
3769 If we do that, should we make that file the current file? If so,
3770 it means we can no longer get at the other packets. What does
3773 /* Iterate through the list of packets, processing the packets we were
3776 XXX - we've already called "packet_range_process_init(range)", but
3777 "process_specified_packets()" will do it again. Fortunately,
3778 that's harmless in this case, as we haven't done anything to
3779 "range" since we initialized it. */
3780 callback_args.pdh = pdh;
3781 callback_args.fname = fname;
3782 callback_args.file_type = save_format;
3783 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3784 TRUE, save_packet, &callback_args)) {
3787 /* Completed successfully. */
3791 /* The user decided to abort the saving.
3792 XXX - remove the output file? */
3796 /* Error while saving. */
3797 wtap_dump_close(pdh, &err);
3801 if (!wtap_dump_close(pdh, &err)) {
3802 cf_close_failure_alert_box(fname, err);
3807 cf_callback_invoke(cf_cb_file_save_finished, NULL);
3809 if (packet_range_process_all(range)) {
3810 /* We saved the entire capture, not just some packets from it.
3811 Open and read the file we saved it to.
3813 XXX - this is somewhat of a waste; we already have the
3814 packets, all this gets us is updated file type information
3815 (which we could just stuff into "cf"), and having the new
3816 file be the one we have opened and from which we're reading
3817 the data, and it means we have to spend time opening and
3818 reading the file, which could be a significant amount of
3819 time if the file is large. */
3820 cf->user_saved = TRUE;
3822 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3823 /* XXX - report errors if this fails?
3824 What should we return if it fails or is aborted? */
3826 switch (cf_read(cf, TRUE)) {
3830 /* Just because we got an error, that doesn't mean we were unable
3831 to read any of the file; we handle what we could get from the
3835 case CF_READ_ABORTED:
3836 /* The user bailed out of re-reading the capture file; the
3837 capture file has been closed - just return (without
3838 changing any menu settings; "cf_close()" set them
3839 correctly for the "no capture file open" state). */
3842 cf_callback_invoke(cf_cb_file_save_reload_finished, cf);
3848 cf_callback_invoke(cf_cb_file_save_failed, NULL);
3853 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3854 gboolean for_writing, int file_type)
3857 /* Wiretap error. */
3860 case WTAP_ERR_NOT_REGULAR_FILE:
3861 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3862 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3866 case WTAP_ERR_RANDOM_OPEN_PIPE:
3867 /* Seen only when opening a capture file for reading. */
3868 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3869 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
3873 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3874 /* Seen only when opening a capture file for reading. */
3875 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3876 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
3880 case WTAP_ERR_UNSUPPORTED:
3881 /* Seen only when opening a capture file for reading. */
3882 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3883 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
3885 filename, err_info);
3889 case WTAP_ERR_CANT_WRITE_TO_PIPE:
3890 /* Seen only when opening a capture file for writing. */
3891 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3892 "The file \"%s\" is a pipe, and %s capture files can't be "
3893 "written to a pipe.",
3894 filename, wtap_file_type_string(file_type));
3897 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3898 /* Seen only when opening a capture file for writing. */
3899 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3900 "Wireshark doesn't support writing capture files in that format.");
3903 case WTAP_ERR_UNSUPPORTED_ENCAP:
3905 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3906 "Wireshark can't save this capture in that format.");
3908 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3909 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
3911 filename, err_info);
3916 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3918 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3919 "Wireshark can't save this capture in that format.");
3921 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3922 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
3927 case WTAP_ERR_BAD_FILE:
3928 /* Seen only when opening a capture file for reading. */
3929 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3930 "The file \"%s\" appears to be damaged or corrupt.\n"
3932 filename, err_info);
3936 case WTAP_ERR_CANT_OPEN:
3938 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3939 "The file \"%s\" could not be created for some unknown reason.",
3942 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3943 "The file \"%s\" could not be opened for some unknown reason.",
3948 case WTAP_ERR_SHORT_READ:
3949 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3950 "The file \"%s\" appears to have been cut short"
3951 " in the middle of a packet or other data.",
3955 case WTAP_ERR_SHORT_WRITE:
3956 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3957 "A full header couldn't be written to the file \"%s\".",
3961 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
3962 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3963 "Gzip compression not supported by this file type.");
3966 case WTAP_ERR_DECOMPRESS:
3967 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3968 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
3969 "(%s)", filename, err_info);
3974 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3975 "The file \"%s\" could not be %s: %s.",
3977 for_writing ? "created" : "opened",
3978 wtap_strerror(err));
3983 open_failure_alert_box(filename, err, for_writing);
3988 file_rename_error_message(int err)
3991 static char errmsg_errno[1024+1];
3996 errmsg = "The path to the file \"%s\" doesn't exist.";
4000 errmsg = "You don't have permission to move the capture file to \"%s\".";
4004 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4005 "The file \"%%s\" could not be moved: %s.",
4006 wtap_strerror(err));
4007 errmsg = errmsg_errno;
4013 /* Check for write errors - if the file is being written to an NFS server,
4014 a write error may not show up until the file is closed, as NFS clients
4015 might not send writes to the server until the "write()" call finishes,
4016 so that the write may fail on the server but the "write()" may succeed. */
4018 cf_close_failure_alert_box(const char *filename, int err)
4021 /* Wiretap error. */
4024 case WTAP_ERR_CANT_CLOSE:
4025 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4026 "The file \"%s\" couldn't be closed for some unknown reason.",
4030 case WTAP_ERR_SHORT_WRITE:
4031 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4032 "Not all the packets could be written to the file \"%s\".",
4037 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4038 "An error occurred while closing the file \"%s\": %s.",
4039 filename, wtap_strerror(err));
4044 We assume that a close error from the OS is really a write error. */
4045 write_failure_alert_box(filename, err);
4049 /* Reload the current capture file. */
4051 cf_reload(capture_file *cf) {
4053 gboolean is_tempfile;
4056 /* If the file could be opened, "cf_open()" calls "cf_close()"
4057 to get rid of state for the old capture file before filling in state
4058 for the new capture file. "cf_close()" will remove the file if
4059 it's a temporary file; we don't want that to happen (for one thing,
4060 it'd prevent subsequent reopens from working). Remember whether it's
4061 a temporary file, mark it as not being a temporary file, and then
4062 reopen it as the type of file it was.
4064 Also, "cf_close()" will free "cf->filename", so we must make
4065 a copy of it first. */
4066 filename = g_strdup(cf->filename);
4067 is_tempfile = cf->is_tempfile;
4068 cf->is_tempfile = FALSE;
4069 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4070 switch (cf_read(cf, FALSE)) {
4074 /* Just because we got an error, that doesn't mean we were unable
4075 to read any of the file; we handle what we could get from the
4079 case CF_READ_ABORTED:
4080 /* The user bailed out of re-reading the capture file; the
4081 capture file has been closed - just free the capture file name
4082 string and return (without changing the last containing
4088 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4089 Instead, the file was left open, so we should restore "cf->is_tempfile"
4092 XXX - change the menu? Presumably "cf_open()" will do that;
4093 make sure it does! */
4094 cf->is_tempfile = is_tempfile;
4096 /* "cf_open()" made a copy of the file name we handed it, so
4097 we should free up our copy. */
4107 * indent-tabs-mode: nil
4110 * ex: set shiftwidth=2 tabstop=8 expandtab:
4111 * :indentSize=2:tabSize=8:noTabs=true: