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 /* If it's a temporary capture buffer file, mark it as not saved. */
310 cf->user_saved = !is_tempfile;
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".
369 cf_reset_state(capture_file *cf)
371 /* Die if we're in the middle of reading a file. */
372 g_assert(cf->state != FILE_READ_IN_PROGRESS);
378 /* We have no file open... */
379 if (cf->filename != NULL) {
380 /* If it's a temporary file, remove it. */
382 ws_unlink(cf->filename);
383 g_free(cf->filename);
386 /* ...which means we have nothing to save. */
387 cf->user_saved = FALSE;
389 dfilter_free(cf->rfcode);
391 if (cf->frames != NULL) {
392 free_frame_data_sequence(cf->frames);
395 #ifdef WANT_PACKET_EDITOR
396 if (cf->edited_frames) {
397 g_tree_destroy(cf->edited_frames);
398 cf->edited_frames = NULL;
401 cf_unselect_packet(cf); /* nothing to select */
402 cf->first_displayed = 0;
403 cf->last_displayed = 0;
405 /* No frames, no frame selected, no field in that frame selected. */
407 cf->current_frame = 0;
409 cf->finfo_selected = NULL;
411 /* Clear the packet list. */
412 new_packet_list_freeze();
413 new_packet_list_clear();
414 new_packet_list_thaw();
417 nstime_set_zero(&cf->elapsed_time);
419 reset_tap_listeners();
421 /* We have no file open. */
422 cf->state = FILE_CLOSED;
424 fileset_file_closed();
427 /* Reset everything to a pristine state */
429 cf_close(capture_file *cf)
431 /* do GUI things even if file is already closed,
432 * e.g. to cleanup things if a capture couldn't be started */
433 cf_callback_invoke(cf_cb_file_closing, cf);
435 /* close things, if not already closed before */
436 if(cf->state != FILE_CLOSED) {
437 color_filters_cleanup();
439 cleanup_dissection();
442 cf_callback_invoke(cf_cb_file_closed, cf);
445 /* an out of memory exception occured, wait for a user button press to exit */
446 static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
452 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
456 progbar_val = (gfloat) file_pos / (gfloat) size;
457 if (progbar_val > 1.0) {
459 /* The file probably grew while we were reading it.
460 * Update file size, and try again.
462 size = wtap_file_size(cf->wth, NULL);
465 progbar_val = (gfloat) file_pos / (gfloat) size;
467 /* If it's still > 1, either "wtap_file_size()" failed (in which
468 * case there's not much we can do about it), or the file
469 * *shrank* (in which case there's not much we can do about
470 * it); just clip the progress value at 1.0.
472 if (progbar_val > 1.0f)
476 g_snprintf(status_str, status_size,
477 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
478 file_pos / 1024, size / 1024);
484 cf_read(capture_file *cf, gboolean from_save)
488 const gchar *name_ptr;
490 char errmsg_errno[1024+1];
493 progdlg_t *volatile progbar = NULL;
495 volatile gint64 size;
496 volatile float progbar_val;
498 gchar status_str[100];
499 volatile gint64 progbar_nextstep;
500 volatile gint64 progbar_quantum;
502 gboolean filtering_tap_listeners;
504 volatile int count = 0;
506 volatile int displayed_once = 0;
510 /* Compile the current display filter.
511 * We assume this will not fail since cf->dfilter is only set in
512 * cf_filter IFF the filter was valid.
514 compiled = dfilter_compile(cf->dfilter, &dfcode);
515 g_assert(!cf->dfilter || (compiled && dfcode));
517 /* Do we have any tap listeners with filters? */
518 filtering_tap_listeners = have_filtering_tap_listeners();
520 /* Get the union of the flags for all tap listeners. */
521 tap_flags = union_of_tap_listener_flags();
523 reset_tap_listeners();
525 name_ptr = get_basename(cf->filename);
527 if (from_save == FALSE)
528 cf_callback_invoke(cf_cb_file_read_started, cf);
530 cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr);
532 /* Find the size of the file. */
533 size = wtap_file_size(cf->wth, NULL);
535 /* Update the progress bar when it gets to this value. */
536 progbar_nextstep = 0;
537 /* When we reach the value that triggers a progress bar update,
538 bump that value by this amount. */
540 progbar_quantum = size/N_PROGBAR_UPDATES;
541 if (progbar_quantum < MIN_QUANTUM)
542 progbar_quantum = MIN_QUANTUM;
545 /* Progress so far. */
548 /* The packet list window will be empty untill the file is completly loaded */
549 new_packet_list_freeze();
552 g_get_current_time(&start_time);
554 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
557 file_pos = wtap_read_so_far(cf->wth);
559 /* Create the progress bar if necessary.
560 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
562 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
563 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
564 if (from_save == FALSE)
565 progbar = delayed_create_progress_dlg("Loading", name_ptr,
566 TRUE, &stop_flag, &start_time, progbar_val);
568 progbar = delayed_create_progress_dlg("Saving", name_ptr,
569 TRUE, &stop_flag, &start_time, progbar_val);
572 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
573 when we update it, we have to run the GTK+ main loop to get it
574 to repaint what's pending, and doing so may involve an "ioctl()"
575 to see if there's any pending input from an X server, and doing
576 that for every packet can be costly, especially on a big file. */
577 if (file_pos >= progbar_nextstep) {
578 if (progbar != NULL) {
579 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
580 /* update the packet bar content on the first run or frequently on very large files */
582 if (progbar_quantum > 500000 || displayed_once == 0) {
583 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
585 packets_bar_update();
588 #endif /* HAVE_LIBPCAP */
589 update_progress_dlg(progbar, progbar_val, status_str);
591 progbar_nextstep += progbar_quantum;
596 /* Well, the user decided to abort the read. He/She will be warned and
597 it might be enough for him/her to work with the already loaded
599 This is especially true for very large capture files, where you don't
600 want to wait loading the whole file (which may last minutes or even
601 hours even on fast machines) just to see that it was the wrong file. */
605 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
607 CATCH(OutOfMemoryError) {
610 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
611 "%sOut Of Memory!%s\n"
613 "Sorry, but Wireshark has to terminate now!\n"
615 "Some infos / workarounds can be found at:\n"
616 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
617 simple_dialog_primary_start(), simple_dialog_primary_end());
618 /* we have to terminate, as we cannot recover from the memory error */
619 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
621 main_window_update();
622 /* XXX - how to avoid a busy wait? */
630 /* Cleanup and release all dfilter resources */
632 dfilter_free(dfcode);
635 /* We're done reading the file; destroy the progress bar if it was created. */
637 destroy_progress_dlg(progbar);
639 /* We're done reading sequentially through the file. */
640 cf->state = FILE_READ_DONE;
642 /* Close the sequential I/O side, to free up memory it requires. */
643 wtap_sequential_close(cf->wth);
645 /* Allow the protocol dissectors to free up memory that they
646 * don't need after the sequential run-through of the packets. */
647 postseq_cleanup_all_protocols();
649 /* compute the time it took to load the file */
650 compute_elapsed(&start_time);
652 /* Set the file encapsulation type now; we don't know what it is until
653 we've looked at all the packets, as we don't know until then whether
654 there's more than one type (and thus whether it's
655 WTAP_ENCAP_PER_PACKET). */
656 cf->lnk_t = wtap_file_encap(cf->wth);
658 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
661 new_packet_list_thaw();
662 if (from_save == FALSE)
663 cf_callback_invoke(cf_cb_file_read_finished, cf);
665 cf_callback_invoke(cf_cb_file_save_finished, cf);
667 /* If we have any displayed packets to select, select the first of those
668 packets by making the first row the selected row. */
669 if (cf->first_displayed != 0){
670 new_packet_list_select_first_row();
674 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
675 "%sFile loading was cancelled!%s\n"
677 "The remaining packets in the file were discarded.\n"
679 "As a lot of packets from the original file will be missing,\n"
680 "remember to be careful when saving the current content to a file.\n",
681 simple_dialog_primary_start(), simple_dialog_primary_end());
682 return CF_READ_ERROR;
686 /* Put up a message box noting that the read failed somewhere along
687 the line. Don't throw out the stuff we managed to read, though,
691 case WTAP_ERR_UNSUPPORTED:
692 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
693 "The capture file contains record data that TShark doesn't support.\n(%s)",
696 errmsg = errmsg_errno;
699 case WTAP_ERR_UNSUPPORTED_ENCAP:
700 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
701 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
704 errmsg = errmsg_errno;
707 case WTAP_ERR_CANT_READ:
708 errmsg = "An attempt to read from the capture file failed for"
709 " some unknown reason.";
712 case WTAP_ERR_SHORT_READ:
713 errmsg = "The capture file appears to have been cut short"
714 " in the middle of a packet.";
717 case WTAP_ERR_BAD_FILE:
718 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
719 "The capture file appears to be damaged or corrupt.\n(%s)",
722 errmsg = errmsg_errno;
725 case WTAP_ERR_DECOMPRESS:
726 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
727 "The compressed capture file appears to be damaged or corrupt.\n"
730 errmsg = errmsg_errno;
734 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
735 "An error occurred while reading the"
736 " capture file: %s.", wtap_strerror(err));
737 errmsg = errmsg_errno;
740 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
741 return CF_READ_ERROR;
748 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
750 cf_status_t cf_status;
752 cf_status = cf_open(cf, fname, is_tempfile, err);
757 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
759 gint64 data_offset = 0;
761 volatile int newly_displayed_packets = 0;
763 gboolean filtering_tap_listeners;
767 /* Compile the current display filter.
768 * We assume this will not fail since cf->dfilter is only set in
769 * cf_filter IFF the filter was valid.
771 compiled = dfilter_compile(cf->dfilter, &dfcode);
772 g_assert(!cf->dfilter || (compiled && dfcode));
774 /* Do we have any tap listeners with filters? */
775 filtering_tap_listeners = have_filtering_tap_listeners();
777 /* Get the union of the flags for all tap listeners. */
778 tap_flags = union_of_tap_listener_flags();
782 new_packet_list_check_end();
783 /* Don't freeze/thaw the list when doing live capture */
784 /*new_packet_list_freeze();*/
786 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
788 while (to_read != 0) {
789 wtap_cleareof(cf->wth);
790 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
793 if (cf->state == FILE_READ_ABORTED) {
794 /* Well, the user decided to exit Wireshark. Break out of the
795 loop, and let the code below (which is called even if there
796 aren't any packets left to read) exit. */
800 if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
801 data_offset) != -1) {
802 newly_displayed_packets++;
805 CATCH(OutOfMemoryError) {
808 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
809 "%sOut Of Memory!%s\n"
811 "Sorry, but Wireshark has to terminate now!\n"
813 "The capture file is not lost, it can be found at:\n"
816 "Some infos / workarounds can be found at:\n"
817 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
818 simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
819 /* we have to terminate, as we cannot recover from the memory error */
820 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
822 main_window_update();
823 /* XXX - how to avoid a busy wait? */
826 /* Don't freeze/thaw the list when doing live capture */
827 /*new_packet_list_thaw();*/
828 return CF_READ_ABORTED;
834 /* Cleanup and release all dfilter resources */
836 dfilter_free(dfcode);
839 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
840 cf->count, cf->state, *err);*/
842 /* Don't freeze/thaw the list when doing live capture */
843 /*new_packet_list_thaw();*/
844 /* With the new packet list the first packet
845 * isn't automatically selected.
847 if(!cf->current_frame)
848 new_packet_list_select_first_row();
850 /* moving to the end of the packet list - if the user requested so and
851 we have some new packets. */
852 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
853 new_packet_list_moveto_end();
855 if (cf->state == FILE_READ_ABORTED) {
856 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
857 so that our caller can kill off the capture child process;
858 this will cause an EOF on the pipe from the child, so
859 "cf_finish_tail()" will be called, and it will clean up
861 return CF_READ_ABORTED;
862 } else if (*err != 0) {
863 /* We got an error reading the capture file.
864 XXX - pop up a dialog box instead? */
865 g_warning("Error \"%s\" while reading: \"%s\"\n",
866 wtap_strerror(*err), cf->filename);
868 return CF_READ_ERROR;
874 cf_fake_continue_tail(capture_file *cf) {
875 cf->state = FILE_READ_DONE;
879 cf_finish_tail(capture_file *cf, int *err)
884 gboolean filtering_tap_listeners;
888 /* Compile the current display filter.
889 * We assume this will not fail since cf->dfilter is only set in
890 * cf_filter IFF the filter was valid.
892 compiled = dfilter_compile(cf->dfilter, &dfcode);
893 g_assert(!cf->dfilter || (compiled && dfcode));
895 /* Do we have any tap listeners with filters? */
896 filtering_tap_listeners = have_filtering_tap_listeners();
898 /* Get the union of the flags for all tap listeners. */
899 tap_flags = union_of_tap_listener_flags();
901 if(cf->wth == NULL) {
903 return CF_READ_ERROR;
906 new_packet_list_check_end();
907 /* Don't freeze/thaw the list when doing live capture */
908 /*new_packet_list_freeze();*/
910 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
911 if (cf->state == FILE_READ_ABORTED) {
912 /* Well, the user decided to abort the read. Break out of the
913 loop, and let the code below (which is called even if there
914 aren't any packets left to read) exit. */
917 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
920 /* Cleanup and release all dfilter resources */
922 dfilter_free(dfcode);
925 /* Don't freeze/thaw the list when doing live capture */
926 /*new_packet_list_thaw();*/
928 if (cf->state == FILE_READ_ABORTED) {
929 /* Well, the user decided to abort the read. We're only called
930 when the child capture process closes the pipe to us (meaning
931 it's probably exited), so we can just close the capture
932 file; we return CF_READ_ABORTED so our caller can do whatever
933 is appropriate when that happens. */
935 return CF_READ_ABORTED;
938 if (auto_scroll_live && cf->count != 0)
939 new_packet_list_moveto_end();
941 /* We're done reading sequentially through the file. */
942 cf->state = FILE_READ_DONE;
944 /* We're done reading sequentially through the file; close the
945 sequential I/O side, to free up memory it requires. */
946 wtap_sequential_close(cf->wth);
948 /* Allow the protocol dissectors to free up memory that they
949 * don't need after the sequential run-through of the packets. */
950 postseq_cleanup_all_protocols();
952 /* Set the file encapsulation type now; we don't know what it is until
953 we've looked at all the packets, as we don't know until then whether
954 there's more than one type (and thus whether it's
955 WTAP_ENCAP_PER_PACKET). */
956 cf->lnk_t = wtap_file_encap(cf->wth);
959 /* We got an error reading the capture file.
960 XXX - pop up a dialog box? */
961 return CF_READ_ERROR;
966 #endif /* HAVE_LIBPCAP */
969 cf_get_display_name(capture_file *cf)
971 const gchar *displayname;
973 /* Return a name to use in displays */
974 if (!cf->is_tempfile) {
975 /* Get the last component of the file name, and use that. */
977 displayname = get_basename(cf->filename);
979 displayname="(No file)";
982 /* The file we read is a temporary file from a live capture;
983 we don't mention its name. */
985 displayname = cf->source;
987 displayname = "(Untitled)";
993 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
999 cf->source = g_strdup(source);
1001 cf->source = g_strdup("");
1005 const gchar *cf_get_tempfile_source(capture_file *cf) {
1013 /* XXX - use a macro instead? */
1015 cf_get_packet_count(capture_file *cf)
1020 /* XXX - use a macro instead? */
1022 cf_set_packet_count(capture_file *cf, int packet_count)
1024 cf->count = packet_count;
1027 /* XXX - use a macro instead? */
1029 cf_is_tempfile(capture_file *cf)
1031 return cf->is_tempfile;
1034 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1036 cf->is_tempfile = is_tempfile;
1040 /* XXX - use a macro instead? */
1041 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1043 cf->drops_known = drops_known;
1046 /* XXX - use a macro instead? */
1047 void cf_set_drops(capture_file *cf, guint32 drops)
1052 /* XXX - use a macro instead? */
1053 gboolean cf_get_drops_known(capture_file *cf)
1055 return cf->drops_known;
1058 /* XXX - use a macro instead? */
1059 guint32 cf_get_drops(capture_file *cf)
1064 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1066 cf->rfcode = rfcode;
1070 find_and_mark_frame_depended_upon(gpointer data, gpointer user_data)
1072 frame_data *dependent_fd;
1073 guint32 dependent_frame = GPOINTER_TO_UINT(data);
1074 capture_file *cf = (capture_file *)user_data;
1076 dependent_fd = frame_data_sequence_find(cf->frames, dependent_frame);
1077 dependent_fd->flags.dependent_of_displayed = 1;
1081 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1082 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1084 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1086 gboolean add_to_packet_list)
1088 gboolean create_proto_tree = FALSE;
1093 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1095 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1096 &first_ts, &prev_dis_ts, &prev_cap_ts);
1099 + we have a display filter and are re-applying it;
1100 + we have tap listeners with filters;
1101 + we have tap listeners that require a protocol tree;
1103 allocate a protocol tree root node, so that we'll construct
1104 a protocol tree against which a filter expression can be
1106 if ((dfcode != NULL && refilter) ||
1107 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1108 create_proto_tree = TRUE;
1110 /* Dissect the frame. */
1111 epan_dissect_init(&edt, create_proto_tree, FALSE);
1113 if (dfcode != NULL && refilter) {
1114 epan_dissect_prime_dfilter(&edt, dfcode);
1117 tap_queue_init(&edt);
1118 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1119 tap_push_tapped_queue(&edt);
1121 /* If we have a display filter, apply it if we're refiltering, otherwise
1122 leave the "passed_dfilter" flag alone.
1124 If we don't have a display filter, set "passed_dfilter" to 1. */
1125 if (dfcode != NULL) {
1127 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1129 /* This frame passed the display filter but it may depend on other
1130 * (potentially not displayed) frames. Find those frames and mark them
1133 g_slist_foreach(edt.pi.dependent_frames, find_and_mark_frame_depended_upon, cf);
1136 fdata->flags.passed_dfilter = 1;
1138 /* We're done with this list */
1139 g_slist_free(edt.pi.dependent_frames);
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 (!cf_read_frame(cf, fdata))
1817 break; /* error reading the frame */
1819 /* If the previous frame is displayed, and we haven't yet seen the
1820 selected frame, remember that frame - it's the closest one we've
1821 yet seen before the selected frame. */
1822 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1823 preceding_frame_num = prev_frame_num;
1824 preceding_frame = prev_frame;
1826 add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1827 tap_flags, &cf->pseudo_header, cf->pd,
1829 add_to_packet_list);
1831 /* If this frame is displayed, and this is the first frame we've
1832 seen displayed after the selected frame, remember this frame -
1833 it's the closest one we've yet seen at or after the selected
1835 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1836 following_frame_num = fdata->num;
1837 following_frame = fdata;
1839 if (fdata == selected_frame) {
1840 selected_frame_seen = TRUE;
1841 if (fdata->flags.passed_dfilter)
1842 selected_frame_num = fdata->num;
1845 /* Remember this frame - it'll be the previous frame
1846 on the next pass through the loop. */
1847 prev_frame_num = fdata->num;
1851 /* We are done redissecting the packet list. */
1852 cf->redissecting = FALSE;
1855 /* Clear out what remains of the visited flags and per-frame data
1858 XXX - that may cause various forms of bogosity when dissecting
1859 these frames, as they won't have been seen by this sequential
1860 pass, but the only alternative I see is to keep scanning them
1861 even though the user requested that the scan stop, and that
1862 would leave the user stuck with an Wireshark grinding on
1863 until it finishes. Should we just stick them with that? */
1864 for (; framenum <= cf->count; framenum++) {
1865 fdata = frame_data_sequence_find(cf->frames, framenum);
1866 fdata->flags.visited = 0;
1867 frame_data_cleanup(fdata);
1871 /* We're done filtering the packets; destroy the progress bar if it
1873 if (progbar != NULL)
1874 destroy_progress_dlg(progbar);
1876 /* Unfreeze the packet list. */
1877 if (!add_to_packet_list)
1878 new_packet_list_recreate_visible_rows();
1880 /* Compute the time it took to filter the file */
1881 compute_elapsed(&start_time);
1883 new_packet_list_thaw();
1885 if (selected_frame_num == -1) {
1886 /* The selected frame didn't pass the filter. */
1887 if (selected_frame == NULL) {
1888 /* That's because there *was* no selected frame. Make the first
1889 displayed frame the current frame. */
1890 selected_frame_num = 0;
1892 /* Find the nearest displayed frame to the selected frame (whether
1893 it's before or after that frame) and make that the current frame.
1894 If the next and previous displayed frames are equidistant from the
1895 selected frame, choose the next one. */
1896 g_assert(following_frame == NULL ||
1897 following_frame->num >= selected_frame->num);
1898 g_assert(preceding_frame == NULL ||
1899 preceding_frame->num <= selected_frame->num);
1900 if (following_frame == NULL) {
1901 /* No frame after the selected frame passed the filter, so we
1902 have to select the last displayed frame before the selected
1904 selected_frame_num = preceding_frame_num;
1905 selected_frame = preceding_frame;
1906 } else if (preceding_frame == NULL) {
1907 /* No frame before the selected frame passed the filter, so we
1908 have to select the first displayed frame after the selected
1910 selected_frame_num = following_frame_num;
1911 selected_frame = following_frame;
1913 /* Frames before and after the selected frame passed the filter, so
1914 we'll select the previous frame */
1915 selected_frame_num = preceding_frame_num;
1916 selected_frame = preceding_frame;
1921 if (selected_frame_num == -1) {
1922 /* There are no frames displayed at all. */
1923 cf_unselect_packet(cf);
1925 /* Either the frame that was selected passed the filter, or we've
1926 found the nearest displayed frame to that frame. Select it, make
1927 it the focus row, and make it visible. */
1928 /* Set to invalid to force update of packet list and packet details */
1929 cf->current_row = -1;
1930 if (selected_frame_num == 0) {
1931 new_packet_list_select_first_row();
1933 if (!new_packet_list_select_row_from_data(selected_frame)) {
1934 /* We didn't find a row corresponding to this frame.
1935 This means that the frame isn't being displayed currently,
1936 so we can't select it. */
1937 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
1938 "%sEnd of capture exceeded!%s\n\n"
1939 "The capture file is probably not fully dissected.",
1940 simple_dialog_primary_start(), simple_dialog_primary_end());
1945 /* Cleanup and release all dfilter resources */
1946 dfilter_free(dfcode);
1951 * Scan trough all frame data and recalculate the ref time
1952 * without rereading the file.
1953 * XXX - do we need a progres bar or is this fast enough?
1956 ref_time_packets(capture_file *cf)
1961 nstime_set_unset(&first_ts);
1962 nstime_set_unset(&prev_dis_ts);
1965 for (framenum = 1; framenum <= cf->count; framenum++) {
1966 fdata = frame_data_sequence_find(cf->frames, framenum);
1968 /* just add some value here until we know if it is being displayed or not */
1969 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1975 /* If we don't have the time stamp of the first packet in the
1976 capture, it's because this is the first packet. Save the time
1977 stamp of this packet as the time stamp of the first packet. */
1978 if (nstime_is_unset(&first_ts)) {
1979 first_ts = fdata->abs_ts;
1981 /* if this frames is marked as a reference time frame, reset
1982 firstsec and firstusec to this frame */
1983 if(fdata->flags.ref_time){
1984 first_ts = fdata->abs_ts;
1987 /* If we don't have the time stamp of the previous displayed packet,
1988 it's because this is the first displayed packet. Save the time
1989 stamp of this packet as the time stamp of the previous displayed
1991 if (nstime_is_unset(&prev_dis_ts)) {
1992 prev_dis_ts = fdata->abs_ts;
1995 /* Get the time elapsed between the first packet and this packet. */
1996 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
1998 /* If it's greater than the current elapsed time, set the elapsed time
1999 to it (we check for "greater than" so as not to be confused by
2000 time moving backwards). */
2001 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
2002 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
2003 cf->elapsed_time = fdata->rel_ts;
2006 /* If this frame is displayed, get the time elapsed between the
2007 previous displayed packet and this packet. */
2008 if( fdata->flags.passed_dfilter ) {
2009 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
2010 prev_dis_ts = fdata->abs_ts;
2016 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
2017 /* This frame either passed the display filter list or is marked as
2018 a time reference frame. All time reference frames are displayed
2019 even if they dont pass the display filter */
2020 if(fdata->flags.ref_time){
2021 /* if this was a TIME REF frame we should reset the cum_bytes field */
2022 cum_bytes = fdata->pkt_len;
2023 fdata->cum_bytes = cum_bytes;
2025 /* increase cum_bytes with this packets length */
2026 cum_bytes += fdata->pkt_len;
2039 process_specified_packets(capture_file *cf, packet_range_t *range,
2040 const char *string1, const char *string2, gboolean terminate_is_stop,
2041 gboolean (*callback)(capture_file *, frame_data *,
2042 union wtap_pseudo_header *, const guint8 *, void *),
2043 void *callback_args)
2047 union wtap_pseudo_header pseudo_header;
2048 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
2049 psp_return_t ret = PSP_FINISHED;
2051 progdlg_t *progbar = NULL;
2054 gboolean progbar_stop_flag;
2055 GTimeVal progbar_start_time;
2056 gchar progbar_status_str[100];
2057 int progbar_nextstep;
2058 int progbar_quantum;
2059 range_process_e process_this;
2061 /* Update the progress bar when it gets to this value. */
2062 progbar_nextstep = 0;
2063 /* When we reach the value that triggers a progress bar update,
2064 bump that value by this amount. */
2065 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2066 /* Count of packets at which we've looked. */
2068 /* Progress so far. */
2071 progbar_stop_flag = FALSE;
2072 g_get_current_time(&progbar_start_time);
2074 packet_range_process_init(range);
2076 /* Iterate through all the packets, printing the packets that
2077 were selected by the current display filter. */
2078 for (framenum = 1; framenum <= cf->count; framenum++) {
2079 fdata = frame_data_sequence_find(cf->frames, framenum);
2081 /* Create the progress bar if necessary.
2082 We check on every iteration of the loop, so that it takes no
2083 longer than the standard time to create it (otherwise, for a
2084 large file, we might take considerably longer than that standard
2085 time in order to get to the next progress bar step). */
2086 if (progbar == NULL)
2087 progbar = delayed_create_progress_dlg(string1, string2,
2090 &progbar_start_time,
2093 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2094 when we update it, we have to run the GTK+ main loop to get it
2095 to repaint what's pending, and doing so may involve an "ioctl()"
2096 to see if there's any pending input from an X server, and doing
2097 that for every packet can be costly, especially on a big file. */
2098 if (progbar_count >= progbar_nextstep) {
2099 /* let's not divide by zero. I should never be started
2100 * with count == 0, so let's assert that
2102 g_assert(cf->count > 0);
2103 progbar_val = (gfloat) progbar_count / cf->count;
2105 if (progbar != NULL) {
2106 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2107 "%4u of %u packets", progbar_count, cf->count);
2108 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2111 progbar_nextstep += progbar_quantum;
2114 if (progbar_stop_flag) {
2115 /* Well, the user decided to abort the operation. Just stop,
2116 and arrange to return PSP_STOPPED to our caller, so they know
2117 it was stopped explicitly. */
2124 /* do we have to process this packet? */
2125 process_this = packet_range_process_packet(range, fdata);
2126 if (process_this == range_process_next) {
2127 /* this packet uninteresting, continue with next one */
2129 } else if (process_this == range_processing_finished) {
2130 /* all interesting packets processed, stop the loop */
2134 /* Get the packet */
2135 if (!cf_read_frame_r(cf, fdata, &pseudo_header, pd)) {
2136 /* Attempt to get the packet failed. */
2140 /* Process the packet */
2141 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
2142 /* Callback failed. We assume it reported the error appropriately. */
2148 /* We're done printing the packets; destroy the progress bar if
2150 if (progbar != NULL)
2151 destroy_progress_dlg(progbar);
2157 gboolean construct_protocol_tree;
2159 } retap_callback_args_t;
2162 retap_packet(capture_file *cf _U_, frame_data *fdata,
2163 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2166 retap_callback_args_t *args = argsp;
2169 epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
2170 tap_queue_init(&edt);
2171 epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
2172 tap_push_tapped_queue(&edt);
2173 epan_dissect_cleanup(&edt);
2179 cf_retap_packets(capture_file *cf)
2181 packet_range_t range;
2182 retap_callback_args_t callback_args;
2183 gboolean filtering_tap_listeners;
2186 /* Do we have any tap listeners with filters? */
2187 filtering_tap_listeners = have_filtering_tap_listeners();
2189 tap_flags = union_of_tap_listener_flags();
2191 /* If any tap listeners have filters, or require the protocol tree,
2192 construct the protocol tree. */
2193 callback_args.construct_protocol_tree = filtering_tap_listeners ||
2194 (tap_flags & TL_REQUIRES_PROTO_TREE);
2196 /* If any tap listeners require the columns, construct them. */
2197 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2199 /* Reset the tap listeners. */
2200 reset_tap_listeners();
2202 /* Iterate through the list of packets, dissecting all packets and
2203 re-running the taps. */
2204 packet_range_init(&range);
2205 packet_range_process_init(&range);
2206 switch (process_specified_packets(cf, &range, "Recalculating statistics on",
2207 "all packets", TRUE, retap_packet,
2210 /* Completed successfully. */
2214 /* Well, the user decided to abort the refiltering.
2215 Return CF_READ_ABORTED so our caller knows they did that. */
2216 return CF_READ_ABORTED;
2219 /* Error while retapping. */
2220 return CF_READ_ERROR;
2223 g_assert_not_reached();
2228 print_args_t *print_args;
2229 gboolean print_header_line;
2230 char *header_line_buf;
2231 int header_line_buf_len;
2232 gboolean print_formfeed;
2233 gboolean print_separator;
2237 } print_callback_args_t;
2240 print_packet(capture_file *cf, frame_data *fdata,
2241 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2244 print_callback_args_t *args = argsp;
2251 gboolean proto_tree_needed;
2252 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2253 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2255 /* Create the protocol tree, and make it visible, if we're printing
2256 the dissection or the hex data.
2257 XXX - do we need it if we're just printing the hex data? */
2259 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2260 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2262 /* Fill in the column information if we're printing the summary
2264 if (args->print_args->print_summary) {
2265 col_custom_prime_edt(&edt, &cf->cinfo);
2266 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2267 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2269 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2271 if (args->print_formfeed) {
2272 if (!new_page(args->print_args->stream))
2275 if (args->print_separator) {
2276 if (!print_line(args->print_args->stream, 0, ""))
2282 * We generate bookmarks, if the output format supports them.
2283 * The name is "__frameN__".
2285 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2287 if (args->print_args->print_summary) {
2288 if (args->print_header_line) {
2289 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2291 args->print_header_line = FALSE; /* we might not need to print any more */
2293 cp = &args->line_buf[0];
2295 for (i = 0; i < cf->cinfo.num_cols; i++) {
2296 /* Find the length of the string for this column. */
2297 column_len = (int) strlen(cf->cinfo.col_data[i]);
2298 if (args->col_widths[i] > column_len)
2299 column_len = args->col_widths[i];
2301 /* Make sure there's room in the line buffer for the column; if not,
2302 double its length. */
2303 line_len += column_len + 1; /* "+1" for space */
2304 if (line_len > args->line_buf_len) {
2305 cp_off = (int) (cp - args->line_buf);
2306 args->line_buf_len = 2 * line_len;
2307 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2308 cp = args->line_buf + cp_off;
2311 /* Right-justify the packet number column. */
2312 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2313 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
2315 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
2317 if (i != cf->cinfo.num_cols - 1)
2323 * Generate a bookmark, using the summary line as the title.
2325 if (!print_bookmark(args->print_args->stream, bookmark_name,
2329 if (!print_line(args->print_args->stream, 0, args->line_buf))
2333 * Generate a bookmark, using "Frame N" as the title, as we're not
2334 * printing the summary line.
2336 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2337 if (!print_bookmark(args->print_args->stream, bookmark_name,
2340 } /* if (print_summary) */
2342 if (args->print_args->print_dissections != print_dissections_none) {
2343 if (args->print_args->print_summary) {
2344 /* Separate the summary line from the tree with a blank line. */
2345 if (!print_line(args->print_args->stream, 0, ""))
2349 /* Print the information in that tree. */
2350 if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
2353 /* Print a blank line if we print anything after this (aka more than one packet). */
2354 args->print_separator = TRUE;
2356 /* Print a header line if we print any more packet summaries */
2357 args->print_header_line = TRUE;
2360 if (args->print_args->print_hex) {
2361 /* Print the full packet data as hex. */
2362 if (!print_hex_data(args->print_args->stream, &edt))
2365 /* Print a blank line if we print anything after this (aka more than one packet). */
2366 args->print_separator = TRUE;
2368 /* Print a header line if we print any more packet summaries */
2369 args->print_header_line = TRUE;
2370 } /* if (args->print_args->print_dissections != print_dissections_none) */
2372 epan_dissect_cleanup(&edt);
2374 /* do we want to have a formfeed between each packet from now on? */
2375 if(args->print_args->print_formfeed) {
2376 args->print_formfeed = TRUE;
2382 epan_dissect_cleanup(&edt);
2387 cf_print_packets(capture_file *cf, print_args_t *print_args)
2390 print_callback_args_t callback_args;
2398 callback_args.print_args = print_args;
2399 callback_args.print_header_line = TRUE;
2400 callback_args.header_line_buf = NULL;
2401 callback_args.header_line_buf_len = 256;
2402 callback_args.print_formfeed = FALSE;
2403 callback_args.print_separator = FALSE;
2404 callback_args.line_buf = NULL;
2405 callback_args.line_buf_len = 256;
2406 callback_args.col_widths = NULL;
2408 if (!print_preamble(print_args->stream, cf->filename)) {
2409 destroy_print_stream(print_args->stream);
2410 return CF_PRINT_WRITE_ERROR;
2413 if (print_args->print_summary) {
2414 /* We're printing packet summaries. Allocate the header line buffer
2415 and get the column widths. */
2416 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2418 /* Find the widths for each of the columns - maximum of the
2419 width of the title and the width of the data - and construct
2420 a buffer with a line containing the column titles. */
2421 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2422 cp = &callback_args.header_line_buf[0];
2424 for (i = 0; i < cf->cinfo.num_cols; i++) {
2425 /* Don't pad the last column. */
2426 if (i == cf->cinfo.num_cols - 1)
2427 callback_args.col_widths[i] = 0;
2429 callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
2430 data_width = get_column_char_width(get_column_format(i));
2431 if (data_width > callback_args.col_widths[i])
2432 callback_args.col_widths[i] = data_width;
2435 /* Find the length of the string for this column. */
2436 column_len = (int) strlen(cf->cinfo.col_title[i]);
2437 if (callback_args.col_widths[i] > column_len)
2438 column_len = callback_args.col_widths[i];
2440 /* Make sure there's room in the line buffer for the column; if not,
2441 double its length. */
2442 line_len += column_len + 1; /* "+1" for space */
2443 if (line_len > callback_args.header_line_buf_len) {
2444 cp_off = (int) (cp - callback_args.header_line_buf);
2445 callback_args.header_line_buf_len = 2 * line_len;
2446 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2447 callback_args.header_line_buf_len + 1);
2448 cp = callback_args.header_line_buf + cp_off;
2451 /* Right-justify the packet number column. */
2452 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2453 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2455 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2457 if (i != cf->cinfo.num_cols - 1)
2462 /* Now start out the main line buffer with the same length as the
2463 header line buffer. */
2464 callback_args.line_buf_len = callback_args.header_line_buf_len;
2465 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2466 } /* if (print_summary) */
2468 /* Iterate through the list of packets, printing the packets we were
2470 ret = process_specified_packets(cf, &print_args->range, "Printing",
2471 "selected packets", TRUE, print_packet,
2474 g_free(callback_args.header_line_buf);
2475 g_free(callback_args.line_buf);
2476 g_free(callback_args.col_widths);
2481 /* Completed successfully. */
2485 /* Well, the user decided to abort the printing.
2487 XXX - note that what got generated before they did that
2488 will get printed if we're piping to a print program; we'd
2489 have to write to a file and then hand that to the print
2490 program to make it actually not print anything. */
2494 /* Error while printing.
2496 XXX - note that what got generated before they did that
2497 will get printed if we're piping to a print program; we'd
2498 have to write to a file and then hand that to the print
2499 program to make it actually not print anything. */
2500 destroy_print_stream(print_args->stream);
2501 return CF_PRINT_WRITE_ERROR;
2504 if (!print_finale(print_args->stream)) {
2505 destroy_print_stream(print_args->stream);
2506 return CF_PRINT_WRITE_ERROR;
2509 if (!destroy_print_stream(print_args->stream))
2510 return CF_PRINT_WRITE_ERROR;
2516 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2517 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2523 /* Create the protocol tree, but don't fill in the column information. */
2524 epan_dissect_init(&edt, TRUE, TRUE);
2525 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2527 /* Write out the information in that tree. */
2528 proto_tree_write_pdml(&edt, fh);
2530 epan_dissect_cleanup(&edt);
2536 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2541 fh = ws_fopen(print_args->file, "w");
2543 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2545 write_pdml_preamble(fh, cf->filename);
2548 return CF_PRINT_WRITE_ERROR;
2551 /* Iterate through the list of packets, printing the packets we were
2553 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2554 "selected packets", TRUE,
2555 write_pdml_packet, fh);
2560 /* Completed successfully. */
2564 /* Well, the user decided to abort the printing. */
2568 /* Error while printing. */
2570 return CF_PRINT_WRITE_ERROR;
2573 write_pdml_finale(fh);
2576 return CF_PRINT_WRITE_ERROR;
2579 /* XXX - check for an error */
2586 write_psml_packet(capture_file *cf, frame_data *fdata,
2587 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2592 gboolean proto_tree_needed;
2594 /* Fill in the column information, only create the protocol tree
2595 if having custom columns. */
2596 proto_tree_needed = have_custom_cols(&cf->cinfo);
2597 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2598 col_custom_prime_edt(&edt, &cf->cinfo);
2599 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2600 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2602 /* Write out the information in that tree. */
2603 proto_tree_write_psml(&edt, fh);
2605 epan_dissect_cleanup(&edt);
2611 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2616 fh = ws_fopen(print_args->file, "w");
2618 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2620 write_psml_preamble(fh);
2623 return CF_PRINT_WRITE_ERROR;
2626 /* Iterate through the list of packets, printing the packets we were
2628 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2629 "selected packets", TRUE,
2630 write_psml_packet, fh);
2635 /* Completed successfully. */
2639 /* Well, the user decided to abort the printing. */
2643 /* Error while printing. */
2645 return CF_PRINT_WRITE_ERROR;
2648 write_psml_finale(fh);
2651 return CF_PRINT_WRITE_ERROR;
2654 /* XXX - check for an error */
2661 write_csv_packet(capture_file *cf, frame_data *fdata,
2662 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2667 gboolean proto_tree_needed;
2669 /* Fill in the column information, only create the protocol tree
2670 if having custom columns. */
2671 proto_tree_needed = have_custom_cols(&cf->cinfo);
2672 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2673 col_custom_prime_edt(&edt, &cf->cinfo);
2674 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2675 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2677 /* Write out the information in that tree. */
2678 proto_tree_write_csv(&edt, fh);
2680 epan_dissect_cleanup(&edt);
2686 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2691 fh = ws_fopen(print_args->file, "w");
2693 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2695 write_csv_preamble(fh);
2698 return CF_PRINT_WRITE_ERROR;
2701 /* Iterate through the list of packets, printing the packets we were
2703 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2704 "selected packets", TRUE,
2705 write_csv_packet, fh);
2710 /* Completed successfully. */
2714 /* Well, the user decided to abort the printing. */
2718 /* Error while printing. */
2720 return CF_PRINT_WRITE_ERROR;
2723 write_csv_finale(fh);
2726 return CF_PRINT_WRITE_ERROR;
2729 /* XXX - check for an error */
2736 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
2737 union wtap_pseudo_header *pseudo_header,
2738 const guint8 *pd, void *argsp)
2743 epan_dissect_init(&edt, TRUE, TRUE);
2744 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2745 proto_tree_write_carrays(fdata->num, fh, &edt);
2746 epan_dissect_cleanup(&edt);
2752 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2757 fh = ws_fopen(print_args->file, "w");
2760 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2762 write_carrays_preamble(fh);
2766 return CF_PRINT_WRITE_ERROR;
2769 /* Iterate through the list of packets, printing the packets we were
2771 ret = process_specified_packets(cf, &print_args->range,
2773 "selected packets", TRUE,
2774 write_carrays_packet, fh);
2777 /* Completed successfully. */
2780 /* Well, the user decided to abort the printing. */
2783 /* Error while printing. */
2785 return CF_PRINT_WRITE_ERROR;
2788 write_carrays_finale(fh);
2792 return CF_PRINT_WRITE_ERROR;
2800 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2801 search_direction dir)
2805 mdata.string = string;
2806 mdata.string_len = strlen(string);
2807 return find_packet(cf, match_protocol_tree, &mdata, dir);
2811 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2813 mdata->frame_matched = FALSE;
2814 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2815 mdata->string_len = strlen(mdata->string);
2817 /* Iterate through all the nodes looking for matching text */
2818 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2819 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2823 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2825 match_data *mdata = criterion;
2828 /* Load the frame's data. */
2829 if (!cf_read_frame(cf, fdata)) {
2830 /* Attempt to get the packet failed. */
2834 /* Construct the protocol tree, including the displayed text */
2835 epan_dissect_init(&edt, TRUE, TRUE);
2836 /* We don't need the column information */
2837 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2839 /* Iterate through all the nodes, seeing if they have text that matches. */
2841 mdata->frame_matched = FALSE;
2842 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2843 epan_dissect_cleanup(&edt);
2844 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2848 match_subtree_text(proto_node *node, gpointer data)
2850 match_data *mdata = (match_data*) data;
2851 const gchar *string = mdata->string;
2852 size_t string_len = mdata->string_len;
2853 capture_file *cf = mdata->cf;
2854 field_info *fi = PNODE_FINFO(node);
2855 gchar label_str[ITEM_LABEL_LENGTH];
2862 g_assert(fi && "dissection with an invisible proto tree?");
2864 if (mdata->frame_matched) {
2865 /* We already had a match; don't bother doing any more work. */
2869 /* Don't match invisible entries. */
2870 if (PROTO_ITEM_IS_HIDDEN(node))
2873 /* was a free format label produced? */
2875 label_ptr = fi->rep->representation;
2877 /* no, make a generic label */
2878 label_ptr = label_str;
2879 proto_item_fill_label(fi, label_str);
2882 /* Does that label match? */
2883 label_len = strlen(label_ptr);
2884 for (i = 0; i < label_len; i++) {
2885 c_char = label_ptr[i];
2887 c_char = toupper(c_char);
2888 if (c_char == string[c_match]) {
2890 if (c_match == string_len) {
2891 /* No need to look further; we have a match */
2892 mdata->frame_matched = TRUE;
2900 /* Recurse into the subtree, if it exists */
2901 if (node->first_child != NULL)
2902 proto_tree_children_foreach(node, match_subtree_text, mdata);
2906 cf_find_packet_summary_line(capture_file *cf, const char *string,
2907 search_direction dir)
2911 mdata.string = string;
2912 mdata.string_len = strlen(string);
2913 return find_packet(cf, match_summary_line, &mdata, dir);
2917 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2919 match_data *mdata = criterion;
2920 const gchar *string = mdata->string;
2921 size_t string_len = mdata->string_len;
2923 const char *info_column;
2924 size_t info_column_len;
2925 match_result result = MR_NOTMATCHED;
2931 /* Load the frame's data. */
2932 if (!cf_read_frame(cf, fdata)) {
2933 /* Attempt to get the packet failed. */
2937 /* Don't bother constructing the protocol tree */
2938 epan_dissect_init(&edt, FALSE, FALSE);
2939 /* Get the column information */
2940 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2942 /* Find the Info column */
2943 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2944 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2945 /* Found it. See if we match. */
2946 info_column = edt.pi.cinfo->col_data[colx];
2947 info_column_len = strlen(info_column);
2948 for (i = 0; i < info_column_len; i++) {
2949 c_char = info_column[i];
2951 c_char = toupper(c_char);
2952 if (c_char == string[c_match]) {
2954 if (c_match == string_len) {
2955 result = MR_MATCHED;
2964 epan_dissect_cleanup(&edt);
2971 } cbs_t; /* "Counted byte string" */
2974 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
2975 search_direction dir)
2980 info.data_len = string_size;
2982 /* String or hex search? */
2984 /* String search - what type of string? */
2985 switch (cf->scs_type) {
2987 case SCS_ASCII_AND_UNICODE:
2988 return find_packet(cf, match_ascii_and_unicode, &info, dir);
2991 return find_packet(cf, match_ascii, &info, dir);
2994 return find_packet(cf, match_unicode, &info, dir);
2997 g_assert_not_reached();
3001 return find_packet(cf, match_binary, &info, dir);
3005 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3007 cbs_t *info = criterion;
3008 const guint8 *ascii_text = info->data;
3009 size_t textlen = info->data_len;
3010 match_result result;
3016 /* Load the frame's data. */
3017 if (!cf_read_frame(cf, fdata)) {
3018 /* Attempt to get the packet failed. */
3022 result = MR_NOTMATCHED;
3023 buf_len = fdata->pkt_len;
3025 while (i < buf_len) {
3028 c_char = toupper(c_char);
3029 if (c_char != '\0') {
3030 if (c_char == ascii_text[c_match]) {
3032 if (c_match == textlen) {
3033 result = MR_MATCHED;
3034 cf->search_pos = i; /* Save the position of the last character
3035 for highlighting the field. */
3040 g_assert(i>=c_match);
3041 i -= (guint32)c_match;
3051 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
3053 cbs_t *info = criterion;
3054 const guint8 *ascii_text = info->data;
3055 size_t textlen = info->data_len;
3056 match_result result;
3062 /* Load the frame's data. */
3063 if (!cf_read_frame(cf, fdata)) {
3064 /* Attempt to get the packet failed. */
3068 result = MR_NOTMATCHED;
3069 buf_len = fdata->pkt_len;
3071 while (i < buf_len) {
3074 c_char = toupper(c_char);
3075 if (c_char == ascii_text[c_match]) {
3077 if (c_match == textlen) {
3078 result = MR_MATCHED;
3079 cf->search_pos = i; /* Save the position of the last character
3080 for highlighting the field. */
3085 g_assert(i>=c_match);
3086 i -= (guint32)c_match;
3096 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3098 cbs_t *info = criterion;
3099 const guint8 *ascii_text = info->data;
3100 size_t textlen = info->data_len;
3101 match_result result;
3107 /* Load the frame's data. */
3108 if (!cf_read_frame(cf, fdata)) {
3109 /* Attempt to get the packet failed. */
3113 result = MR_NOTMATCHED;
3114 buf_len = fdata->pkt_len;
3116 while (i < buf_len) {
3119 c_char = toupper(c_char);
3120 if (c_char == ascii_text[c_match]) {
3122 if (c_match == textlen) {
3123 result = MR_MATCHED;
3124 cf->search_pos = i; /* Save the position of the last character
3125 for highlighting the field. */
3131 g_assert(i>=(c_match*2));
3132 i -= (guint32)c_match*2;
3141 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3143 cbs_t *info = criterion;
3144 const guint8 *binary_data = info->data;
3145 size_t datalen = info->data_len;
3146 match_result result;
3151 /* Load the frame's data. */
3152 if (!cf_read_frame(cf, fdata)) {
3153 /* Attempt to get the packet failed. */
3157 result = MR_NOTMATCHED;
3158 buf_len = fdata->pkt_len;
3160 while (i < buf_len) {
3161 if (cf->pd[i] == binary_data[c_match]) {
3163 if (c_match == datalen) {
3164 result = MR_MATCHED;
3165 cf->search_pos = i; /* Save the position of the last character
3166 for highlighting the field. */
3171 g_assert(i>=c_match);
3172 i -= (guint32)c_match;
3181 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3182 search_direction dir)
3184 return find_packet(cf, match_dfilter, sfcode, dir);
3188 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3189 search_direction dir)
3194 if (!dfilter_compile(filter, &sfcode)) {
3196 * XXX - this shouldn't happen, as the filter string is machine
3201 if (sfcode == NULL) {
3203 * XXX - this shouldn't happen, as the filter string is machine
3208 result = find_packet(cf, match_dfilter, sfcode, dir);
3209 dfilter_free(sfcode);
3214 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3216 dfilter_t *sfcode = criterion;
3218 match_result result;
3220 /* Load the frame's data. */
3221 if (!cf_read_frame(cf, fdata)) {
3222 /* Attempt to get the packet failed. */
3226 epan_dissect_init(&edt, TRUE, FALSE);
3227 epan_dissect_prime_dfilter(&edt, sfcode);
3228 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3229 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3230 epan_dissect_cleanup(&edt);
3235 cf_find_packet_marked(capture_file *cf, search_direction dir)
3237 return find_packet(cf, match_marked, NULL, dir);
3241 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3243 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3247 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3249 return find_packet(cf, match_time_reference, NULL, dir);
3253 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3255 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3259 find_packet(capture_file *cf,
3260 match_result (*match_function)(capture_file *, frame_data *, void *),
3261 void *criterion, search_direction dir)
3263 frame_data *start_fd;
3266 frame_data *new_fd = NULL;
3267 progdlg_t *progbar = NULL;
3272 GTimeVal start_time;
3273 gchar status_str[100];
3274 int progbar_nextstep;
3275 int progbar_quantum;
3277 match_result result;
3279 start_fd = cf->current_frame;
3280 if (start_fd != NULL) {
3281 /* Iterate through the list of packets, starting at the packet we've
3282 picked, calling a routine to run the filter on the packet, see if
3283 it matches, and stop if so. */
3285 framenum = start_fd->num;
3287 /* Update the progress bar when it gets to this value. */
3288 progbar_nextstep = 0;
3289 /* When we reach the value that triggers a progress bar update,
3290 bump that value by this amount. */
3291 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3292 /* Progress so far. */
3296 g_get_current_time(&start_time);
3298 title = cf->sfilter?cf->sfilter:"";
3300 /* Create the progress bar if necessary.
3301 We check on every iteration of the loop, so that it takes no
3302 longer than the standard time to create it (otherwise, for a
3303 large file, we might take considerably longer than that standard
3304 time in order to get to the next progress bar step). */
3305 if (progbar == NULL)
3306 progbar = delayed_create_progress_dlg("Searching", title,
3307 FALSE, &stop_flag, &start_time, progbar_val);
3309 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3310 when we update it, we have to run the GTK+ main loop to get it
3311 to repaint what's pending, and doing so may involve an "ioctl()"
3312 to see if there's any pending input from an X server, and doing
3313 that for every packet can be costly, especially on a big file. */
3314 if (count >= progbar_nextstep) {
3315 /* let's not divide by zero. I should never be started
3316 * with count == 0, so let's assert that
3318 g_assert(cf->count > 0);
3320 progbar_val = (gfloat) count / cf->count;
3322 if (progbar != NULL) {
3323 g_snprintf(status_str, sizeof(status_str),
3324 "%4u of %u packets", count, cf->count);
3325 update_progress_dlg(progbar, progbar_val, status_str);
3328 progbar_nextstep += progbar_quantum;
3332 /* Well, the user decided to abort the search. Go back to the
3333 frame where we started. */
3338 /* Go past the current frame. */
3339 if (dir == SD_BACKWARD) {
3340 /* Go on to the previous frame. */
3341 if (framenum == 1) {
3343 * XXX - other apps have a bit more of a detailed message
3344 * for this, and instead of offering "OK" and "Cancel",
3345 * they offer things such as "Continue" and "Cancel";
3346 * we need an API for popping up alert boxes with
3347 * {Verb} and "Cancel".
3350 if (prefs.gui_find_wrap)
3352 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3353 framenum = cf->count; /* wrap around */
3357 statusbar_push_temporary_msg("Search reached the beginning.");
3358 framenum = start_fd->num; /* stay on previous packet */
3363 /* Go on to the next frame. */
3364 if (framenum == cf->count) {
3365 if (prefs.gui_find_wrap)
3367 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3368 framenum = 1; /* wrap around */
3372 statusbar_push_temporary_msg("Search reached the end.");
3373 framenum = start_fd->num; /* stay on previous packet */
3378 fdata = frame_data_sequence_find(cf->frames, framenum);
3382 /* Is this packet in the display? */
3383 if (fdata->flags.passed_dfilter) {
3384 /* Yes. Does it match the search criterion? */
3385 result = (*match_function)(cf, fdata, criterion);
3386 if (result == MR_ERROR) {
3387 /* Error; our caller has reported the error. Go back to the frame
3388 where we started. */
3391 } else if (result == MR_MATCHED) {
3392 /* Yes. Go to the new frame. */
3398 if (fdata == start_fd) {
3399 /* We're back to the frame we were on originally, and that frame
3400 doesn't match the search filter. The search failed. */
3405 /* We're done scanning the packets; destroy the progress bar if it
3407 if (progbar != NULL)
3408 destroy_progress_dlg(progbar);
3411 if (new_fd != NULL) {
3412 /* Find and select */
3413 cf->search_in_progress = TRUE;
3414 found = new_packet_list_select_row_from_data(new_fd);
3415 cf->search_in_progress = FALSE;
3416 cf->search_pos = 0; /* Reset the position */
3418 /* We didn't find a row corresponding to this frame.
3419 This means that the frame isn't being displayed currently,
3420 so we can't select it. */
3421 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3422 "%sEnd of capture exceeded!%s\n\n"
3423 "The capture file is probably not fully dissected.",
3424 simple_dialog_primary_start(), simple_dialog_primary_end());
3427 return TRUE; /* success */
3429 return FALSE; /* failure */
3433 cf_goto_frame(capture_file *cf, guint fnumber)
3437 fdata = frame_data_sequence_find(cf->frames, fnumber);
3439 if (fdata == NULL) {
3440 /* we didn't find a packet with that packet number */
3441 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3442 return FALSE; /* we failed to go to that packet */
3444 if (!fdata->flags.passed_dfilter) {
3445 /* that packet currently isn't displayed */
3446 /* XXX - add it to the set of displayed packets? */
3447 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3448 return FALSE; /* we failed to go to that packet */
3451 if (!new_packet_list_select_row_from_data(fdata)) {
3452 /* We didn't find a row corresponding to this frame.
3453 This means that the frame isn't being displayed currently,
3454 so we can't select it. */
3455 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3456 "%sEnd of capture exceeded!%s\n\n"
3457 "The capture file is probably not fully dissected.",
3458 simple_dialog_primary_start(), simple_dialog_primary_end());
3461 return TRUE; /* we got to that packet */
3465 cf_goto_top_frame(void)
3467 /* Find and select */
3468 new_packet_list_select_first_row();
3469 return TRUE; /* we got to that packet */
3473 cf_goto_bottom_frame(void)
3475 /* Find and select */
3476 new_packet_list_select_last_row();
3477 return TRUE; /* we got to that packet */
3481 * Go to frame specified by currently selected protocol tree item.
3484 cf_goto_framenum(capture_file *cf)
3486 header_field_info *hfinfo;
3489 if (cf->finfo_selected) {
3490 hfinfo = cf->finfo_selected->hfinfo;
3492 if (hfinfo->type == FT_FRAMENUM) {
3493 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3495 return cf_goto_frame(cf, framenum);
3502 /* Select the packet on a given row. */
3504 cf_select_packet(capture_file *cf, int row)
3508 /* Get the frame data struct pointer for this frame */
3509 fdata = new_packet_list_get_row_data(row);
3511 if (fdata == NULL) {
3512 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3513 the first entry is added to it by "real_insert_row()", that row
3514 is selected (see "real_insert_row()", in "ui/gtk/gtkclist.c", in both
3515 our version and the vanilla GTK+ version).
3517 This means that a "select-row" signal is emitted; this causes
3518 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3521 "cf_select_packet()" fetches, above, the data associated with the
3522 row that was selected; however, as "gtk_clist_append()", which
3523 called "real_insert_row()", hasn't yet returned, we haven't yet
3524 associated any data with that row, so we get back a null pointer.
3526 We can't assume that there's only one frame in the frame list,
3527 either, as we may be filtering the display.
3529 We therefore assume that, if "row" is 0, i.e. the first row
3530 is being selected, and "cf->first_displayed" equals
3531 "cf->last_displayed", i.e. there's only one frame being
3532 displayed, that frame is the frame we want.
3534 This means we have to set "cf->first_displayed" and
3535 "cf->last_displayed" before adding the row to the
3536 GtkCList; see the comment in "add_packet_to_packet_list()". */
3538 if (row == 0 && cf->first_displayed == cf->last_displayed)
3539 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3542 /* If fdata _still_ isn't set simply give up. */
3543 if (fdata == NULL) {
3547 /* Get the data in that frame. */
3548 if (!cf_read_frame (cf, fdata)) {
3552 /* Record that this frame is the current frame. */
3553 cf->current_frame = fdata;
3554 cf->current_row = row;
3556 /* Create the logical protocol tree. */
3557 if (cf->edt != NULL)
3558 epan_dissect_free(cf->edt);
3560 /* We don't need the columns here. */
3561 cf->edt = epan_dissect_new(TRUE, TRUE);
3563 tap_build_interesting(cf->edt);
3564 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3567 dfilter_macro_build_ftv_cache(cf->edt->tree);
3569 cf_callback_invoke(cf_cb_packet_selected, cf);
3572 /* Unselect the selected packet, if any. */
3574 cf_unselect_packet(capture_file *cf)
3576 /* Destroy the epan_dissect_t for the unselected packet. */
3577 if (cf->edt != NULL) {
3578 epan_dissect_free(cf->edt);
3582 /* No packet is selected. */
3583 cf->current_frame = NULL;
3584 cf->current_row = 0;
3586 cf_callback_invoke(cf_cb_packet_unselected, cf);
3588 /* No protocol tree means no selected field. */
3589 cf_unselect_field(cf);
3592 /* Unset the selected protocol tree field, if any. */
3594 cf_unselect_field(capture_file *cf)
3596 cf->finfo_selected = NULL;
3598 cf_callback_invoke(cf_cb_field_unselected, cf);
3602 * Mark a particular frame.
3605 cf_mark_frame(capture_file *cf, frame_data *frame)
3607 if (! frame->flags.marked) {
3608 frame->flags.marked = TRUE;
3609 if (cf->count > cf->marked_count)
3615 * Unmark a particular frame.
3618 cf_unmark_frame(capture_file *cf, frame_data *frame)
3620 if (frame->flags.marked) {
3621 frame->flags.marked = FALSE;
3622 if (cf->marked_count > 0)
3628 * Ignore a particular frame.
3631 cf_ignore_frame(capture_file *cf, frame_data *frame)
3633 if (! frame->flags.ignored) {
3634 frame->flags.ignored = TRUE;
3635 if (cf->count > cf->ignored_count)
3636 cf->ignored_count++;
3641 * Un-ignore a particular frame.
3644 cf_unignore_frame(capture_file *cf, frame_data *frame)
3646 if (frame->flags.ignored) {
3647 frame->flags.ignored = FALSE;
3648 if (cf->ignored_count > 0)
3649 cf->ignored_count--;
3657 } save_callback_args_t;
3660 * Save a capture to a file, in a particular format, saving either
3661 * all packets, all currently-displayed packets, or all marked packets.
3663 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3664 * up a message box for the failure.
3667 save_packet(capture_file *cf _U_, frame_data *fdata,
3668 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3671 save_callback_args_t *args = argsp;
3672 struct wtap_pkthdr hdr;
3675 /* init the wtap header for saving */
3676 hdr.ts.secs = fdata->abs_ts.secs;
3677 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3678 hdr.caplen = fdata->cap_len;
3679 hdr.len = fdata->pkt_len;
3680 hdr.pkt_encap = fdata->lnk_t;
3682 hdr.interface_id = fdata->interface_id; /* identifier of the interface. */
3684 hdr.opt_comment = fdata->opt_comment; /* NULL if not available */
3687 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
3689 /* and save the packet */
3690 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3692 /* Wiretap error. */
3695 case WTAP_ERR_UNSUPPORTED_ENCAP:
3697 * This is a problem with the particular frame we're writing;
3698 * note that, and give the frame number.
3700 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3701 "Frame %u has a network type that can't be saved in a \"%s\" file.",
3702 fdata->num, wtap_file_type_string(args->file_type));
3706 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3707 "An error occurred while writing to the file \"%s\": %s.",
3708 args->fname, wtap_strerror(err));
3713 write_failure_alert_box(args->fname, err);
3721 * Can this capture file be saved in any format except by copying the raw data?
3724 cf_can_save_as(capture_file *cf)
3728 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
3729 /* To save a file with Wiretap, Wiretap has to handle that format,
3730 and its code to handle that format must be able to write a file
3731 with this file's encapsulation type. */
3732 if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
3733 /* OK, we can write it out in this type. */
3738 /* No, we couldn't save it in any format. */
3743 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3745 gchar *from_filename;
3749 save_callback_args_t callback_args;
3751 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
3753 /* don't write over an existing file. */
3754 /* this should've been already checked by our caller, just to be sure... */
3755 if (file_exists(fname)) {
3756 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3757 "%sCapture file: \"%s\" already exists!%s\n\n"
3758 "Please choose a different filename.",
3759 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3763 packet_range_process_init(range);
3765 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3766 /* We're not filtering packets, and we're saving it in the format
3767 it's already in, so we can just move or copy the raw data. */
3769 if (cf->is_tempfile) {
3770 /* The file being saved is a temporary file from a live
3771 capture, so it doesn't need to stay around under that name;
3772 first, try renaming the capture buffer file to the new name. */
3774 if (ws_rename(cf->filename, fname) == 0) {
3775 /* That succeeded - there's no need to copy the source file. */
3776 from_filename = NULL;
3779 if (errno == EXDEV) {
3780 /* They're on different file systems, so we have to copy the
3783 from_filename = cf->filename;
3785 /* The rename failed, but not because they're on different
3786 file systems - put up an error message. (Or should we
3787 just punt and try to copy? The only reason why I'd
3788 expect the rename to fail and the copy to succeed would
3789 be if we didn't have permission to remove the file from
3790 the temporary directory, and that might be fixable - but
3791 is it worth requiring the user to go off and fix it?) */
3792 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3793 file_rename_error_message(errno), fname);
3799 from_filename = cf->filename;
3802 /* It's a permanent file, so we should copy it, and not remove the
3805 from_filename = cf->filename;
3809 /* Copy the file, if we haven't moved it. */
3810 if (!copy_file_binary_mode(from_filename, fname))
3814 /* Either we're filtering packets, or we're saving in a different
3815 format; we can't do that by copying or moving the capture file,
3816 we have to do it by writing the packets out in Wiretap. */
3818 wtapng_section_t *shb_hdr = NULL;
3819 wtapng_iface_descriptions_t *idb_inf = NULL;
3821 shb_hdr = wtap_file_get_shb_info(cf->wth);
3822 idb_inf = wtap_file_get_idb_info(cf->wth);
3824 pdh = wtap_dump_open_ng(fname, save_format, cf->lnk_t, cf->snap,
3825 compressed, shb_hdr, idb_inf, &err);
3827 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3831 /* Add address resolution */
3832 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
3834 /* XXX - we let the user save a subset of the packets.
3836 If we do that, should we make that file the current file? If so,
3837 it means we can no longer get at the other packets. What does
3840 /* Iterate through the list of packets, processing the packets we were
3843 XXX - we've already called "packet_range_process_init(range)", but
3844 "process_specified_packets()" will do it again. Fortunately,
3845 that's harmless in this case, as we haven't done anything to
3846 "range" since we initialized it. */
3847 callback_args.pdh = pdh;
3848 callback_args.fname = fname;
3849 callback_args.file_type = save_format;
3850 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3851 TRUE, save_packet, &callback_args)) {
3854 /* Completed successfully. */
3858 /* The user decided to abort the saving.
3859 XXX - remove the output file? */
3863 /* Error while saving. */
3864 wtap_dump_close(pdh, &err);
3868 if (!wtap_dump_close(pdh, &err)) {
3869 cf_close_failure_alert_box(fname, err);
3874 cf_callback_invoke(cf_cb_file_save_finished, NULL);
3876 if (packet_range_process_all(range)) {
3877 /* We saved the entire capture, not just some packets from it.
3878 Open and read the file we saved it to.
3880 XXX - this is somewhat of a waste; we already have the
3881 packets, all this gets us is updated file type information
3882 (which we could just stuff into "cf"), and having the new
3883 file be the one we have opened and from which we're reading
3884 the data, and it means we have to spend time opening and
3885 reading the file, which could be a significant amount of
3886 time if the file is large. */
3887 cf->user_saved = TRUE;
3889 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3890 /* XXX - report errors if this fails?
3891 What should we return if it fails or is aborted? */
3893 switch (cf_read(cf, TRUE)) {
3897 /* Just because we got an error, that doesn't mean we were unable
3898 to read any of the file; we handle what we could get from the
3902 case CF_READ_ABORTED:
3903 /* The user bailed out of re-reading the capture file; the
3904 capture file has been closed - just return (without
3905 changing any menu settings; "cf_close()" set them
3906 correctly for the "no capture file open" state). */
3909 cf_callback_invoke(cf_cb_file_save_reload_finished, cf);
3915 cf_callback_invoke(cf_cb_file_save_failed, NULL);
3920 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3921 gboolean for_writing, int file_type)
3924 /* Wiretap error. */
3927 case WTAP_ERR_NOT_REGULAR_FILE:
3928 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3929 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3933 case WTAP_ERR_RANDOM_OPEN_PIPE:
3934 /* Seen only when opening a capture file for reading. */
3935 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3936 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
3940 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3941 /* Seen only when opening a capture file for reading. */
3942 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3943 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
3947 case WTAP_ERR_UNSUPPORTED:
3948 /* Seen only when opening a capture file for reading. */
3949 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3950 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
3952 filename, err_info);
3956 case WTAP_ERR_CANT_WRITE_TO_PIPE:
3957 /* Seen only when opening a capture file for writing. */
3958 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3959 "The file \"%s\" is a pipe, and %s capture files can't be "
3960 "written to a pipe.",
3961 filename, wtap_file_type_string(file_type));
3964 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3965 /* Seen only when opening a capture file for writing. */
3966 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3967 "Wireshark doesn't support writing capture files in that format.");
3970 case WTAP_ERR_UNSUPPORTED_ENCAP:
3972 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3973 "Wireshark can't save this capture in that format.");
3975 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3976 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
3978 filename, err_info);
3983 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3985 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3986 "Wireshark can't save this capture in that format.");
3988 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3989 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
3994 case WTAP_ERR_BAD_FILE:
3995 /* Seen only when opening a capture file for reading. */
3996 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3997 "The file \"%s\" appears to be damaged or corrupt.\n"
3999 filename, err_info);
4003 case WTAP_ERR_CANT_OPEN:
4005 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4006 "The file \"%s\" could not be created for some unknown reason.",
4009 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4010 "The file \"%s\" could not be opened for some unknown reason.",
4015 case WTAP_ERR_SHORT_READ:
4016 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4017 "The file \"%s\" appears to have been cut short"
4018 " in the middle of a packet or other data.",
4022 case WTAP_ERR_SHORT_WRITE:
4023 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4024 "A full header couldn't be written to the file \"%s\".",
4028 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4029 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4030 "This file type cannot be written as a compressed file.");
4033 case WTAP_ERR_DECOMPRESS:
4034 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4035 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
4036 "(%s)", filename, err_info);
4041 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4042 "The file \"%s\" could not be %s: %s.",
4044 for_writing ? "created" : "opened",
4045 wtap_strerror(err));
4050 open_failure_alert_box(filename, err, for_writing);
4055 file_rename_error_message(int err)
4058 static char errmsg_errno[1024+1];
4063 errmsg = "The path to the file \"%s\" doesn't exist.";
4067 errmsg = "You don't have permission to move the capture file to \"%s\".";
4071 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4072 "The file \"%%s\" could not be moved: %s.",
4073 wtap_strerror(err));
4074 errmsg = errmsg_errno;
4080 /* Check for write errors - if the file is being written to an NFS server,
4081 a write error may not show up until the file is closed, as NFS clients
4082 might not send writes to the server until the "write()" call finishes,
4083 so that the write may fail on the server but the "write()" may succeed. */
4085 cf_close_failure_alert_box(const char *filename, int err)
4088 /* Wiretap error. */
4091 case WTAP_ERR_CANT_CLOSE:
4092 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4093 "The file \"%s\" couldn't be closed for some unknown reason.",
4097 case WTAP_ERR_SHORT_WRITE:
4098 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4099 "Not all the packets could be written to the file \"%s\".",
4104 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4105 "An error occurred while closing the file \"%s\": %s.",
4106 filename, wtap_strerror(err));
4111 We assume that a close error from the OS is really a write error. */
4112 write_failure_alert_box(filename, err);
4116 /* Reload the current capture file. */
4118 cf_reload(capture_file *cf) {
4120 gboolean is_tempfile;
4123 /* If the file could be opened, "cf_open()" calls "cf_close()"
4124 to get rid of state for the old capture file before filling in state
4125 for the new capture file. "cf_close()" will remove the file if
4126 it's a temporary file; we don't want that to happen (for one thing,
4127 it'd prevent subsequent reopens from working). Remember whether it's
4128 a temporary file, mark it as not being a temporary file, and then
4129 reopen it as the type of file it was.
4131 Also, "cf_close()" will free "cf->filename", so we must make
4132 a copy of it first. */
4133 filename = g_strdup(cf->filename);
4134 is_tempfile = cf->is_tempfile;
4135 cf->is_tempfile = FALSE;
4136 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4137 switch (cf_read(cf, FALSE)) {
4141 /* Just because we got an error, that doesn't mean we were unable
4142 to read any of the file; we handle what we could get from the
4146 case CF_READ_ABORTED:
4147 /* The user bailed out of re-reading the capture file; the
4148 capture file has been closed - just free the capture file name
4149 string and return (without changing the last containing
4155 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4156 Instead, the file was left open, so we should restore "cf->is_tempfile"
4159 XXX - change the menu? Presumably "cf_open()" will do that;
4160 make sure it does! */
4161 cf->is_tempfile = is_tempfile;
4163 /* "cf_open()" made a copy of the file name we handed it, so
4164 we should free up our copy. */
4174 * indent-tabs-mode: nil
4177 * ex: set shiftwidth=2 tabstop=8 expandtab:
4178 * :indentSize=2:tabSize=8:noTabs=true: