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"
62 #include <epan/prefs.h>
63 #include <epan/dfilter/dfilter.h>
64 #include <epan/epan_dissect.h>
66 #include <epan/dissectors/packet-data.h>
67 #include <epan/dissectors/packet-ber.h>
68 #include <epan/timestamp.h>
69 #include <epan/dfilter/dfilter-macro.h>
70 #include <wsutil/file_util.h>
71 #include <epan/strutil.h>
72 #include <epan/addr_resolv.h>
74 #include "ui/alert_box.h"
75 #include "ui/simple_dialog.h"
76 #include "ui/main_statusbar.h"
77 #include "ui/progress_dlg.h"
78 #include "ui/ui_util.h"
81 gboolean auto_scroll_live;
84 static guint32 cum_bytes;
85 static nstime_t first_ts;
86 static nstime_t prev_dis_ts;
87 static nstime_t prev_cap_ts;
89 static gulong computed_elapsed;
91 static void cf_reset_state(capture_file *cf);
93 static int read_packet(capture_file *cf, dfilter_t *dfcode,
94 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset);
96 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
97 gboolean refilter, gboolean redissect);
104 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
106 static void match_subtree_text(proto_node *node, gpointer data);
107 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
109 static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
111 static match_result match_ascii(capture_file *cf, frame_data *fdata,
113 static match_result match_unicode(capture_file *cf, frame_data *fdata,
115 static match_result match_binary(capture_file *cf, frame_data *fdata,
117 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
119 static match_result match_marked(capture_file *cf, frame_data *fdata,
121 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
123 static gboolean find_packet(capture_file *cf,
124 match_result (*match_function)(capture_file *, frame_data *, void *),
125 void *criterion, search_direction dir);
127 static void cf_open_failure_alert_box(const char *filename, int err,
128 gchar *err_info, gboolean for_writing,
130 static const char *file_rename_error_message(int err);
131 static void cf_close_failure_alert_box(const char *filename, int err);
132 static void ref_time_packets(capture_file *cf);
133 /* Update the progress bar this many times when reading a file. */
134 #define N_PROGBAR_UPDATES 100
135 /* We read around 200k/100ms don't update the progress bar more often than that */
136 #define MIN_QUANTUM 200000
137 #define MIN_NUMBER_OF_PACKET 1500
140 * We could probably use g_signal_...() instead of the callbacks below but that
141 * would require linking our CLI programs to libgobject and creating an object
142 * instance for the signals.
145 cf_callback_t cb_fct;
147 } cf_callback_data_t;
149 static GList *cf_callbacks = NULL;
152 cf_callback_invoke(int event, gpointer data)
154 cf_callback_data_t *cb;
155 GList *cb_item = cf_callbacks;
157 /* there should be at least one interested */
158 g_assert(cb_item != NULL);
160 while(cb_item != NULL) {
162 cb->cb_fct(event, data, cb->user_data);
163 cb_item = g_list_next(cb_item);
169 cf_callback_add(cf_callback_t func, gpointer user_data)
171 cf_callback_data_t *cb;
173 cb = g_malloc(sizeof(cf_callback_data_t));
175 cb->user_data = user_data;
177 cf_callbacks = g_list_append(cf_callbacks, cb);
181 cf_callback_remove(cf_callback_t func)
183 cf_callback_data_t *cb;
184 GList *cb_item = cf_callbacks;
186 while(cb_item != NULL) {
188 if(cb->cb_fct == func) {
189 cf_callbacks = g_list_remove(cf_callbacks, cb);
193 cb_item = g_list_next(cb_item);
196 g_assert_not_reached();
200 cf_timestamp_auto_precision(capture_file *cf)
203 int prec = timestamp_get_precision();
206 /* don't try to get the file's precision if none is opened */
207 if(cf->state == FILE_CLOSED) {
211 /* if we are in auto mode, set precision of current file */
212 if(prec == TS_PREC_AUTO ||
213 prec == TS_PREC_AUTO_SEC ||
214 prec == TS_PREC_AUTO_DSEC ||
215 prec == TS_PREC_AUTO_CSEC ||
216 prec == TS_PREC_AUTO_MSEC ||
217 prec == TS_PREC_AUTO_USEC ||
218 prec == TS_PREC_AUTO_NSEC)
220 switch(wtap_file_tsprecision(cf->wth)) {
221 case(WTAP_FILE_TSPREC_SEC):
222 timestamp_set_precision(TS_PREC_AUTO_SEC);
224 case(WTAP_FILE_TSPREC_DSEC):
225 timestamp_set_precision(TS_PREC_AUTO_DSEC);
227 case(WTAP_FILE_TSPREC_CSEC):
228 timestamp_set_precision(TS_PREC_AUTO_CSEC);
230 case(WTAP_FILE_TSPREC_MSEC):
231 timestamp_set_precision(TS_PREC_AUTO_MSEC);
233 case(WTAP_FILE_TSPREC_USEC):
234 timestamp_set_precision(TS_PREC_AUTO_USEC);
236 case(WTAP_FILE_TSPREC_NSEC):
237 timestamp_set_precision(TS_PREC_AUTO_NSEC);
240 g_assert_not_reached();
243 /* Set the column widths of those columns that show the time in
244 "command-line-specified" format. */
245 for (i = 0; i < cf->cinfo.num_cols; i++) {
246 if (col_has_time_fmt(&cf->cinfo, i)) {
247 new_packet_list_resize_column(i);
253 cf_get_computed_elapsed(void)
255 return computed_elapsed;
258 static void reset_elapsed(void)
260 computed_elapsed = 0;
263 static void compute_elapsed(GTimeVal *start_time)
268 g_get_current_time(&time_now);
270 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
271 time_now.tv_usec - start_time->tv_usec;
273 computed_elapsed = (gulong) (delta_time / 1000); /* ms */
277 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
282 wth = wtap_open_offline(fname, err, &err_info, TRUE);
286 /* The open succeeded. Close whatever capture file we had open,
287 and fill in the information for this file. */
290 /* Cleanup all data structures used for dissection. */
291 cleanup_dissection();
292 /* Initialize all data structures used for dissection. */
295 /* We're about to start reading the file. */
296 cf->state = FILE_READ_IN_PROGRESS;
301 /* Set the file name because we need it to set the follow stream filter.
302 XXX - is that still true? We need it for other reasons, though,
304 cf->filename = g_strdup(fname);
306 /* Indicate whether it's a permanent or temporary file. */
307 cf->is_tempfile = is_tempfile;
309 /* No user changes yet. */
310 cf->unsaved_changes = FALSE;
314 cf->cd_t = wtap_file_type(cf->wth);
316 cf->displayed_count = 0;
317 cf->marked_count = 0;
318 cf->ignored_count = 0;
319 cf->ref_time_count = 0;
320 cf->drops_known = FALSE;
322 cf->snap = wtap_snapshot_length(cf->wth);
324 /* Snapshot length not known. */
325 cf->has_snap = FALSE;
326 cf->snap = WTAP_MAX_PACKET_SIZE;
330 /* Allocate a frame_data_sequence for the frames in this file */
331 cf->frames = new_frame_data_sequence();
333 nstime_set_zero(&cf->elapsed_time);
334 nstime_set_unset(&first_ts);
335 nstime_set_unset(&prev_dis_ts);
336 nstime_set_unset(&prev_cap_ts);
339 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
340 cf_timestamp_auto_precision(cf);
342 new_packet_list_queue_draw();
343 fileset_file_opened(fname);
345 if(cf->cd_t == WTAP_FILE_BER) {
346 /* tell the BER dissector the file name */
347 ber_set_filename(cf->filename);
350 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
351 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
356 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
362 * Reset the state for the currently closed file, but don't do the
363 * UI callbacks; this is for use in "cf_open()", where we don't
364 * want the UI to go from "file open" to "file closed" back to
365 * "file open", we want it to go from "old file open" to "new file
366 * open and being read".
368 * XXX - currently, cf_open() calls cf_close(), rather than
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 no changes to that file to save. */
390 cf->unsaved_changes = 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 if(cf->state != FILE_CLOSED) {
435 cf_callback_invoke(cf_cb_file_closing, cf);
437 /* close things, if not already closed before */
438 color_filters_cleanup();
440 cleanup_dissection();
442 cf_callback_invoke(cf_cb_file_closed, cf);
446 /* an out of memory exception occured, wait for a user button press to exit */
447 static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
453 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
457 progbar_val = (gfloat) file_pos / (gfloat) size;
458 if (progbar_val > 1.0) {
460 /* The file probably grew while we were reading it.
461 * Update file size, and try again.
463 size = wtap_file_size(cf->wth, NULL);
466 progbar_val = (gfloat) file_pos / (gfloat) size;
468 /* If it's still > 1, either "wtap_file_size()" failed (in which
469 * case there's not much we can do about it), or the file
470 * *shrank* (in which case there's not much we can do about
471 * it); just clip the progress value at 1.0.
473 if (progbar_val > 1.0f)
477 g_snprintf(status_str, status_size,
478 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
479 file_pos / 1024, size / 1024);
485 cf_read(capture_file *cf, gboolean from_save)
489 const gchar *name_ptr;
491 char errmsg_errno[1024+1];
494 progdlg_t *volatile progbar = NULL;
496 volatile gint64 size;
497 volatile float progbar_val;
499 gchar status_str[100];
500 volatile gint64 progbar_nextstep;
501 volatile gint64 progbar_quantum;
503 gboolean filtering_tap_listeners;
505 volatile int count = 0;
507 volatile int displayed_once = 0;
511 /* Compile the current display filter.
512 * We assume this will not fail since cf->dfilter is only set in
513 * cf_filter IFF the filter was valid.
515 compiled = dfilter_compile(cf->dfilter, &dfcode);
516 g_assert(!cf->dfilter || (compiled && dfcode));
518 /* Do we have any tap listeners with filters? */
519 filtering_tap_listeners = have_filtering_tap_listeners();
521 /* Get the union of the flags for all tap listeners. */
522 tap_flags = union_of_tap_listener_flags();
524 reset_tap_listeners();
526 name_ptr = get_basename(cf->filename);
528 if (from_save == FALSE)
529 cf_callback_invoke(cf_cb_file_read_started, cf);
531 cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr);
533 /* Find the size of the file. */
534 size = wtap_file_size(cf->wth, NULL);
536 /* Update the progress bar when it gets to this value. */
537 progbar_nextstep = 0;
538 /* When we reach the value that triggers a progress bar update,
539 bump that value by this amount. */
541 progbar_quantum = size/N_PROGBAR_UPDATES;
542 if (progbar_quantum < MIN_QUANTUM)
543 progbar_quantum = MIN_QUANTUM;
546 /* Progress so far. */
549 /* The packet list window will be empty untill the file is completly loaded */
550 new_packet_list_freeze();
553 g_get_current_time(&start_time);
555 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
558 file_pos = wtap_read_so_far(cf->wth);
560 /* Create the progress bar if necessary.
561 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
563 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
564 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
565 if (from_save == FALSE)
566 progbar = delayed_create_progress_dlg("Loading", name_ptr,
567 TRUE, &stop_flag, &start_time, progbar_val);
569 progbar = delayed_create_progress_dlg("Saving", name_ptr,
570 TRUE, &stop_flag, &start_time, progbar_val);
573 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
574 when we update it, we have to run the GTK+ main loop to get it
575 to repaint what's pending, and doing so may involve an "ioctl()"
576 to see if there's any pending input from an X server, and doing
577 that for every packet can be costly, especially on a big file. */
578 if (file_pos >= progbar_nextstep) {
579 if (progbar != NULL) {
580 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
581 /* update the packet bar content on the first run or frequently on very large files */
583 if (progbar_quantum > 500000 || displayed_once == 0) {
584 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
586 packets_bar_update();
589 #endif /* HAVE_LIBPCAP */
590 update_progress_dlg(progbar, progbar_val, status_str);
592 progbar_nextstep += progbar_quantum;
597 /* Well, the user decided to abort the read. He/She will be warned and
598 it might be enough for him/her to work with the already loaded
600 This is especially true for very large capture files, where you don't
601 want to wait loading the whole file (which may last minutes or even
602 hours even on fast machines) just to see that it was the wrong file. */
606 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
608 CATCH(OutOfMemoryError) {
611 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
612 "%sOut Of Memory!%s\n"
614 "Sorry, but Wireshark has to terminate now!\n"
616 "Some infos / workarounds can be found at:\n"
617 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
618 simple_dialog_primary_start(), simple_dialog_primary_end());
619 /* we have to terminate, as we cannot recover from the memory error */
620 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
622 main_window_update();
623 /* XXX - how to avoid a busy wait? */
631 /* Cleanup and release all dfilter resources */
633 dfilter_free(dfcode);
636 /* We're done reading the file; destroy the progress bar if it was created. */
638 destroy_progress_dlg(progbar);
640 /* We're done reading sequentially through the file. */
641 cf->state = FILE_READ_DONE;
643 /* Close the sequential I/O side, to free up memory it requires. */
644 wtap_sequential_close(cf->wth);
646 /* Allow the protocol dissectors to free up memory that they
647 * don't need after the sequential run-through of the packets. */
648 postseq_cleanup_all_protocols();
650 /* compute the time it took to load the file */
651 compute_elapsed(&start_time);
653 /* Set the file encapsulation type now; we don't know what it is until
654 we've looked at all the packets, as we don't know until then whether
655 there's more than one type (and thus whether it's
656 WTAP_ENCAP_PER_PACKET). */
657 cf->lnk_t = wtap_file_encap(cf->wth);
659 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
662 new_packet_list_thaw();
663 if (from_save == FALSE)
664 cf_callback_invoke(cf_cb_file_read_finished, cf);
666 cf_callback_invoke(cf_cb_file_save_finished, cf);
668 /* If we have any displayed packets to select, select the first of those
669 packets by making the first row the selected row. */
670 if (cf->first_displayed != 0){
671 new_packet_list_select_first_row();
675 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
676 "%sFile loading was cancelled!%s\n"
678 "The remaining packets in the file were discarded.\n"
680 "As a lot of packets from the original file will be missing,\n"
681 "remember to be careful when saving the current content to a file.\n",
682 simple_dialog_primary_start(), simple_dialog_primary_end());
683 return CF_READ_ERROR;
687 /* Put up a message box noting that the read failed somewhere along
688 the line. Don't throw out the stuff we managed to read, though,
692 case WTAP_ERR_UNSUPPORTED:
693 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
694 "The capture file contains record data that TShark doesn't support.\n(%s)",
697 errmsg = errmsg_errno;
700 case WTAP_ERR_UNSUPPORTED_ENCAP:
701 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
702 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
705 errmsg = errmsg_errno;
708 case WTAP_ERR_CANT_READ:
709 errmsg = "An attempt to read from the capture file failed for"
710 " some unknown reason.";
713 case WTAP_ERR_SHORT_READ:
714 errmsg = "The capture file appears to have been cut short"
715 " in the middle of a packet.";
718 case WTAP_ERR_BAD_FILE:
719 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
720 "The capture file appears to be damaged or corrupt.\n(%s)",
723 errmsg = errmsg_errno;
726 case WTAP_ERR_DECOMPRESS:
727 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
728 "The compressed capture file appears to be damaged or corrupt.\n"
731 errmsg = errmsg_errno;
735 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
736 "An error occurred while reading the"
737 " capture file: %s.", wtap_strerror(err));
738 errmsg = errmsg_errno;
741 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
742 return CF_READ_ERROR;
749 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
751 cf_status_t cf_status;
753 cf_status = cf_open(cf, fname, is_tempfile, err);
758 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
760 gint64 data_offset = 0;
762 volatile int newly_displayed_packets = 0;
764 gboolean filtering_tap_listeners;
768 /* Compile the current display filter.
769 * We assume this will not fail since cf->dfilter is only set in
770 * cf_filter IFF the filter was valid.
772 compiled = dfilter_compile(cf->dfilter, &dfcode);
773 g_assert(!cf->dfilter || (compiled && dfcode));
775 /* Do we have any tap listeners with filters? */
776 filtering_tap_listeners = have_filtering_tap_listeners();
778 /* Get the union of the flags for all tap listeners. */
779 tap_flags = union_of_tap_listener_flags();
783 new_packet_list_check_end();
784 /* Don't freeze/thaw the list when doing live capture */
785 /*new_packet_list_freeze();*/
787 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
789 while (to_read != 0) {
790 wtap_cleareof(cf->wth);
791 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
794 if (cf->state == FILE_READ_ABORTED) {
795 /* Well, the user decided to exit Wireshark. Break out of the
796 loop, and let the code below (which is called even if there
797 aren't any packets left to read) exit. */
801 if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
802 data_offset) != -1) {
803 newly_displayed_packets++;
806 CATCH(OutOfMemoryError) {
809 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
810 "%sOut Of Memory!%s\n"
812 "Sorry, but Wireshark has to terminate now!\n"
814 "The capture file is not lost, it can be found at:\n"
817 "Some infos / workarounds can be found at:\n"
818 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
819 simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
820 /* we have to terminate, as we cannot recover from the memory error */
821 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
823 main_window_update();
824 /* XXX - how to avoid a busy wait? */
827 /* Don't freeze/thaw the list when doing live capture */
828 /*new_packet_list_thaw();*/
829 return CF_READ_ABORTED;
835 /* Cleanup and release all dfilter resources */
837 dfilter_free(dfcode);
840 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
841 cf->count, cf->state, *err);*/
843 /* Don't freeze/thaw the list when doing live capture */
844 /*new_packet_list_thaw();*/
845 /* With the new packet list the first packet
846 * isn't automatically selected.
848 if(!cf->current_frame)
849 new_packet_list_select_first_row();
851 /* moving to the end of the packet list - if the user requested so and
852 we have some new packets. */
853 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
854 new_packet_list_moveto_end();
856 if (cf->state == FILE_READ_ABORTED) {
857 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
858 so that our caller can kill off the capture child process;
859 this will cause an EOF on the pipe from the child, so
860 "cf_finish_tail()" will be called, and it will clean up
862 return CF_READ_ABORTED;
863 } else if (*err != 0) {
864 /* We got an error reading the capture file.
865 XXX - pop up a dialog box instead? */
866 g_warning("Error \"%s\" while reading: \"%s\"\n",
867 wtap_strerror(*err), cf->filename);
869 return CF_READ_ERROR;
875 cf_fake_continue_tail(capture_file *cf) {
876 cf->state = FILE_READ_DONE;
880 cf_finish_tail(capture_file *cf, int *err)
885 gboolean filtering_tap_listeners;
889 /* Compile the current display filter.
890 * We assume this will not fail since cf->dfilter is only set in
891 * cf_filter IFF the filter was valid.
893 compiled = dfilter_compile(cf->dfilter, &dfcode);
894 g_assert(!cf->dfilter || (compiled && dfcode));
896 /* Do we have any tap listeners with filters? */
897 filtering_tap_listeners = have_filtering_tap_listeners();
899 /* Get the union of the flags for all tap listeners. */
900 tap_flags = union_of_tap_listener_flags();
902 if(cf->wth == NULL) {
904 return CF_READ_ERROR;
907 new_packet_list_check_end();
908 /* Don't freeze/thaw the list when doing live capture */
909 /*new_packet_list_freeze();*/
911 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
912 if (cf->state == FILE_READ_ABORTED) {
913 /* Well, the user decided to abort the read. Break out of the
914 loop, and let the code below (which is called even if there
915 aren't any packets left to read) exit. */
918 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
921 /* Cleanup and release all dfilter resources */
923 dfilter_free(dfcode);
926 /* Don't freeze/thaw the list when doing live capture */
927 /*new_packet_list_thaw();*/
929 if (cf->state == FILE_READ_ABORTED) {
930 /* Well, the user decided to abort the read. We're only called
931 when the child capture process closes the pipe to us (meaning
932 it's probably exited), so we can just close the capture
933 file; we return CF_READ_ABORTED so our caller can do whatever
934 is appropriate when that happens. */
936 return CF_READ_ABORTED;
939 if (auto_scroll_live && cf->count != 0)
940 new_packet_list_moveto_end();
942 /* We're done reading sequentially through the file. */
943 cf->state = FILE_READ_DONE;
945 /* We're done reading sequentially through the file; close the
946 sequential I/O side, to free up memory it requires. */
947 wtap_sequential_close(cf->wth);
949 /* Allow the protocol dissectors to free up memory that they
950 * don't need after the sequential run-through of the packets. */
951 postseq_cleanup_all_protocols();
953 /* Set the file encapsulation type now; we don't know what it is until
954 we've looked at all the packets, as we don't know until then whether
955 there's more than one type (and thus whether it's
956 WTAP_ENCAP_PER_PACKET). */
957 cf->lnk_t = wtap_file_encap(cf->wth);
960 /* We got an error reading the capture file.
961 XXX - pop up a dialog box? */
962 return CF_READ_ERROR;
967 #endif /* HAVE_LIBPCAP */
970 cf_get_display_name(capture_file *cf)
972 const gchar *displayname;
974 /* Return a name to use in displays */
975 if (!cf->is_tempfile) {
976 /* Get the last component of the file name, and use that. */
978 displayname = get_basename(cf->filename);
980 displayname="(No file)";
983 /* The file we read is a temporary file from a live capture;
984 we don't mention its name. */
986 displayname = cf->source;
988 displayname = "(Untitled)";
994 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1000 cf->source = g_strdup(source);
1002 cf->source = g_strdup("");
1006 const gchar *cf_get_tempfile_source(capture_file *cf) {
1014 /* XXX - use a macro instead? */
1016 cf_get_packet_count(capture_file *cf)
1021 /* XXX - use a macro instead? */
1023 cf_set_packet_count(capture_file *cf, int packet_count)
1025 cf->count = packet_count;
1028 /* XXX - use a macro instead? */
1030 cf_is_tempfile(capture_file *cf)
1032 return cf->is_tempfile;
1035 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1037 cf->is_tempfile = is_tempfile;
1041 /* XXX - use a macro instead? */
1042 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1044 cf->drops_known = drops_known;
1047 /* XXX - use a macro instead? */
1048 void cf_set_drops(capture_file *cf, guint32 drops)
1053 /* XXX - use a macro instead? */
1054 gboolean cf_get_drops_known(capture_file *cf)
1056 return cf->drops_known;
1059 /* XXX - use a macro instead? */
1060 guint32 cf_get_drops(capture_file *cf)
1065 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1067 cf->rfcode = rfcode;
1071 find_and_mark_frame_depended_upon(gpointer data, gpointer user_data)
1073 frame_data *dependent_fd;
1074 guint32 dependent_frame = GPOINTER_TO_UINT(data);
1075 capture_file *cf = (capture_file *)user_data;
1077 dependent_fd = frame_data_sequence_find(cf->frames, dependent_frame);
1078 dependent_fd->flags.dependent_of_displayed = 1;
1082 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1083 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1085 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1087 gboolean add_to_packet_list)
1089 gboolean create_proto_tree = FALSE;
1094 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1096 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1097 &first_ts, &prev_dis_ts, &prev_cap_ts);
1100 + we have a display filter and are re-applying it;
1101 + we have tap listeners with filters;
1102 + we have tap listeners that require a protocol tree;
1104 allocate a protocol tree root node, so that we'll construct
1105 a protocol tree against which a filter expression can be
1107 if ((dfcode != NULL && refilter) ||
1108 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1109 create_proto_tree = TRUE;
1111 /* Dissect the frame. */
1112 epan_dissect_init(&edt, create_proto_tree, FALSE);
1114 if (dfcode != NULL && refilter) {
1115 epan_dissect_prime_dfilter(&edt, dfcode);
1118 tap_queue_init(&edt);
1119 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1120 tap_push_tapped_queue(&edt);
1122 /* If we have a display filter, apply it if we're refiltering, otherwise
1123 leave the "passed_dfilter" flag alone.
1125 If we don't have a display filter, set "passed_dfilter" to 1. */
1126 if (dfcode != NULL) {
1128 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1130 if (fdata->flags.passed_dfilter) {
1131 /* This frame passed the display filter but it may depend on other
1132 * (potentially not displayed) frames. Find those frames and mark them
1135 g_slist_foreach(edt.pi.dependent_frames, find_and_mark_frame_depended_upon, cf);
1139 fdata->flags.passed_dfilter = 1;
1141 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1142 cf->displayed_count++;
1144 if (add_to_packet_list) {
1145 /* We fill the needed columns from new_packet_list */
1146 row = new_packet_list_append(cinfo, fdata, &edt.pi);
1149 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1151 frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1153 /* If we haven't yet seen the first frame, this is it.
1155 XXX - we must do this before we add the row to the display,
1156 as, if the display's GtkCList's selection mode is
1157 GTK_SELECTION_BROWSE, when the first entry is added to it,
1158 "cf_select_packet()" will be called, and it will fetch the row
1159 data for the 0th row, and will get a null pointer rather than
1160 "fdata", as "gtk_clist_append()" won't yet have returned and
1161 thus "gtk_clist_set_row_data()" won't yet have been called.
1163 We thus need to leave behind bread crumbs so that
1164 "cf_select_packet()" can find this frame. See the comment
1165 in "cf_select_packet()". */
1166 if (cf->first_displayed == 0)
1167 cf->first_displayed = fdata->num;
1169 /* This is the last frame we've seen so far. */
1170 cf->last_displayed = fdata->num;
1173 epan_dissect_cleanup(&edt);
1177 /* read in a new packet */
1178 /* returns the row of the new packet in the packet list or -1 if not displayed */
1180 read_packet(capture_file *cf, dfilter_t *dfcode,
1181 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1183 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1184 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1185 const guchar *buf = wtap_buf_ptr(cf->wth);
1192 /* The frame number of this packet is one more than the count of
1193 frames in this packet. */
1194 framenum = cf->count + 1;
1196 frame_data_init(&fdlocal, framenum, phdr, offset, cum_bytes);
1201 epan_dissect_init(&edt, TRUE, FALSE);
1202 epan_dissect_prime_dfilter(&edt, cf->rfcode);
1203 epan_dissect_run(&edt, pseudo_header, buf, &fdlocal, NULL);
1204 passed = dfilter_apply_edt(cf->rfcode, &edt);
1205 epan_dissect_cleanup(&edt);
1209 /* This does a shallow copy of fdlocal, which is good enough. */
1210 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1213 cf->f_datalen = offset + fdlocal.cap_len;
1215 if (!cf->redissecting) {
1216 row = add_packet_to_packet_list(fdata, cf, dfcode,
1217 filtering_tap_listeners, tap_flags,
1218 pseudo_header, buf, TRUE, TRUE);
1226 cf_merge_files(char **out_filenamep, int in_file_count,
1227 char *const *in_filenames, int file_type, gboolean do_append)
1229 merge_in_file_t *in_files, *in_file;
1234 int open_err, read_err, write_err, close_err;
1238 char errmsg_errno[1024+1];
1240 gboolean got_read_error = FALSE, got_write_error = FALSE;
1242 progdlg_t *progbar = NULL;
1244 gint64 f_len, file_pos;
1246 GTimeVal start_time;
1247 gchar status_str[100];
1248 gint64 progbar_nextstep;
1249 gint64 progbar_quantum;
1251 /* open the input files */
1252 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1253 &open_err, &err_info, &err_fileno)) {
1255 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1260 if (*out_filenamep != NULL) {
1261 out_filename = *out_filenamep;
1262 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1266 out_fd = create_tempfile(&tmpname, "wireshark");
1269 out_filename = g_strdup(tmpname);
1270 *out_filenamep = out_filename;
1274 merge_close_in_files(in_file_count, in_files);
1276 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1280 pdh = wtap_dump_fdopen(out_fd, file_type,
1281 merge_select_frame_type(in_file_count, in_files),
1282 merge_max_snapshot_length(in_file_count, in_files),
1283 FALSE /* compressed */, &open_err);
1286 merge_close_in_files(in_file_count, in_files);
1288 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1293 /* Get the sum of the sizes of all the files. */
1295 for (i = 0; i < in_file_count; i++)
1296 f_len += in_files[i].size;
1298 /* Update the progress bar when it gets to this value. */
1299 progbar_nextstep = 0;
1300 /* When we reach the value that triggers a progress bar update,
1301 bump that value by this amount. */
1302 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1303 /* Progress so far. */
1307 g_get_current_time(&start_time);
1309 /* do the merge (or append) */
1312 in_file = merge_append_read_packet(in_file_count, in_files, &read_err,
1315 in_file = merge_read_packet(in_file_count, in_files, &read_err,
1317 if (in_file == NULL) {
1322 if (read_err != 0) {
1323 /* I/O error reading from in_file */
1324 got_read_error = TRUE;
1328 /* Get the sum of the data offsets in all of the files. */
1330 for (i = 0; i < in_file_count; i++)
1331 data_offset += in_files[i].data_offset;
1333 /* Create the progress bar if necessary.
1334 We check on every iteration of the loop, so that it takes no
1335 longer than the standard time to create it (otherwise, for a
1336 large file, we might take considerably longer than that standard
1337 time in order to get to the next progress bar step). */
1338 if (progbar == NULL) {
1339 progbar = delayed_create_progress_dlg("Merging", "files",
1340 FALSE, &stop_flag, &start_time, progbar_val);
1343 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1344 when we update it, we have to run the GTK+ main loop to get it
1345 to repaint what's pending, and doing so may involve an "ioctl()"
1346 to see if there's any pending input from an X server, and doing
1347 that for every packet can be costly, especially on a big file. */
1348 if (data_offset >= progbar_nextstep) {
1349 /* Get the sum of the seek positions in all of the files. */
1351 for (i = 0; i < in_file_count; i++)
1352 file_pos += wtap_read_so_far(in_files[i].wth);
1353 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1354 if (progbar_val > 1.0f) {
1355 /* Some file probably grew while we were reading it.
1356 That "shouldn't happen", so we'll just clip the progress
1360 if (progbar != NULL) {
1361 g_snprintf(status_str, sizeof(status_str),
1362 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1363 file_pos / 1024, f_len / 1024);
1364 update_progress_dlg(progbar, progbar_val, status_str);
1366 progbar_nextstep += progbar_quantum;
1370 /* Well, the user decided to abort the merge. */
1374 if (!wtap_dump(pdh, wtap_phdr(in_file->wth), wtap_pseudoheader(in_file->wth),
1375 wtap_buf_ptr(in_file->wth), &write_err)) {
1376 got_write_error = TRUE;
1381 /* We're done merging the files; destroy the progress bar if it was created. */
1382 if (progbar != NULL)
1383 destroy_progress_dlg(progbar);
1385 merge_close_in_files(in_file_count, in_files);
1386 if (!got_read_error && !got_write_error) {
1387 if (!wtap_dump_close(pdh, &write_err))
1388 got_write_error = TRUE;
1390 wtap_dump_close(pdh, &close_err);
1392 if (got_read_error) {
1394 * Find the file on which we got the error, and report the error.
1396 for (i = 0; i < in_file_count; i++) {
1397 if (in_files[i].state == GOT_ERROR) {
1398 /* Put up a message box noting that a read failed somewhere along
1402 case WTAP_ERR_UNSUPPORTED_ENCAP:
1403 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1404 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1407 errmsg = errmsg_errno;
1410 case WTAP_ERR_CANT_READ:
1411 errmsg = "An attempt to read from the capture file %s failed for"
1412 " some unknown reason.";
1415 case WTAP_ERR_SHORT_READ:
1416 errmsg = "The capture file %s appears to have been cut short"
1417 " in the middle of a packet.";
1420 case WTAP_ERR_BAD_FILE:
1421 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1422 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1425 errmsg = errmsg_errno;
1428 case WTAP_ERR_DECOMPRESS:
1429 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1430 "The compressed capture file %%s appears to be damaged or corrupt.\n"
1433 errmsg = errmsg_errno;
1437 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1438 "An error occurred while reading the"
1439 " capture file %%s: %s.", wtap_strerror(read_err));
1440 errmsg = errmsg_errno;
1443 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
1448 if (got_write_error) {
1449 /* Put up an alert box for the write error. */
1450 if (write_err < 0) {
1451 /* Wiretap error. */
1452 switch (write_err) {
1454 case WTAP_ERR_UNSUPPORTED_ENCAP:
1456 * This is a problem with the particular frame we're writing;
1457 * note that, and give the frame number.
1459 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1460 "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.",
1461 in_file->packet_num, in_file->filename,
1462 wtap_file_type_string(file_type));
1466 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1467 "An error occurred while writing to the file \"%s\": %s.",
1468 out_filename, wtap_strerror(write_err));
1473 write_failure_alert_box(out_filename, write_err);
1477 if (got_read_error || got_write_error || stop_flag) {
1478 /* Callers aren't expected to treat an error or an explicit abort
1479 differently - we put up error dialogs ourselves, so they don't
1487 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1489 const char *filter_new = dftext ? dftext : "";
1490 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1492 GTimeVal start_time;
1494 /* if new filter equals old one, do nothing unless told to do so */
1495 if (!force && strcmp(filter_new, filter_old) == 0) {
1501 if (dftext == NULL) {
1502 /* The new filter is an empty filter (i.e., display all packets).
1503 * so leave dfcode==NULL
1507 * We have a filter; make a copy of it (as we'll be saving it),
1508 * and try to compile it.
1510 dftext = g_strdup(dftext);
1511 if (!dfilter_compile(dftext, &dfcode)) {
1512 /* The attempt failed; report an error. */
1513 gchar *safe_dftext = simple_dialog_format_message(dftext);
1514 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1516 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1519 "The following display filter isn't a valid display filter:\n%s\n"
1520 "See the help for a description of the display filter syntax.",
1521 simple_dialog_primary_start(), safe_dfilter_error_msg,
1522 simple_dialog_primary_end(), safe_dftext);
1523 g_free(safe_dfilter_error_msg);
1524 g_free(safe_dftext);
1530 if (dfcode == NULL) {
1531 /* Yes - free the filter text, and set it to null. */
1537 /* We have a valid filter. Replace the current filter. */
1538 g_free(cf->dfilter);
1539 cf->dfilter = dftext;
1540 g_get_current_time(&start_time);
1543 /* Now rescan the packet list, applying the new filter, but not
1544 throwing away information constructed on a previous pass. */
1545 if (dftext == NULL) {
1546 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1548 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1551 /* Cleanup and release all dfilter resources */
1552 dfilter_free(dfcode);
1558 cf_reftime_packets(capture_file *cf)
1561 ref_time_packets(cf);
1565 cf_redissect_packets(capture_file *cf)
1567 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1571 cf_read_frame_r(capture_file *cf, frame_data *fdata,
1572 union wtap_pseudo_header *pseudo_header, guint8 *pd)
1576 char errmsg_errno[1024+1];
1578 #ifdef WANT_PACKET_EDITOR
1579 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1580 if (G_UNLIKELY(fdata->file_off == -1)) {
1581 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1584 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "fdata->file_off == -1, but can't find modified frame!");
1588 *pseudo_header = frame->ph;
1589 memcpy(pd, frame->pd, fdata->cap_len);
1594 if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
1595 fdata->cap_len, &err, &err_info)) {
1598 case WTAP_ERR_UNSUPPORTED_ENCAP:
1599 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1600 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1605 case WTAP_ERR_BAD_FILE:
1606 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1607 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
1608 wtap_strerror(err), err_info);
1613 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1614 "An error occurred while reading from the file \"%%s\": %s.",
1615 wtap_strerror(err));
1618 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg_errno, cf->filename);
1625 cf_read_frame(capture_file *cf, frame_data *fdata)
1627 return cf_read_frame_r(cf, fdata, &cf->pseudo_header, cf->pd);
1630 /* Rescan the list of packets, reconstructing the CList.
1632 "action" describes why we're doing this; it's used in the progress
1635 "action_item" describes what we're doing; it's used in the progress
1638 "refilter" is TRUE if we need to re-evaluate the filter expression.
1640 "redissect" is TRUE if we need to make the dissectors reconstruct
1641 any state information they have (because a preference that affects
1642 some dissector has changed, meaning some dissector might construct
1643 its state differently from the way it was constructed the last time). */
1645 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1646 gboolean refilter, gboolean redissect)
1648 /* Rescan packets new packet list */
1651 progdlg_t *progbar = NULL;
1654 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1655 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1656 gboolean selected_frame_seen;
1658 GTimeVal start_time;
1659 gchar status_str[100];
1660 int progbar_nextstep;
1661 int progbar_quantum;
1663 gboolean filtering_tap_listeners;
1665 gboolean add_to_packet_list = FALSE;
1668 /* Compile the current display filter.
1669 * We assume this will not fail since cf->dfilter is only set in
1670 * cf_filter IFF the filter was valid.
1672 compiled = dfilter_compile(cf->dfilter, &dfcode);
1673 g_assert(!cf->dfilter || (compiled && dfcode));
1675 /* Do we have any tap listeners with filters? */
1676 filtering_tap_listeners = have_filtering_tap_listeners();
1678 /* Get the union of the flags for all tap listeners. */
1679 tap_flags = union_of_tap_listener_flags();
1681 reset_tap_listeners();
1682 /* Which frame, if any, is the currently selected frame?
1683 XXX - should the selected frame or the focus frame be the "current"
1684 frame, that frame being the one from which "Find Frame" searches
1686 selected_frame = cf->current_frame;
1688 /* Mark frame num as not found */
1689 selected_frame_num = -1;
1691 /* Freeze the packet list while we redo it, so we don't get any
1692 screen updates while it happens. */
1693 new_packet_list_freeze();
1696 /* We need to re-initialize all the state information that protocols
1697 keep, because some preference that controls a dissector has changed,
1698 which might cause the state information to be constructed differently
1699 by that dissector. */
1701 /* We might receive new packets while redissecting, and we don't
1702 want to dissect those before their time. */
1703 cf->redissecting = TRUE;
1705 /* Cleanup all data structures used for dissection. */
1706 cleanup_dissection();
1707 /* Initialize all data structures used for dissection. */
1710 /* We need to redissect the packets so we have to discard our old
1711 * packet list store. */
1712 new_packet_list_clear();
1713 add_to_packet_list = TRUE;
1716 /* We don't yet know which will be the first and last frames displayed. */
1717 cf->first_displayed = 0;
1718 cf->last_displayed = 0;
1720 /* We currently don't display any packets */
1721 cf->displayed_count = 0;
1723 /* Iterate through the list of frames. Call a routine for each frame
1724 to check whether it should be displayed and, if so, add it to
1725 the display list. */
1726 nstime_set_unset(&first_ts);
1727 nstime_set_unset(&prev_dis_ts);
1728 nstime_set_unset(&prev_cap_ts);
1731 /* Update the progress bar when it gets to this value. */
1732 progbar_nextstep = 0;
1733 /* When we reach the value that triggers a progress bar update,
1734 bump that value by this amount. */
1735 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1736 /* Count of packets at which we've looked. */
1738 /* Progress so far. */
1742 g_get_current_time(&start_time);
1744 /* no previous row yet */
1745 prev_frame_num = -1;
1748 preceding_frame_num = -1;
1749 preceding_frame = NULL;
1750 following_frame_num = -1;
1751 following_frame = NULL;
1753 selected_frame_seen = FALSE;
1755 for (framenum = 1; framenum <= cf->count; framenum++) {
1756 fdata = frame_data_sequence_find(cf->frames, framenum);
1758 /* Create the progress bar if necessary.
1759 We check on every iteration of the loop, so that it takes no
1760 longer than the standard time to create it (otherwise, for a
1761 large file, we might take considerably longer than that standard
1762 time in order to get to the next progress bar step). */
1763 if (progbar == NULL)
1764 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1765 &stop_flag, &start_time,
1768 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1769 when we update it, we have to run the GTK+ main loop to get it
1770 to repaint what's pending, and doing so may involve an "ioctl()"
1771 to see if there's any pending input from an X server, and doing
1772 that for every packet can be costly, especially on a big file. */
1773 if (count >= progbar_nextstep) {
1774 /* let's not divide by zero. I should never be started
1775 * with count == 0, so let's assert that
1777 g_assert(cf->count > 0);
1778 progbar_val = (gfloat) count / cf->count;
1780 if (progbar != NULL) {
1781 g_snprintf(status_str, sizeof(status_str),
1782 "%4u of %u frames", count, cf->count);
1783 update_progress_dlg(progbar, progbar_val, status_str);
1786 progbar_nextstep += progbar_quantum;
1790 /* Well, the user decided to abort the filtering. Just stop.
1792 XXX - go back to the previous filter? Users probably just
1793 want not to wait for a filtering operation to finish;
1794 unless we cancel by having no filter, reverting to the
1795 previous filter will probably be even more expensive than
1796 continuing the filtering, as it involves going back to the
1797 beginning and filtering, and even with no filter we currently
1798 have to re-generate the entire clist, which is also expensive.
1800 I'm not sure what Network Monitor does, but it doesn't appear
1801 to give you an unfiltered display if you cancel. */
1808 /* Since all state for the frame was destroyed, mark the frame
1809 * as not visited, free the GSList referring to the state
1810 * data (the per-frame data itself was freed by
1811 * "init_dissection()"), and null out the GSList pointer. */
1812 fdata->flags.visited = 0;
1813 frame_data_cleanup(fdata);
1816 if (redissect || refilter) {
1817 /* If we're redissecting or refiltering then any frame dependencies
1818 * from the previous dissection/filtering are no longer valid.
1820 fdata->flags.dependent_of_displayed = 0;
1823 if (!cf_read_frame(cf, fdata))
1824 break; /* error reading the frame */
1826 /* If the previous frame is displayed, and we haven't yet seen the
1827 selected frame, remember that frame - it's the closest one we've
1828 yet seen before the selected frame. */
1829 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1830 preceding_frame_num = prev_frame_num;
1831 preceding_frame = prev_frame;
1833 add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1834 tap_flags, &cf->pseudo_header, cf->pd,
1836 add_to_packet_list);
1838 /* If this frame is displayed, and this is the first frame we've
1839 seen displayed after the selected frame, remember this frame -
1840 it's the closest one we've yet seen at or after the selected
1842 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1843 following_frame_num = fdata->num;
1844 following_frame = fdata;
1846 if (fdata == selected_frame) {
1847 selected_frame_seen = TRUE;
1848 if (fdata->flags.passed_dfilter)
1849 selected_frame_num = fdata->num;
1852 /* Remember this frame - it'll be the previous frame
1853 on the next pass through the loop. */
1854 prev_frame_num = fdata->num;
1858 /* We are done redissecting the packet list. */
1859 cf->redissecting = FALSE;
1862 /* Clear out what remains of the visited flags and per-frame data
1865 XXX - that may cause various forms of bogosity when dissecting
1866 these frames, as they won't have been seen by this sequential
1867 pass, but the only alternative I see is to keep scanning them
1868 even though the user requested that the scan stop, and that
1869 would leave the user stuck with an Wireshark grinding on
1870 until it finishes. Should we just stick them with that? */
1871 for (; framenum <= cf->count; framenum++) {
1872 fdata = frame_data_sequence_find(cf->frames, framenum);
1873 fdata->flags.visited = 0;
1874 frame_data_cleanup(fdata);
1878 /* We're done filtering the packets; destroy the progress bar if it
1880 if (progbar != NULL)
1881 destroy_progress_dlg(progbar);
1883 /* Unfreeze the packet list. */
1884 if (!add_to_packet_list)
1885 new_packet_list_recreate_visible_rows();
1887 /* Compute the time it took to filter the file */
1888 compute_elapsed(&start_time);
1890 new_packet_list_thaw();
1892 if (selected_frame_num == -1) {
1893 /* The selected frame didn't pass the filter. */
1894 if (selected_frame == NULL) {
1895 /* That's because there *was* no selected frame. Make the first
1896 displayed frame the current frame. */
1897 selected_frame_num = 0;
1899 /* Find the nearest displayed frame to the selected frame (whether
1900 it's before or after that frame) and make that the current frame.
1901 If the next and previous displayed frames are equidistant from the
1902 selected frame, choose the next one. */
1903 g_assert(following_frame == NULL ||
1904 following_frame->num >= selected_frame->num);
1905 g_assert(preceding_frame == NULL ||
1906 preceding_frame->num <= selected_frame->num);
1907 if (following_frame == NULL) {
1908 /* No frame after the selected frame passed the filter, so we
1909 have to select the last displayed frame before the selected
1911 selected_frame_num = preceding_frame_num;
1912 selected_frame = preceding_frame;
1913 } else if (preceding_frame == NULL) {
1914 /* No frame before the selected frame passed the filter, so we
1915 have to select the first displayed frame after the selected
1917 selected_frame_num = following_frame_num;
1918 selected_frame = following_frame;
1920 /* Frames before and after the selected frame passed the filter, so
1921 we'll select the previous frame */
1922 selected_frame_num = preceding_frame_num;
1923 selected_frame = preceding_frame;
1928 if (selected_frame_num == -1) {
1929 /* There are no frames displayed at all. */
1930 cf_unselect_packet(cf);
1932 /* Either the frame that was selected passed the filter, or we've
1933 found the nearest displayed frame to that frame. Select it, make
1934 it the focus row, and make it visible. */
1935 /* Set to invalid to force update of packet list and packet details */
1936 cf->current_row = -1;
1937 if (selected_frame_num == 0) {
1938 new_packet_list_select_first_row();
1940 if (!new_packet_list_select_row_from_data(selected_frame)) {
1941 /* We didn't find a row corresponding to this frame.
1942 This means that the frame isn't being displayed currently,
1943 so we can't select it. */
1944 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
1945 "%sEnd of capture exceeded!%s\n\n"
1946 "The capture file is probably not fully dissected.",
1947 simple_dialog_primary_start(), simple_dialog_primary_end());
1952 /* Cleanup and release all dfilter resources */
1953 dfilter_free(dfcode);
1958 * Scan trough all frame data and recalculate the ref time
1959 * without rereading the file.
1960 * XXX - do we need a progres bar or is this fast enough?
1963 ref_time_packets(capture_file *cf)
1968 nstime_set_unset(&first_ts);
1969 nstime_set_unset(&prev_dis_ts);
1972 for (framenum = 1; framenum <= cf->count; framenum++) {
1973 fdata = frame_data_sequence_find(cf->frames, framenum);
1975 /* just add some value here until we know if it is being displayed or not */
1976 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1982 /* If we don't have the time stamp of the first packet in the
1983 capture, it's because this is the first packet. Save the time
1984 stamp of this packet as the time stamp of the first packet. */
1985 if (nstime_is_unset(&first_ts)) {
1986 first_ts = fdata->abs_ts;
1988 /* if this frames is marked as a reference time frame, reset
1989 firstsec and firstusec to this frame */
1990 if(fdata->flags.ref_time){
1991 first_ts = fdata->abs_ts;
1994 /* If we don't have the time stamp of the previous displayed packet,
1995 it's because this is the first displayed packet. Save the time
1996 stamp of this packet as the time stamp of the previous displayed
1998 if (nstime_is_unset(&prev_dis_ts)) {
1999 prev_dis_ts = fdata->abs_ts;
2002 /* Get the time elapsed between the first packet and this packet. */
2003 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
2005 /* If it's greater than the current elapsed time, set the elapsed time
2006 to it (we check for "greater than" so as not to be confused by
2007 time moving backwards). */
2008 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
2009 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
2010 cf->elapsed_time = fdata->rel_ts;
2013 /* If this frame is displayed, get the time elapsed between the
2014 previous displayed packet and this packet. */
2015 if( fdata->flags.passed_dfilter ) {
2016 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
2017 prev_dis_ts = fdata->abs_ts;
2023 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
2024 /* This frame either passed the display filter list or is marked as
2025 a time reference frame. All time reference frames are displayed
2026 even if they dont pass the display filter */
2027 if(fdata->flags.ref_time){
2028 /* if this was a TIME REF frame we should reset the cum_bytes field */
2029 cum_bytes = fdata->pkt_len;
2030 fdata->cum_bytes = cum_bytes;
2032 /* increase cum_bytes with this packets length */
2033 cum_bytes += fdata->pkt_len;
2046 process_specified_packets(capture_file *cf, packet_range_t *range,
2047 const char *string1, const char *string2, gboolean terminate_is_stop,
2048 gboolean (*callback)(capture_file *, frame_data *,
2049 union wtap_pseudo_header *, const guint8 *, void *),
2050 void *callback_args)
2054 union wtap_pseudo_header pseudo_header;
2055 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
2056 psp_return_t ret = PSP_FINISHED;
2058 progdlg_t *progbar = NULL;
2061 gboolean progbar_stop_flag;
2062 GTimeVal progbar_start_time;
2063 gchar progbar_status_str[100];
2064 int progbar_nextstep;
2065 int progbar_quantum;
2066 range_process_e process_this;
2068 /* Update the progress bar when it gets to this value. */
2069 progbar_nextstep = 0;
2070 /* When we reach the value that triggers a progress bar update,
2071 bump that value by this amount. */
2072 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2073 /* Count of packets at which we've looked. */
2075 /* Progress so far. */
2078 progbar_stop_flag = FALSE;
2079 g_get_current_time(&progbar_start_time);
2081 packet_range_process_init(range);
2083 /* Iterate through all the packets, printing the packets that
2084 were selected by the current display filter. */
2085 for (framenum = 1; framenum <= cf->count; framenum++) {
2086 fdata = frame_data_sequence_find(cf->frames, framenum);
2088 /* Create the progress bar if necessary.
2089 We check on every iteration of the loop, so that it takes no
2090 longer than the standard time to create it (otherwise, for a
2091 large file, we might take considerably longer than that standard
2092 time in order to get to the next progress bar step). */
2093 if (progbar == NULL)
2094 progbar = delayed_create_progress_dlg(string1, string2,
2097 &progbar_start_time,
2100 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2101 when we update it, we have to run the GTK+ main loop to get it
2102 to repaint what's pending, and doing so may involve an "ioctl()"
2103 to see if there's any pending input from an X server, and doing
2104 that for every packet can be costly, especially on a big file. */
2105 if (progbar_count >= progbar_nextstep) {
2106 /* let's not divide by zero. I should never be started
2107 * with count == 0, so let's assert that
2109 g_assert(cf->count > 0);
2110 progbar_val = (gfloat) progbar_count / cf->count;
2112 if (progbar != NULL) {
2113 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2114 "%4u of %u packets", progbar_count, cf->count);
2115 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2118 progbar_nextstep += progbar_quantum;
2121 if (progbar_stop_flag) {
2122 /* Well, the user decided to abort the operation. Just stop,
2123 and arrange to return PSP_STOPPED to our caller, so they know
2124 it was stopped explicitly. */
2131 /* do we have to process this packet? */
2132 process_this = packet_range_process_packet(range, fdata);
2133 if (process_this == range_process_next) {
2134 /* this packet uninteresting, continue with next one */
2136 } else if (process_this == range_processing_finished) {
2137 /* all interesting packets processed, stop the loop */
2141 /* Get the packet */
2142 if (!cf_read_frame_r(cf, fdata, &pseudo_header, pd)) {
2143 /* Attempt to get the packet failed. */
2147 /* Process the packet */
2148 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
2149 /* Callback failed. We assume it reported the error appropriately. */
2155 /* We're done printing the packets; destroy the progress bar if
2157 if (progbar != NULL)
2158 destroy_progress_dlg(progbar);
2164 gboolean construct_protocol_tree;
2166 } retap_callback_args_t;
2169 retap_packet(capture_file *cf _U_, frame_data *fdata,
2170 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2173 retap_callback_args_t *args = argsp;
2176 epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
2177 tap_queue_init(&edt);
2178 epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
2179 tap_push_tapped_queue(&edt);
2180 epan_dissect_cleanup(&edt);
2186 cf_retap_packets(capture_file *cf)
2188 packet_range_t range;
2189 retap_callback_args_t callback_args;
2190 gboolean filtering_tap_listeners;
2193 /* Do we have any tap listeners with filters? */
2194 filtering_tap_listeners = have_filtering_tap_listeners();
2196 tap_flags = union_of_tap_listener_flags();
2198 /* If any tap listeners have filters, or require the protocol tree,
2199 construct the protocol tree. */
2200 callback_args.construct_protocol_tree = filtering_tap_listeners ||
2201 (tap_flags & TL_REQUIRES_PROTO_TREE);
2203 /* If any tap listeners require the columns, construct them. */
2204 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2206 /* Reset the tap listeners. */
2207 reset_tap_listeners();
2209 /* Iterate through the list of packets, dissecting all packets and
2210 re-running the taps. */
2211 packet_range_init(&range);
2212 packet_range_process_init(&range);
2213 switch (process_specified_packets(cf, &range, "Recalculating statistics on",
2214 "all packets", TRUE, retap_packet,
2217 /* Completed successfully. */
2221 /* Well, the user decided to abort the refiltering.
2222 Return CF_READ_ABORTED so our caller knows they did that. */
2223 return CF_READ_ABORTED;
2226 /* Error while retapping. */
2227 return CF_READ_ERROR;
2230 g_assert_not_reached();
2235 print_args_t *print_args;
2236 gboolean print_header_line;
2237 char *header_line_buf;
2238 int header_line_buf_len;
2239 gboolean print_formfeed;
2240 gboolean print_separator;
2244 } print_callback_args_t;
2247 print_packet(capture_file *cf, frame_data *fdata,
2248 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2251 print_callback_args_t *args = argsp;
2258 gboolean proto_tree_needed;
2259 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2260 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2262 /* Create the protocol tree, and make it visible, if we're printing
2263 the dissection or the hex data.
2264 XXX - do we need it if we're just printing the hex data? */
2266 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2267 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2269 /* Fill in the column information if we're printing the summary
2271 if (args->print_args->print_summary) {
2272 col_custom_prime_edt(&edt, &cf->cinfo);
2273 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2274 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2276 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2278 if (args->print_formfeed) {
2279 if (!new_page(args->print_args->stream))
2282 if (args->print_separator) {
2283 if (!print_line(args->print_args->stream, 0, ""))
2289 * We generate bookmarks, if the output format supports them.
2290 * The name is "__frameN__".
2292 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2294 if (args->print_args->print_summary) {
2295 if (args->print_header_line) {
2296 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2298 args->print_header_line = FALSE; /* we might not need to print any more */
2300 cp = &args->line_buf[0];
2302 for (i = 0; i < cf->cinfo.num_cols; i++) {
2303 /* Find the length of the string for this column. */
2304 column_len = (int) strlen(cf->cinfo.col_data[i]);
2305 if (args->col_widths[i] > column_len)
2306 column_len = args->col_widths[i];
2308 /* Make sure there's room in the line buffer for the column; if not,
2309 double its length. */
2310 line_len += column_len + 1; /* "+1" for space */
2311 if (line_len > args->line_buf_len) {
2312 cp_off = (int) (cp - args->line_buf);
2313 args->line_buf_len = 2 * line_len;
2314 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2315 cp = args->line_buf + cp_off;
2318 /* Right-justify the packet number column. */
2319 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2320 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
2322 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
2324 if (i != cf->cinfo.num_cols - 1)
2330 * Generate a bookmark, using the summary line as the title.
2332 if (!print_bookmark(args->print_args->stream, bookmark_name,
2336 if (!print_line(args->print_args->stream, 0, args->line_buf))
2340 * Generate a bookmark, using "Frame N" as the title, as we're not
2341 * printing the summary line.
2343 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2344 if (!print_bookmark(args->print_args->stream, bookmark_name,
2347 } /* if (print_summary) */
2349 if (args->print_args->print_dissections != print_dissections_none) {
2350 if (args->print_args->print_summary) {
2351 /* Separate the summary line from the tree with a blank line. */
2352 if (!print_line(args->print_args->stream, 0, ""))
2356 /* Print the information in that tree. */
2357 if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
2360 /* Print a blank line if we print anything after this (aka more than one packet). */
2361 args->print_separator = TRUE;
2363 /* Print a header line if we print any more packet summaries */
2364 args->print_header_line = TRUE;
2367 if (args->print_args->print_hex) {
2368 /* Print the full packet data as hex. */
2369 if (!print_hex_data(args->print_args->stream, &edt))
2372 /* Print a blank line if we print anything after this (aka more than one packet). */
2373 args->print_separator = TRUE;
2375 /* Print a header line if we print any more packet summaries */
2376 args->print_header_line = TRUE;
2377 } /* if (args->print_args->print_dissections != print_dissections_none) */
2379 epan_dissect_cleanup(&edt);
2381 /* do we want to have a formfeed between each packet from now on? */
2382 if(args->print_args->print_formfeed) {
2383 args->print_formfeed = TRUE;
2389 epan_dissect_cleanup(&edt);
2394 cf_print_packets(capture_file *cf, print_args_t *print_args)
2397 print_callback_args_t callback_args;
2405 callback_args.print_args = print_args;
2406 callback_args.print_header_line = TRUE;
2407 callback_args.header_line_buf = NULL;
2408 callback_args.header_line_buf_len = 256;
2409 callback_args.print_formfeed = FALSE;
2410 callback_args.print_separator = FALSE;
2411 callback_args.line_buf = NULL;
2412 callback_args.line_buf_len = 256;
2413 callback_args.col_widths = NULL;
2415 if (!print_preamble(print_args->stream, cf->filename)) {
2416 destroy_print_stream(print_args->stream);
2417 return CF_PRINT_WRITE_ERROR;
2420 if (print_args->print_summary) {
2421 /* We're printing packet summaries. Allocate the header line buffer
2422 and get the column widths. */
2423 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2425 /* Find the widths for each of the columns - maximum of the
2426 width of the title and the width of the data - and construct
2427 a buffer with a line containing the column titles. */
2428 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2429 cp = &callback_args.header_line_buf[0];
2431 for (i = 0; i < cf->cinfo.num_cols; i++) {
2432 /* Don't pad the last column. */
2433 if (i == cf->cinfo.num_cols - 1)
2434 callback_args.col_widths[i] = 0;
2436 callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
2437 data_width = get_column_char_width(get_column_format(i));
2438 if (data_width > callback_args.col_widths[i])
2439 callback_args.col_widths[i] = data_width;
2442 /* Find the length of the string for this column. */
2443 column_len = (int) strlen(cf->cinfo.col_title[i]);
2444 if (callback_args.col_widths[i] > column_len)
2445 column_len = callback_args.col_widths[i];
2447 /* Make sure there's room in the line buffer for the column; if not,
2448 double its length. */
2449 line_len += column_len + 1; /* "+1" for space */
2450 if (line_len > callback_args.header_line_buf_len) {
2451 cp_off = (int) (cp - callback_args.header_line_buf);
2452 callback_args.header_line_buf_len = 2 * line_len;
2453 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2454 callback_args.header_line_buf_len + 1);
2455 cp = callback_args.header_line_buf + cp_off;
2458 /* Right-justify the packet number column. */
2459 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2460 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2462 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2464 if (i != cf->cinfo.num_cols - 1)
2469 /* Now start out the main line buffer with the same length as the
2470 header line buffer. */
2471 callback_args.line_buf_len = callback_args.header_line_buf_len;
2472 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2473 } /* if (print_summary) */
2475 /* Iterate through the list of packets, printing the packets we were
2477 ret = process_specified_packets(cf, &print_args->range, "Printing",
2478 "selected packets", TRUE, print_packet,
2481 g_free(callback_args.header_line_buf);
2482 g_free(callback_args.line_buf);
2483 g_free(callback_args.col_widths);
2488 /* Completed successfully. */
2492 /* Well, the user decided to abort the printing.
2494 XXX - note that what got generated before they did that
2495 will get printed if we're piping to a print program; we'd
2496 have to write to a file and then hand that to the print
2497 program to make it actually not print anything. */
2501 /* Error while printing.
2503 XXX - note that what got generated before they did that
2504 will get printed if we're piping to a print program; we'd
2505 have to write to a file and then hand that to the print
2506 program to make it actually not print anything. */
2507 destroy_print_stream(print_args->stream);
2508 return CF_PRINT_WRITE_ERROR;
2511 if (!print_finale(print_args->stream)) {
2512 destroy_print_stream(print_args->stream);
2513 return CF_PRINT_WRITE_ERROR;
2516 if (!destroy_print_stream(print_args->stream))
2517 return CF_PRINT_WRITE_ERROR;
2523 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2524 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2530 /* Create the protocol tree, but don't fill in the column information. */
2531 epan_dissect_init(&edt, TRUE, TRUE);
2532 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2534 /* Write out the information in that tree. */
2535 proto_tree_write_pdml(&edt, fh);
2537 epan_dissect_cleanup(&edt);
2543 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2548 fh = ws_fopen(print_args->file, "w");
2550 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2552 write_pdml_preamble(fh, cf->filename);
2555 return CF_PRINT_WRITE_ERROR;
2558 /* Iterate through the list of packets, printing the packets we were
2560 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2561 "selected packets", TRUE,
2562 write_pdml_packet, fh);
2567 /* Completed successfully. */
2571 /* Well, the user decided to abort the printing. */
2575 /* Error while printing. */
2577 return CF_PRINT_WRITE_ERROR;
2580 write_pdml_finale(fh);
2583 return CF_PRINT_WRITE_ERROR;
2586 /* XXX - check for an error */
2593 write_psml_packet(capture_file *cf, frame_data *fdata,
2594 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2599 gboolean proto_tree_needed;
2601 /* Fill in the column information, only create the protocol tree
2602 if having custom columns. */
2603 proto_tree_needed = have_custom_cols(&cf->cinfo);
2604 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2605 col_custom_prime_edt(&edt, &cf->cinfo);
2606 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2607 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2609 /* Write out the information in that tree. */
2610 proto_tree_write_psml(&edt, fh);
2612 epan_dissect_cleanup(&edt);
2618 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2623 fh = ws_fopen(print_args->file, "w");
2625 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2627 write_psml_preamble(fh);
2630 return CF_PRINT_WRITE_ERROR;
2633 /* Iterate through the list of packets, printing the packets we were
2635 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2636 "selected packets", TRUE,
2637 write_psml_packet, fh);
2642 /* Completed successfully. */
2646 /* Well, the user decided to abort the printing. */
2650 /* Error while printing. */
2652 return CF_PRINT_WRITE_ERROR;
2655 write_psml_finale(fh);
2658 return CF_PRINT_WRITE_ERROR;
2661 /* XXX - check for an error */
2668 write_csv_packet(capture_file *cf, frame_data *fdata,
2669 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2674 gboolean proto_tree_needed;
2676 /* Fill in the column information, only create the protocol tree
2677 if having custom columns. */
2678 proto_tree_needed = have_custom_cols(&cf->cinfo);
2679 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2680 col_custom_prime_edt(&edt, &cf->cinfo);
2681 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2682 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2684 /* Write out the information in that tree. */
2685 proto_tree_write_csv(&edt, fh);
2687 epan_dissect_cleanup(&edt);
2693 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2698 fh = ws_fopen(print_args->file, "w");
2700 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2702 write_csv_preamble(fh);
2705 return CF_PRINT_WRITE_ERROR;
2708 /* Iterate through the list of packets, printing the packets we were
2710 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2711 "selected packets", TRUE,
2712 write_csv_packet, fh);
2717 /* Completed successfully. */
2721 /* Well, the user decided to abort the printing. */
2725 /* Error while printing. */
2727 return CF_PRINT_WRITE_ERROR;
2730 write_csv_finale(fh);
2733 return CF_PRINT_WRITE_ERROR;
2736 /* XXX - check for an error */
2743 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
2744 union wtap_pseudo_header *pseudo_header,
2745 const guint8 *pd, void *argsp)
2750 epan_dissect_init(&edt, TRUE, TRUE);
2751 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2752 proto_tree_write_carrays(fdata->num, fh, &edt);
2753 epan_dissect_cleanup(&edt);
2759 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2764 fh = ws_fopen(print_args->file, "w");
2767 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2769 write_carrays_preamble(fh);
2773 return CF_PRINT_WRITE_ERROR;
2776 /* Iterate through the list of packets, printing the packets we were
2778 ret = process_specified_packets(cf, &print_args->range,
2780 "selected packets", TRUE,
2781 write_carrays_packet, fh);
2784 /* Completed successfully. */
2787 /* Well, the user decided to abort the printing. */
2790 /* Error while printing. */
2792 return CF_PRINT_WRITE_ERROR;
2795 write_carrays_finale(fh);
2799 return CF_PRINT_WRITE_ERROR;
2807 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2808 search_direction dir)
2812 mdata.string = string;
2813 mdata.string_len = strlen(string);
2814 return find_packet(cf, match_protocol_tree, &mdata, dir);
2818 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2820 mdata->frame_matched = FALSE;
2821 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2822 mdata->string_len = strlen(mdata->string);
2824 /* Iterate through all the nodes looking for matching text */
2825 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2826 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2830 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2832 match_data *mdata = criterion;
2835 /* Load the frame's data. */
2836 if (!cf_read_frame(cf, fdata)) {
2837 /* Attempt to get the packet failed. */
2841 /* Construct the protocol tree, including the displayed text */
2842 epan_dissect_init(&edt, TRUE, TRUE);
2843 /* We don't need the column information */
2844 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2846 /* Iterate through all the nodes, seeing if they have text that matches. */
2848 mdata->frame_matched = FALSE;
2849 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2850 epan_dissect_cleanup(&edt);
2851 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2855 match_subtree_text(proto_node *node, gpointer data)
2857 match_data *mdata = (match_data *) data;
2858 const gchar *string = mdata->string;
2859 size_t string_len = mdata->string_len;
2860 capture_file *cf = mdata->cf;
2861 field_info *fi = PNODE_FINFO(node);
2862 gchar label_str[ITEM_LABEL_LENGTH];
2869 g_assert(fi && "dissection with an invisible proto tree?");
2871 if (mdata->frame_matched) {
2872 /* We already had a match; don't bother doing any more work. */
2876 /* Don't match invisible entries. */
2877 if (PROTO_ITEM_IS_HIDDEN(node))
2880 /* was a free format label produced? */
2882 label_ptr = fi->rep->representation;
2884 /* no, make a generic label */
2885 label_ptr = label_str;
2886 proto_item_fill_label(fi, label_str);
2889 /* Does that label match? */
2890 label_len = strlen(label_ptr);
2891 for (i = 0; i < label_len; i++) {
2892 c_char = label_ptr[i];
2894 c_char = toupper(c_char);
2895 if (c_char == string[c_match]) {
2897 if (c_match == string_len) {
2898 /* No need to look further; we have a match */
2899 mdata->frame_matched = TRUE;
2907 /* Recurse into the subtree, if it exists */
2908 if (node->first_child != NULL)
2909 proto_tree_children_foreach(node, match_subtree_text, mdata);
2913 cf_find_packet_summary_line(capture_file *cf, const char *string,
2914 search_direction dir)
2918 mdata.string = string;
2919 mdata.string_len = strlen(string);
2920 return find_packet(cf, match_summary_line, &mdata, dir);
2924 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2926 match_data *mdata = criterion;
2927 const gchar *string = mdata->string;
2928 size_t string_len = mdata->string_len;
2930 const char *info_column;
2931 size_t info_column_len;
2932 match_result result = MR_NOTMATCHED;
2938 /* Load the frame's data. */
2939 if (!cf_read_frame(cf, fdata)) {
2940 /* Attempt to get the packet failed. */
2944 /* Don't bother constructing the protocol tree */
2945 epan_dissect_init(&edt, FALSE, FALSE);
2946 /* Get the column information */
2947 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2949 /* Find the Info column */
2950 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2951 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2952 /* Found it. See if we match. */
2953 info_column = edt.pi.cinfo->col_data[colx];
2954 info_column_len = strlen(info_column);
2955 for (i = 0; i < info_column_len; i++) {
2956 c_char = info_column[i];
2958 c_char = toupper(c_char);
2959 if (c_char == string[c_match]) {
2961 if (c_match == string_len) {
2962 result = MR_MATCHED;
2971 epan_dissect_cleanup(&edt);
2978 } cbs_t; /* "Counted byte string" */
2981 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
2982 search_direction dir)
2987 info.data_len = string_size;
2989 /* String or hex search? */
2991 /* String search - what type of string? */
2992 switch (cf->scs_type) {
2994 case SCS_ASCII_AND_UNICODE:
2995 return find_packet(cf, match_ascii_and_unicode, &info, dir);
2998 return find_packet(cf, match_ascii, &info, dir);
3001 return find_packet(cf, match_unicode, &info, dir);
3004 g_assert_not_reached();
3008 return find_packet(cf, match_binary, &info, dir);
3012 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3014 cbs_t *info = criterion;
3015 const guint8 *ascii_text = info->data;
3016 size_t textlen = info->data_len;
3017 match_result result;
3023 /* Load the frame's data. */
3024 if (!cf_read_frame(cf, fdata)) {
3025 /* Attempt to get the packet failed. */
3029 result = MR_NOTMATCHED;
3030 buf_len = fdata->pkt_len;
3032 while (i < buf_len) {
3035 c_char = toupper(c_char);
3036 if (c_char != '\0') {
3037 if (c_char == ascii_text[c_match]) {
3039 if (c_match == textlen) {
3040 result = MR_MATCHED;
3041 cf->search_pos = i; /* Save the position of the last character
3042 for highlighting the field. */
3047 g_assert(i>=c_match);
3048 i -= (guint32)c_match;
3058 match_ascii(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;
3078 while (i < buf_len) {
3081 c_char = toupper(c_char);
3082 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. */
3092 g_assert(i>=c_match);
3093 i -= (guint32)c_match;
3103 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3105 cbs_t *info = criterion;
3106 const guint8 *ascii_text = info->data;
3107 size_t textlen = info->data_len;
3108 match_result result;
3114 /* Load the frame's data. */
3115 if (!cf_read_frame(cf, fdata)) {
3116 /* Attempt to get the packet failed. */
3120 result = MR_NOTMATCHED;
3121 buf_len = fdata->pkt_len;
3123 while (i < buf_len) {
3126 c_char = toupper(c_char);
3127 if (c_char == ascii_text[c_match]) {
3129 if (c_match == textlen) {
3130 result = MR_MATCHED;
3131 cf->search_pos = i; /* Save the position of the last character
3132 for highlighting the field. */
3138 g_assert(i>=(c_match*2));
3139 i -= (guint32)c_match*2;
3148 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3150 cbs_t *info = criterion;
3151 const guint8 *binary_data = info->data;
3152 size_t datalen = info->data_len;
3153 match_result result;
3158 /* Load the frame's data. */
3159 if (!cf_read_frame(cf, fdata)) {
3160 /* Attempt to get the packet failed. */
3164 result = MR_NOTMATCHED;
3165 buf_len = fdata->pkt_len;
3167 while (i < buf_len) {
3168 if (cf->pd[i] == binary_data[c_match]) {
3170 if (c_match == datalen) {
3171 result = MR_MATCHED;
3172 cf->search_pos = i; /* Save the position of the last character
3173 for highlighting the field. */
3178 g_assert(i>=c_match);
3179 i -= (guint32)c_match;
3188 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3189 search_direction dir)
3191 return find_packet(cf, match_dfilter, sfcode, dir);
3195 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3196 search_direction dir)
3201 if (!dfilter_compile(filter, &sfcode)) {
3203 * XXX - this shouldn't happen, as the filter string is machine
3208 if (sfcode == NULL) {
3210 * XXX - this shouldn't happen, as the filter string is machine
3215 result = find_packet(cf, match_dfilter, sfcode, dir);
3216 dfilter_free(sfcode);
3221 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3223 dfilter_t *sfcode = criterion;
3225 match_result result;
3227 /* Load the frame's data. */
3228 if (!cf_read_frame(cf, fdata)) {
3229 /* Attempt to get the packet failed. */
3233 epan_dissect_init(&edt, TRUE, FALSE);
3234 epan_dissect_prime_dfilter(&edt, sfcode);
3235 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3236 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3237 epan_dissect_cleanup(&edt);
3242 cf_find_packet_marked(capture_file *cf, search_direction dir)
3244 return find_packet(cf, match_marked, NULL, dir);
3248 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3250 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3254 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3256 return find_packet(cf, match_time_reference, NULL, dir);
3260 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3262 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3266 find_packet(capture_file *cf,
3267 match_result (*match_function)(capture_file *, frame_data *, void *),
3268 void *criterion, search_direction dir)
3270 frame_data *start_fd;
3273 frame_data *new_fd = NULL;
3274 progdlg_t *progbar = NULL;
3279 GTimeVal start_time;
3280 gchar status_str[100];
3281 int progbar_nextstep;
3282 int progbar_quantum;
3284 match_result result;
3286 start_fd = cf->current_frame;
3287 if (start_fd != NULL) {
3288 /* Iterate through the list of packets, starting at the packet we've
3289 picked, calling a routine to run the filter on the packet, see if
3290 it matches, and stop if so. */
3292 framenum = start_fd->num;
3294 /* Update the progress bar when it gets to this value. */
3295 progbar_nextstep = 0;
3296 /* When we reach the value that triggers a progress bar update,
3297 bump that value by this amount. */
3298 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3299 /* Progress so far. */
3303 g_get_current_time(&start_time);
3305 title = cf->sfilter?cf->sfilter:"";
3307 /* Create the progress bar if necessary.
3308 We check on every iteration of the loop, so that it takes no
3309 longer than the standard time to create it (otherwise, for a
3310 large file, we might take considerably longer than that standard
3311 time in order to get to the next progress bar step). */
3312 if (progbar == NULL)
3313 progbar = delayed_create_progress_dlg("Searching", title,
3314 FALSE, &stop_flag, &start_time, progbar_val);
3316 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3317 when we update it, we have to run the GTK+ main loop to get it
3318 to repaint what's pending, and doing so may involve an "ioctl()"
3319 to see if there's any pending input from an X server, and doing
3320 that for every packet can be costly, especially on a big file. */
3321 if (count >= progbar_nextstep) {
3322 /* let's not divide by zero. I should never be started
3323 * with count == 0, so let's assert that
3325 g_assert(cf->count > 0);
3327 progbar_val = (gfloat) count / cf->count;
3329 if (progbar != NULL) {
3330 g_snprintf(status_str, sizeof(status_str),
3331 "%4u of %u packets", count, cf->count);
3332 update_progress_dlg(progbar, progbar_val, status_str);
3335 progbar_nextstep += progbar_quantum;
3339 /* Well, the user decided to abort the search. Go back to the
3340 frame where we started. */
3345 /* Go past the current frame. */
3346 if (dir == SD_BACKWARD) {
3347 /* Go on to the previous frame. */
3348 if (framenum == 1) {
3350 * XXX - other apps have a bit more of a detailed message
3351 * for this, and instead of offering "OK" and "Cancel",
3352 * they offer things such as "Continue" and "Cancel";
3353 * we need an API for popping up alert boxes with
3354 * {Verb} and "Cancel".
3357 if (prefs.gui_find_wrap)
3359 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3360 framenum = cf->count; /* wrap around */
3364 statusbar_push_temporary_msg("Search reached the beginning.");
3365 framenum = start_fd->num; /* stay on previous packet */
3370 /* Go on to the next frame. */
3371 if (framenum == cf->count) {
3372 if (prefs.gui_find_wrap)
3374 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3375 framenum = 1; /* wrap around */
3379 statusbar_push_temporary_msg("Search reached the end.");
3380 framenum = start_fd->num; /* stay on previous packet */
3385 fdata = frame_data_sequence_find(cf->frames, framenum);
3389 /* Is this packet in the display? */
3390 if (fdata->flags.passed_dfilter) {
3391 /* Yes. Does it match the search criterion? */
3392 result = (*match_function)(cf, fdata, criterion);
3393 if (result == MR_ERROR) {
3394 /* Error; our caller has reported the error. Go back to the frame
3395 where we started. */
3398 } else if (result == MR_MATCHED) {
3399 /* Yes. Go to the new frame. */
3405 if (fdata == start_fd) {
3406 /* We're back to the frame we were on originally, and that frame
3407 doesn't match the search filter. The search failed. */
3412 /* We're done scanning the packets; destroy the progress bar if it
3414 if (progbar != NULL)
3415 destroy_progress_dlg(progbar);
3418 if (new_fd != NULL) {
3419 /* Find and select */
3420 cf->search_in_progress = TRUE;
3421 found = new_packet_list_select_row_from_data(new_fd);
3422 cf->search_in_progress = FALSE;
3423 cf->search_pos = 0; /* Reset the position */
3425 /* We didn't find a row corresponding to this frame.
3426 This means that the frame isn't being displayed currently,
3427 so we can't select it. */
3428 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3429 "%sEnd of capture exceeded!%s\n\n"
3430 "The capture file is probably not fully dissected.",
3431 simple_dialog_primary_start(), simple_dialog_primary_end());
3434 return TRUE; /* success */
3436 return FALSE; /* failure */
3440 cf_goto_frame(capture_file *cf, guint fnumber)
3444 fdata = frame_data_sequence_find(cf->frames, fnumber);
3446 if (fdata == NULL) {
3447 /* we didn't find a packet with that packet number */
3448 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3449 return FALSE; /* we failed to go to that packet */
3451 if (!fdata->flags.passed_dfilter) {
3452 /* that packet currently isn't displayed */
3453 /* XXX - add it to the set of displayed packets? */
3454 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3455 return FALSE; /* we failed to go to that packet */
3458 if (!new_packet_list_select_row_from_data(fdata)) {
3459 /* We didn't find a row corresponding to this frame.
3460 This means that the frame isn't being displayed currently,
3461 so we can't select it. */
3462 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3463 "%sEnd of capture exceeded!%s\n\n"
3464 "The capture file is probably not fully dissected.",
3465 simple_dialog_primary_start(), simple_dialog_primary_end());
3468 return TRUE; /* we got to that packet */
3472 cf_goto_top_frame(void)
3474 /* Find and select */
3475 new_packet_list_select_first_row();
3476 return TRUE; /* we got to that packet */
3480 cf_goto_bottom_frame(void)
3482 /* Find and select */
3483 new_packet_list_select_last_row();
3484 return TRUE; /* we got to that packet */
3488 * Go to frame specified by currently selected protocol tree item.
3491 cf_goto_framenum(capture_file *cf)
3493 header_field_info *hfinfo;
3496 if (cf->finfo_selected) {
3497 hfinfo = cf->finfo_selected->hfinfo;
3499 if (hfinfo->type == FT_FRAMENUM) {
3500 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3502 return cf_goto_frame(cf, framenum);
3509 /* Select the packet on a given row. */
3511 cf_select_packet(capture_file *cf, int row)
3515 /* Get the frame data struct pointer for this frame */
3516 fdata = new_packet_list_get_row_data(row);
3518 if (fdata == NULL) {
3519 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3520 the first entry is added to it by "real_insert_row()", that row
3521 is selected (see "real_insert_row()", in "ui/gtk/gtkclist.c", in both
3522 our version and the vanilla GTK+ version).
3524 This means that a "select-row" signal is emitted; this causes
3525 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3528 "cf_select_packet()" fetches, above, the data associated with the
3529 row that was selected; however, as "gtk_clist_append()", which
3530 called "real_insert_row()", hasn't yet returned, we haven't yet
3531 associated any data with that row, so we get back a null pointer.
3533 We can't assume that there's only one frame in the frame list,
3534 either, as we may be filtering the display.
3536 We therefore assume that, if "row" is 0, i.e. the first row
3537 is being selected, and "cf->first_displayed" equals
3538 "cf->last_displayed", i.e. there's only one frame being
3539 displayed, that frame is the frame we want.
3541 This means we have to set "cf->first_displayed" and
3542 "cf->last_displayed" before adding the row to the
3543 GtkCList; see the comment in "add_packet_to_packet_list()". */
3545 if (row == 0 && cf->first_displayed == cf->last_displayed)
3546 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3549 /* If fdata _still_ isn't set simply give up. */
3550 if (fdata == NULL) {
3554 /* Get the data in that frame. */
3555 if (!cf_read_frame (cf, fdata)) {
3559 /* Record that this frame is the current frame. */
3560 cf->current_frame = fdata;
3561 cf->current_row = row;
3563 /* Create the logical protocol tree. */
3564 if (cf->edt != NULL)
3565 epan_dissect_free(cf->edt);
3567 /* We don't need the columns here. */
3568 cf->edt = epan_dissect_new(TRUE, TRUE);
3570 tap_build_interesting(cf->edt);
3571 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3574 dfilter_macro_build_ftv_cache(cf->edt->tree);
3576 cf_callback_invoke(cf_cb_packet_selected, cf);
3579 /* Unselect the selected packet, if any. */
3581 cf_unselect_packet(capture_file *cf)
3583 /* Destroy the epan_dissect_t for the unselected packet. */
3584 if (cf->edt != NULL) {
3585 epan_dissect_free(cf->edt);
3589 /* No packet is selected. */
3590 cf->current_frame = NULL;
3591 cf->current_row = 0;
3593 cf_callback_invoke(cf_cb_packet_unselected, cf);
3595 /* No protocol tree means no selected field. */
3596 cf_unselect_field(cf);
3599 /* Unset the selected protocol tree field, if any. */
3601 cf_unselect_field(capture_file *cf)
3603 cf->finfo_selected = NULL;
3605 cf_callback_invoke(cf_cb_field_unselected, cf);
3609 * Mark a particular frame.
3612 cf_mark_frame(capture_file *cf, frame_data *frame)
3614 if (! frame->flags.marked) {
3615 frame->flags.marked = TRUE;
3616 if (cf->count > cf->marked_count)
3622 * Unmark a particular frame.
3625 cf_unmark_frame(capture_file *cf, frame_data *frame)
3627 if (frame->flags.marked) {
3628 frame->flags.marked = FALSE;
3629 if (cf->marked_count > 0)
3635 * Ignore a particular frame.
3638 cf_ignore_frame(capture_file *cf, frame_data *frame)
3640 if (! frame->flags.ignored) {
3641 frame->flags.ignored = TRUE;
3642 if (cf->count > cf->ignored_count)
3643 cf->ignored_count++;
3648 * Un-ignore a particular frame.
3651 cf_unignore_frame(capture_file *cf, frame_data *frame)
3653 if (frame->flags.ignored) {
3654 frame->flags.ignored = FALSE;
3655 if (cf->ignored_count > 0)
3656 cf->ignored_count--;
3661 * Read the comment in SHB block
3665 cf_read_shb_comment(capture_file *cf)
3667 wtapng_section_t *shb_inf;
3668 const gchar *temp_str;
3670 /* Get info from SHB */
3671 shb_inf = wtap_file_get_shb_info(cf->wth);
3674 temp_str = shb_inf->opt_comment;
3682 cf_update_capture_comment(capture_file *cf, gchar *comment)
3684 wtapng_section_t *shb_inf;
3686 /* Get info from SHB */
3687 shb_inf = wtap_file_get_shb_info(cf->wth);
3689 /* See if the comment has changed or not */
3690 if (shb_inf && shb_inf->opt_comment) {
3691 if (strcmp(shb_inf->opt_comment, comment) == 0) {
3697 /* The comment has changed, let's update it */
3698 wtap_write_shb_comment(cf->wth, comment);
3699 /* Mark the file as having unsaved changes */
3700 cf->unsaved_changes = TRUE;
3707 } save_callback_args_t;
3710 * Save a capture to a file, in a particular format, saving either
3711 * all packets, all currently-displayed packets, or all marked packets.
3713 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3714 * up a message box for the failure.
3717 save_packet(capture_file *cf _U_, frame_data *fdata,
3718 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3721 save_callback_args_t *args = argsp;
3722 struct wtap_pkthdr hdr;
3725 /* init the wtap header for saving */
3726 /* XXX - these are the only flags that correspond to data that we have
3727 in the frame_data structure and that matter on a per-packet basis.
3729 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
3730 and "on the wire" lengths, or it doesn't.
3732 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
3735 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
3736 from the packet flags. */
3737 hdr.presence_flags = 0;
3738 if (fdata->flags.has_ts)
3739 hdr.presence_flags |= WTAP_HAS_TS;
3740 if (fdata->flags.has_ts)
3741 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
3742 hdr.ts.secs = fdata->abs_ts.secs;
3743 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3744 hdr.caplen = fdata->cap_len;
3745 hdr.len = fdata->pkt_len;
3746 hdr.pkt_encap = fdata->lnk_t;
3748 hdr.interface_id = fdata->interface_id; /* identifier of the interface. */
3750 hdr.opt_comment = fdata->opt_comment; /* NULL if not available */
3753 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
3755 /* and save the packet */
3756 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3758 /* Wiretap error. */
3761 case WTAP_ERR_UNSUPPORTED_ENCAP:
3763 * This is a problem with the particular frame we're writing;
3764 * note that, and give the frame number.
3766 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3767 "Frame %u has a network type that can't be saved in a \"%s\" file.",
3768 fdata->num, wtap_file_type_string(args->file_type));
3772 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3773 "An error occurred while writing to the file \"%s\": %s.",
3774 args->fname, wtap_strerror(err));
3779 write_failure_alert_box(args->fname, err);
3787 * Can this capture file be saved in any format except by copying the raw data?
3790 cf_can_save_as(capture_file *cf)
3794 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
3795 /* To save a file with Wiretap, Wiretap has to handle that format,
3796 and its code to handle that format must be able to write a file
3797 with this file's encapsulation type. */
3798 if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
3799 /* OK, we can write it out in this type. */
3804 /* No, we couldn't save it in any format. */
3809 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3811 gchar *from_filename;
3815 save_callback_args_t callback_args;
3817 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
3819 /* don't write over an existing file. */
3820 /* this should've been already checked by our caller, just to be sure... */
3821 if (file_exists(fname)) {
3822 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3823 "%sCapture file: \"%s\" already exists!%s\n\n"
3824 "Please choose a different filename.",
3825 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3829 packet_range_process_init(range);
3831 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3832 /* We're not filtering packets, and we're saving it in the format
3833 it's already in, so we can just move or copy the raw data. */
3835 if (cf->is_tempfile) {
3836 /* The file being saved is a temporary file from a live
3837 capture, so it doesn't need to stay around under that name;
3838 first, try renaming the capture buffer file to the new name. */
3840 if (ws_rename(cf->filename, fname) == 0) {
3841 /* That succeeded - there's no need to copy the source file. */
3842 from_filename = NULL;
3845 if (errno == EXDEV) {
3846 /* They're on different file systems, so we have to copy the
3849 from_filename = cf->filename;
3851 /* The rename failed, but not because they're on different
3852 file systems - put up an error message. (Or should we
3853 just punt and try to copy? The only reason why I'd
3854 expect the rename to fail and the copy to succeed would
3855 be if we didn't have permission to remove the file from
3856 the temporary directory, and that might be fixable - but
3857 is it worth requiring the user to go off and fix it?) */
3858 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3859 file_rename_error_message(errno), fname);
3865 from_filename = cf->filename;
3868 /* It's a permanent file, so we should copy it, and not remove the
3871 from_filename = cf->filename;
3875 /* Copy the file, if we haven't moved it. */
3876 if (!copy_file_binary_mode(from_filename, fname))
3880 /* Either we're filtering packets, or we're saving in a different
3881 format; we can't do that by copying or moving the capture file,
3882 we have to do it by writing the packets out in Wiretap. */
3884 wtapng_section_t *shb_hdr = NULL;
3885 wtapng_iface_descriptions_t *idb_inf = NULL;
3887 shb_hdr = wtap_file_get_shb_info(cf->wth);
3888 idb_inf = wtap_file_get_idb_info(cf->wth);
3890 pdh = wtap_dump_open_ng(fname, save_format, cf->lnk_t, cf->snap,
3891 compressed, shb_hdr, idb_inf, &err);
3896 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3900 /* Add address resolution */
3901 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
3903 /* XXX - we let the user save a subset of the packets.
3905 If we do that, should we make that file the current file? If so,
3906 it means we can no longer get at the other packets. What does
3909 /* Iterate through the list of packets, processing the packets we were
3912 XXX - we've already called "packet_range_process_init(range)", but
3913 "process_specified_packets()" will do it again. Fortunately,
3914 that's harmless in this case, as we haven't done anything to
3915 "range" since we initialized it. */
3916 callback_args.pdh = pdh;
3917 callback_args.fname = fname;
3918 callback_args.file_type = save_format;
3919 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3920 TRUE, save_packet, &callback_args)) {
3923 /* Completed successfully. */
3927 /* The user decided to abort the saving.
3928 XXX - remove the output file? */
3932 /* Error while saving. */
3933 wtap_dump_close(pdh, &err);
3937 if (!wtap_dump_close(pdh, &err)) {
3938 cf_close_failure_alert_box(fname, err);
3943 cf_callback_invoke(cf_cb_file_save_finished, NULL);
3945 if (packet_range_process_all(range)) {
3946 /* We saved the entire capture, not just some packets from it.
3947 Open and read the file we saved it to.
3949 XXX - this is somewhat of a waste; we already have the
3950 packets, all this gets us is updated file type information
3951 (which we could just stuff into "cf"), and having the new
3952 file be the one we have opened and from which we're reading
3953 the data, and it means we have to spend time opening and
3954 reading the file, which could be a significant amount of
3955 time if the file is large. */
3956 cf->unsaved_changes = FALSE;
3958 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3959 /* XXX - report errors if this fails?
3960 What should we return if it fails or is aborted? */
3962 switch (cf_read(cf, TRUE)) {
3966 /* Just because we got an error, that doesn't mean we were unable
3967 to read any of the file; we handle what we could get from the
3971 case CF_READ_ABORTED:
3972 /* The user bailed out of re-reading the capture file; the
3973 capture file has been closed - just return (without
3974 changing any menu settings; "cf_close()" set them
3975 correctly for the "no capture file open" state). */
3978 cf_callback_invoke(cf_cb_file_save_reload_finished, cf);
3984 cf_callback_invoke(cf_cb_file_save_failed, NULL);
3989 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3990 gboolean for_writing, int file_type)
3993 /* Wiretap error. */
3996 case WTAP_ERR_NOT_REGULAR_FILE:
3997 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3998 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4002 case WTAP_ERR_RANDOM_OPEN_PIPE:
4003 /* Seen only when opening a capture file for reading. */
4004 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4005 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.\n"
4006 "To capture from a pipe or FIFO use wireshark -i -",
4010 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
4011 /* Seen only when opening a capture file for reading. */
4012 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4013 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
4017 case WTAP_ERR_UNSUPPORTED:
4018 /* Seen only when opening a capture file for reading. */
4019 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4020 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
4022 filename, err_info);
4026 case WTAP_ERR_CANT_WRITE_TO_PIPE:
4027 /* Seen only when opening a capture file for writing. */
4028 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4029 "The file \"%s\" is a pipe, and %s capture files can't be "
4030 "written to a pipe.",
4031 filename, wtap_file_type_string(file_type));
4034 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
4035 /* Seen only when opening a capture file for writing. */
4036 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4037 "Wireshark doesn't support writing capture files in that format.");
4040 case WTAP_ERR_UNSUPPORTED_ENCAP:
4042 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4043 "Wireshark can't save this capture in that format.");
4045 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4046 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
4048 filename, err_info);
4053 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
4055 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4056 "Wireshark can't save this capture in that format.");
4058 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4059 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
4064 case WTAP_ERR_BAD_FILE:
4065 /* Seen only when opening a capture file for reading. */
4066 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4067 "The file \"%s\" appears to be damaged or corrupt.\n"
4069 filename, err_info);
4073 case WTAP_ERR_CANT_OPEN:
4075 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4076 "The file \"%s\" could not be created for some unknown reason.",
4079 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4080 "The file \"%s\" could not be opened for some unknown reason.",
4085 case WTAP_ERR_SHORT_READ:
4086 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4087 "The file \"%s\" appears to have been cut short"
4088 " in the middle of a packet or other data.",
4092 case WTAP_ERR_SHORT_WRITE:
4093 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4094 "A full header couldn't be written to the file \"%s\".",
4098 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4099 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4100 "This file type cannot be written as a compressed file.");
4103 case WTAP_ERR_DECOMPRESS:
4104 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4105 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
4106 "(%s)", filename, err_info);
4111 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4112 "The file \"%s\" could not be %s: %s.",
4114 for_writing ? "created" : "opened",
4115 wtap_strerror(err));
4120 open_failure_alert_box(filename, err, for_writing);
4125 file_rename_error_message(int err)
4128 static char errmsg_errno[1024+1];
4133 errmsg = "The path to the file \"%s\" doesn't exist.";
4137 errmsg = "You don't have permission to move the capture file to \"%s\".";
4141 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4142 "The file \"%%s\" could not be moved: %s.",
4143 wtap_strerror(err));
4144 errmsg = errmsg_errno;
4150 /* Check for write errors - if the file is being written to an NFS server,
4151 a write error may not show up until the file is closed, as NFS clients
4152 might not send writes to the server until the "write()" call finishes,
4153 so that the write may fail on the server but the "write()" may succeed. */
4155 cf_close_failure_alert_box(const char *filename, int err)
4158 /* Wiretap error. */
4161 case WTAP_ERR_CANT_CLOSE:
4162 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4163 "The file \"%s\" couldn't be closed for some unknown reason.",
4167 case WTAP_ERR_SHORT_WRITE:
4168 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4169 "Not all the packets could be written to the file \"%s\".",
4174 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4175 "An error occurred while closing the file \"%s\": %s.",
4176 filename, wtap_strerror(err));
4181 We assume that a close error from the OS is really a write error. */
4182 write_failure_alert_box(filename, err);
4186 /* Reload the current capture file. */
4188 cf_reload(capture_file *cf) {
4190 gboolean is_tempfile;
4193 /* If the file could be opened, "cf_open()" calls "cf_close()"
4194 to get rid of state for the old capture file before filling in state
4195 for the new capture file. "cf_close()" will remove the file if
4196 it's a temporary file; we don't want that to happen (for one thing,
4197 it'd prevent subsequent reopens from working). Remember whether it's
4198 a temporary file, mark it as not being a temporary file, and then
4199 reopen it as the type of file it was.
4201 Also, "cf_close()" will free "cf->filename", so we must make
4202 a copy of it first. */
4203 filename = g_strdup(cf->filename);
4204 is_tempfile = cf->is_tempfile;
4205 cf->is_tempfile = FALSE;
4206 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4207 switch (cf_read(cf, FALSE)) {
4211 /* Just because we got an error, that doesn't mean we were unable
4212 to read any of the file; we handle what we could get from the
4216 case CF_READ_ABORTED:
4217 /* The user bailed out of re-reading the capture file; the
4218 capture file has been closed - just free the capture file name
4219 string and return (without changing the last containing
4225 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4226 Instead, the file was left open, so we should restore "cf->is_tempfile"
4229 XXX - change the menu? Presumably "cf_open()" will do that;
4230 make sure it does! */
4231 cf->is_tempfile = is_tempfile;
4233 /* "cf_open()" made a copy of the file name we handed it, so
4234 we should free up our copy. */
4244 * indent-tabs-mode: nil
4247 * ex: set shiftwidth=2 tabstop=8 expandtab:
4248 * :indentSize=2:tabSize=8:noTabs=true: