6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #include <epan/epan.h>
47 #include <epan/filesystem.h>
50 #include "color_filters.h"
52 #include <epan/column.h>
53 #include <epan/packet.h>
54 #include <epan/column-utils.h>
55 #include "packet-range.h"
62 #include <epan/prefs.h>
63 #include <epan/dfilter/dfilter.h>
64 #include <epan/epan_dissect.h>
66 #include <epan/dissectors/packet-data.h>
67 #include <epan/dissectors/packet-ber.h>
68 #include <epan/timestamp.h>
69 #include <epan/dfilter/dfilter-macro.h>
70 #include <wsutil/file_util.h>
71 #include <epan/strutil.h>
72 #include <epan/addr_resolv.h>
74 #include "ui/alert_box.h"
75 #include "ui/simple_dialog.h"
76 #include "ui/main_statusbar.h"
77 #include "ui/progress_dlg.h"
78 #include "ui/ui_util.h"
81 gboolean auto_scroll_live;
84 static guint32 cum_bytes;
85 static nstime_t first_ts;
86 static nstime_t prev_dis_ts;
87 static nstime_t prev_cap_ts;
89 static gulong computed_elapsed;
91 static void cf_reset_state(capture_file *cf);
93 static int read_packet(capture_file *cf, dfilter_t *dfcode,
94 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset);
96 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
97 gboolean refilter, gboolean redissect);
104 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
106 static void match_subtree_text(proto_node *node, gpointer data);
107 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
109 static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
111 static match_result match_ascii(capture_file *cf, frame_data *fdata,
113 static match_result match_unicode(capture_file *cf, frame_data *fdata,
115 static match_result match_binary(capture_file *cf, frame_data *fdata,
117 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
119 static match_result match_marked(capture_file *cf, frame_data *fdata,
121 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
123 static gboolean find_packet(capture_file *cf,
124 match_result (*match_function)(capture_file *, frame_data *, void *),
125 void *criterion, search_direction dir);
127 static void cf_open_failure_alert_box(const char *filename, int err,
128 gchar *err_info, gboolean for_writing,
130 static const char *file_rename_error_message(int err);
131 static void cf_close_failure_alert_box(const char *filename, int err);
132 static void ref_time_packets(capture_file *cf);
133 /* Update the progress bar this many times when reading a file. */
134 #define N_PROGBAR_UPDATES 100
135 /* We read around 200k/100ms don't update the progress bar more often than that */
136 #define MIN_QUANTUM 200000
137 #define MIN_NUMBER_OF_PACKET 1500
140 * We could probably use g_signal_...() instead of the callbacks below but that
141 * would require linking our CLI programs to libgobject and creating an object
142 * instance for the signals.
145 cf_callback_t cb_fct;
147 } cf_callback_data_t;
149 static GList *cf_callbacks = NULL;
152 cf_callback_invoke(int event, gpointer data)
154 cf_callback_data_t *cb;
155 GList *cb_item = cf_callbacks;
157 /* there should be at least one interested */
158 g_assert(cb_item != NULL);
160 while(cb_item != NULL) {
162 cb->cb_fct(event, data, cb->user_data);
163 cb_item = g_list_next(cb_item);
169 cf_callback_add(cf_callback_t func, gpointer user_data)
171 cf_callback_data_t *cb;
173 cb = g_malloc(sizeof(cf_callback_data_t));
175 cb->user_data = user_data;
177 cf_callbacks = g_list_append(cf_callbacks, cb);
181 cf_callback_remove(cf_callback_t func)
183 cf_callback_data_t *cb;
184 GList *cb_item = cf_callbacks;
186 while(cb_item != NULL) {
188 if(cb->cb_fct == func) {
189 cf_callbacks = g_list_remove(cf_callbacks, cb);
193 cb_item = g_list_next(cb_item);
196 g_assert_not_reached();
200 cf_timestamp_auto_precision(capture_file *cf)
203 int prec = timestamp_get_precision();
206 /* don't try to get the file's precision if none is opened */
207 if(cf->state == FILE_CLOSED) {
211 /* if we are in auto mode, set precision of current file */
212 if(prec == TS_PREC_AUTO ||
213 prec == TS_PREC_AUTO_SEC ||
214 prec == TS_PREC_AUTO_DSEC ||
215 prec == TS_PREC_AUTO_CSEC ||
216 prec == TS_PREC_AUTO_MSEC ||
217 prec == TS_PREC_AUTO_USEC ||
218 prec == TS_PREC_AUTO_NSEC)
220 switch(wtap_file_tsprecision(cf->wth)) {
221 case(WTAP_FILE_TSPREC_SEC):
222 timestamp_set_precision(TS_PREC_AUTO_SEC);
224 case(WTAP_FILE_TSPREC_DSEC):
225 timestamp_set_precision(TS_PREC_AUTO_DSEC);
227 case(WTAP_FILE_TSPREC_CSEC):
228 timestamp_set_precision(TS_PREC_AUTO_CSEC);
230 case(WTAP_FILE_TSPREC_MSEC):
231 timestamp_set_precision(TS_PREC_AUTO_MSEC);
233 case(WTAP_FILE_TSPREC_USEC):
234 timestamp_set_precision(TS_PREC_AUTO_USEC);
236 case(WTAP_FILE_TSPREC_NSEC):
237 timestamp_set_precision(TS_PREC_AUTO_NSEC);
240 g_assert_not_reached();
243 /* Set the column widths of those columns that show the time in
244 "command-line-specified" format. */
245 for (i = 0; i < cf->cinfo.num_cols; i++) {
246 if (col_has_time_fmt(&cf->cinfo, i)) {
247 new_packet_list_resize_column(i);
253 cf_get_computed_elapsed(void)
255 return computed_elapsed;
258 static void reset_elapsed(void)
260 computed_elapsed = 0;
263 static void compute_elapsed(GTimeVal *start_time)
268 g_get_current_time(&time_now);
270 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
271 time_now.tv_usec - start_time->tv_usec;
273 computed_elapsed = (gulong) (delta_time / 1000); /* ms */
277 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
282 wth = wtap_open_offline(fname, err, &err_info, TRUE);
286 /* The open succeeded. Close whatever capture file we had open,
287 and fill in the information for this file. */
290 /* Cleanup all data structures used for dissection. */
291 cleanup_dissection();
292 /* Initialize all data structures used for dissection. */
295 /* We're about to start reading the file. */
296 cf->state = FILE_READ_IN_PROGRESS;
301 /* Set the file name because we need it to set the follow stream filter.
302 XXX - is that still true? We need it for other reasons, though,
304 cf->filename = g_strdup(fname);
306 /* Indicate whether it's a permanent or temporary file. */
307 cf->is_tempfile = is_tempfile;
309 /* No user changes yet. */
310 cf->unsaved_changes = FALSE;
314 cf->cd_t = wtap_file_type(cf->wth);
316 cf->displayed_count = 0;
317 cf->marked_count = 0;
318 cf->ignored_count = 0;
319 cf->ref_time_count = 0;
320 cf->drops_known = FALSE;
322 cf->snap = wtap_snapshot_length(cf->wth);
324 /* Snapshot length not known. */
325 cf->has_snap = FALSE;
326 cf->snap = WTAP_MAX_PACKET_SIZE;
330 /* Allocate a frame_data_sequence for the frames in this file */
331 cf->frames = new_frame_data_sequence();
333 nstime_set_zero(&cf->elapsed_time);
334 nstime_set_unset(&first_ts);
335 nstime_set_unset(&prev_dis_ts);
336 nstime_set_unset(&prev_cap_ts);
339 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
340 cf_timestamp_auto_precision(cf);
342 new_packet_list_queue_draw();
343 fileset_file_opened(fname);
345 if(cf->cd_t == WTAP_FILE_BER) {
346 /* tell the BER dissector the file name */
347 ber_set_filename(cf->filename);
350 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
351 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
356 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
362 * Reset the state for the currently closed file, but don't do the
363 * UI callbacks; this is for use in "cf_open()", where we don't
364 * want the UI to go from "file open" to "file closed" back to
365 * "file open", we want it to go from "old file open" to "new file
366 * open and being read".
368 * XXX - currently, cf_open() calls cf_close(), rather than
372 cf_reset_state(capture_file *cf)
374 /* Die if we're in the middle of reading a file. */
375 g_assert(cf->state != FILE_READ_IN_PROGRESS);
381 /* We have no file open... */
382 if (cf->filename != NULL) {
383 /* If it's a temporary file, remove it. */
385 ws_unlink(cf->filename);
386 g_free(cf->filename);
389 /* ...which means we have no changes to that file to save. */
390 cf->unsaved_changes = FALSE;
392 dfilter_free(cf->rfcode);
394 if (cf->frames != NULL) {
395 free_frame_data_sequence(cf->frames);
398 #ifdef WANT_PACKET_EDITOR
399 if (cf->edited_frames) {
400 g_tree_destroy(cf->edited_frames);
401 cf->edited_frames = NULL;
404 cf_unselect_packet(cf); /* nothing to select */
405 cf->first_displayed = 0;
406 cf->last_displayed = 0;
408 /* No frames, no frame selected, no field in that frame selected. */
410 cf->current_frame = 0;
412 cf->finfo_selected = NULL;
414 /* Clear the packet list. */
415 new_packet_list_freeze();
416 new_packet_list_clear();
417 new_packet_list_thaw();
420 nstime_set_zero(&cf->elapsed_time);
422 reset_tap_listeners();
424 /* We have no file open. */
425 cf->state = FILE_CLOSED;
427 fileset_file_closed();
430 /* Reset everything to a pristine state */
432 cf_close(capture_file *cf)
434 if(cf->state != FILE_CLOSED) {
435 cf_callback_invoke(cf_cb_file_closing, cf);
437 /* close things, if not already closed before */
438 color_filters_cleanup();
440 cleanup_dissection();
442 cf_callback_invoke(cf_cb_file_closed, cf);
446 /* an out of memory exception occured, wait for a user button press to exit */
447 static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
453 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
457 progbar_val = (gfloat) file_pos / (gfloat) size;
458 if (progbar_val > 1.0) {
460 /* The file probably grew while we were reading it.
461 * Update file size, and try again.
463 size = wtap_file_size(cf->wth, NULL);
466 progbar_val = (gfloat) file_pos / (gfloat) size;
468 /* If it's still > 1, either "wtap_file_size()" failed (in which
469 * case there's not much we can do about it), or the file
470 * *shrank* (in which case there's not much we can do about
471 * it); just clip the progress value at 1.0.
473 if (progbar_val > 1.0f)
477 g_snprintf(status_str, status_size,
478 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
479 file_pos / 1024, size / 1024);
485 cf_read(capture_file *cf, gboolean reloading)
489 const gchar *name_ptr;
491 char errmsg_errno[1024+1];
494 progdlg_t *volatile progbar = NULL;
496 volatile gint64 size;
497 volatile float progbar_val;
499 gchar status_str[100];
500 volatile gint64 progbar_nextstep;
501 volatile gint64 progbar_quantum;
503 gboolean filtering_tap_listeners;
505 volatile int count = 0;
507 volatile int displayed_once = 0;
511 /* Compile the current display filter.
512 * We assume this will not fail since cf->dfilter is only set in
513 * cf_filter IFF the filter was valid.
515 compiled = dfilter_compile(cf->dfilter, &dfcode);
516 g_assert(!cf->dfilter || (compiled && dfcode));
518 /* Do we have any tap listeners with filters? */
519 filtering_tap_listeners = have_filtering_tap_listeners();
521 /* Get the union of the flags for all tap listeners. */
522 tap_flags = union_of_tap_listener_flags();
524 reset_tap_listeners();
526 name_ptr = get_basename(cf->filename);
529 cf_callback_invoke(cf_cb_file_reload_started, cf);
531 cf_callback_invoke(cf_cb_file_read_started, cf);
533 /* Record whether the file is compressed. */
534 cf->iscompressed = wtap_iscompressed(cf->wth);
536 /* Find the size of the file. */
537 size = wtap_file_size(cf->wth, NULL);
539 /* Update the progress bar when it gets to this value. */
540 progbar_nextstep = 0;
541 /* When we reach the value that triggers a progress bar update,
542 bump that value by this amount. */
544 progbar_quantum = size/N_PROGBAR_UPDATES;
545 if (progbar_quantum < MIN_QUANTUM)
546 progbar_quantum = MIN_QUANTUM;
549 /* Progress so far. */
552 /* The packet list window will be empty untill the file is completly loaded */
553 new_packet_list_freeze();
556 g_get_current_time(&start_time);
558 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
561 file_pos = wtap_read_so_far(cf->wth);
563 /* Create the progress bar if necessary.
564 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
566 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
567 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
569 progbar = delayed_create_progress_dlg("Reloading", name_ptr,
570 TRUE, &stop_flag, &start_time, progbar_val);
572 progbar = delayed_create_progress_dlg("Loading", name_ptr,
573 TRUE, &stop_flag, &start_time, progbar_val);
576 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
577 when we update it, we have to run the GTK+ main loop to get it
578 to repaint what's pending, and doing so may involve an "ioctl()"
579 to see if there's any pending input from an X server, and doing
580 that for every packet can be costly, especially on a big file. */
581 if (file_pos >= progbar_nextstep) {
582 if (progbar != NULL) {
583 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
584 /* update the packet bar content on the first run or frequently on very large files */
586 if (progbar_quantum > 500000 || displayed_once == 0) {
587 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
589 packets_bar_update();
592 #endif /* HAVE_LIBPCAP */
593 update_progress_dlg(progbar, progbar_val, status_str);
595 progbar_nextstep += progbar_quantum;
600 /* Well, the user decided to abort the read. He/She will be warned and
601 it might be enough for him/her to work with the already loaded
603 This is especially true for very large capture files, where you don't
604 want to wait loading the whole file (which may last minutes or even
605 hours even on fast machines) just to see that it was the wrong file. */
609 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
611 CATCH(OutOfMemoryError) {
614 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
615 "%sOut Of Memory!%s\n"
617 "Sorry, but Wireshark has to terminate now!\n"
619 "Some infos / workarounds can be found at:\n"
620 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
621 simple_dialog_primary_start(), simple_dialog_primary_end());
622 /* we have to terminate, as we cannot recover from the memory error */
623 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
625 main_window_update();
626 /* XXX - how to avoid a busy wait? */
634 /* Cleanup and release all dfilter resources */
636 dfilter_free(dfcode);
639 /* We're done reading the file; destroy the progress bar if it was created. */
641 destroy_progress_dlg(progbar);
643 /* We're done reading sequentially through the file. */
644 cf->state = FILE_READ_DONE;
646 /* Close the sequential I/O side, to free up memory it requires. */
647 wtap_sequential_close(cf->wth);
649 /* Allow the protocol dissectors to free up memory that they
650 * don't need after the sequential run-through of the packets. */
651 postseq_cleanup_all_protocols();
653 /* compute the time it took to load the file */
654 compute_elapsed(&start_time);
656 /* Set the file encapsulation type now; we don't know what it is until
657 we've looked at all the packets, as we don't know until then whether
658 there's more than one type (and thus whether it's
659 WTAP_ENCAP_PER_PACKET). */
660 cf->lnk_t = wtap_file_encap(cf->wth);
662 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
665 new_packet_list_thaw();
667 cf_callback_invoke(cf_cb_file_reload_finished, cf);
669 cf_callback_invoke(cf_cb_file_read_finished, cf);
671 /* If we have any displayed packets to select, select the first of those
672 packets by making the first row the selected row. */
673 if (cf->first_displayed != 0){
674 new_packet_list_select_first_row();
678 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
679 "%sFile loading was cancelled!%s\n"
681 "The remaining packets in the file were discarded.\n"
683 "As a lot of packets from the original file will be missing,\n"
684 "remember to be careful when saving the current content to a file.\n",
685 simple_dialog_primary_start(), simple_dialog_primary_end());
686 return CF_READ_ERROR;
690 /* Put up a message box noting that the read failed somewhere along
691 the line. Don't throw out the stuff we managed to read, though,
695 case WTAP_ERR_UNSUPPORTED:
696 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
697 "The capture file contains record data that TShark doesn't support.\n(%s)",
700 errmsg = errmsg_errno;
703 case WTAP_ERR_UNSUPPORTED_ENCAP:
704 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
705 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
708 errmsg = errmsg_errno;
711 case WTAP_ERR_CANT_READ:
712 errmsg = "An attempt to read from the capture file failed for"
713 " some unknown reason.";
716 case WTAP_ERR_SHORT_READ:
717 errmsg = "The capture file appears to have been cut short"
718 " in the middle of a packet.";
721 case WTAP_ERR_BAD_FILE:
722 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
723 "The capture file appears to be damaged or corrupt.\n(%s)",
726 errmsg = errmsg_errno;
729 case WTAP_ERR_DECOMPRESS:
730 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
731 "The compressed capture file appears to be damaged or corrupt.\n"
734 errmsg = errmsg_errno;
738 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
739 "An error occurred while reading the"
740 " capture file: %s.", wtap_strerror(err));
741 errmsg = errmsg_errno;
744 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
745 return CF_READ_ERROR;
752 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
754 cf_status_t cf_status;
756 cf_status = cf_open(cf, fname, is_tempfile, err);
761 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
763 gint64 data_offset = 0;
765 volatile int newly_displayed_packets = 0;
767 gboolean filtering_tap_listeners;
771 /* Compile the current display filter.
772 * We assume this will not fail since cf->dfilter is only set in
773 * cf_filter IFF the filter was valid.
775 compiled = dfilter_compile(cf->dfilter, &dfcode);
776 g_assert(!cf->dfilter || (compiled && dfcode));
778 /* Do we have any tap listeners with filters? */
779 filtering_tap_listeners = have_filtering_tap_listeners();
781 /* Get the union of the flags for all tap listeners. */
782 tap_flags = union_of_tap_listener_flags();
786 new_packet_list_check_end();
787 /* Don't freeze/thaw the list when doing live capture */
788 /*new_packet_list_freeze();*/
790 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
792 while (to_read != 0) {
793 wtap_cleareof(cf->wth);
794 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
797 if (cf->state == FILE_READ_ABORTED) {
798 /* Well, the user decided to exit Wireshark. Break out of the
799 loop, and let the code below (which is called even if there
800 aren't any packets left to read) exit. */
804 if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
805 data_offset) != -1) {
806 newly_displayed_packets++;
809 CATCH(OutOfMemoryError) {
812 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
813 "%sOut Of Memory!%s\n"
815 "Sorry, but Wireshark has to terminate now!\n"
817 "The capture file is not lost, it can be found at:\n"
820 "Some infos / workarounds can be found at:\n"
821 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
822 simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
823 /* we have to terminate, as we cannot recover from the memory error */
824 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
826 main_window_update();
827 /* XXX - how to avoid a busy wait? */
830 /* Don't freeze/thaw the list when doing live capture */
831 /*new_packet_list_thaw();*/
832 return CF_READ_ABORTED;
838 /* Cleanup and release all dfilter resources */
840 dfilter_free(dfcode);
843 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
844 cf->count, cf->state, *err);*/
846 /* Don't freeze/thaw the list when doing live capture */
847 /*new_packet_list_thaw();*/
848 /* With the new packet list the first packet
849 * isn't automatically selected.
851 if(!cf->current_frame)
852 new_packet_list_select_first_row();
854 /* moving to the end of the packet list - if the user requested so and
855 we have some new packets. */
856 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
857 new_packet_list_moveto_end();
859 if (cf->state == FILE_READ_ABORTED) {
860 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
861 so that our caller can kill off the capture child process;
862 this will cause an EOF on the pipe from the child, so
863 "cf_finish_tail()" will be called, and it will clean up
865 return CF_READ_ABORTED;
866 } else if (*err != 0) {
867 /* We got an error reading the capture file.
868 XXX - pop up a dialog box instead? */
869 g_warning("Error \"%s\" while reading: \"%s\"\n",
870 wtap_strerror(*err), cf->filename);
872 return CF_READ_ERROR;
878 cf_fake_continue_tail(capture_file *cf) {
879 cf->state = FILE_READ_DONE;
883 cf_finish_tail(capture_file *cf, int *err)
888 gboolean filtering_tap_listeners;
892 /* Compile the current display filter.
893 * We assume this will not fail since cf->dfilter is only set in
894 * cf_filter IFF the filter was valid.
896 compiled = dfilter_compile(cf->dfilter, &dfcode);
897 g_assert(!cf->dfilter || (compiled && dfcode));
899 /* Do we have any tap listeners with filters? */
900 filtering_tap_listeners = have_filtering_tap_listeners();
902 /* Get the union of the flags for all tap listeners. */
903 tap_flags = union_of_tap_listener_flags();
905 if(cf->wth == NULL) {
907 return CF_READ_ERROR;
910 new_packet_list_check_end();
911 /* Don't freeze/thaw the list when doing live capture */
912 /*new_packet_list_freeze();*/
914 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
915 if (cf->state == FILE_READ_ABORTED) {
916 /* Well, the user decided to abort the read. Break out of the
917 loop, and let the code below (which is called even if there
918 aren't any packets left to read) exit. */
921 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
924 /* Cleanup and release all dfilter resources */
926 dfilter_free(dfcode);
929 /* Don't freeze/thaw the list when doing live capture */
930 /*new_packet_list_thaw();*/
932 if (cf->state == FILE_READ_ABORTED) {
933 /* Well, the user decided to abort the read. We're only called
934 when the child capture process closes the pipe to us (meaning
935 it's probably exited), so we can just close the capture
936 file; we return CF_READ_ABORTED so our caller can do whatever
937 is appropriate when that happens. */
939 return CF_READ_ABORTED;
942 if (auto_scroll_live && cf->count != 0)
943 new_packet_list_moveto_end();
945 /* We're done reading sequentially through the file. */
946 cf->state = FILE_READ_DONE;
948 /* We're done reading sequentially through the file; close the
949 sequential I/O side, to free up memory it requires. */
950 wtap_sequential_close(cf->wth);
952 /* Allow the protocol dissectors to free up memory that they
953 * don't need after the sequential run-through of the packets. */
954 postseq_cleanup_all_protocols();
956 /* Set the file encapsulation type now; we don't know what it is until
957 we've looked at all the packets, as we don't know until then whether
958 there's more than one type (and thus whether it's
959 WTAP_ENCAP_PER_PACKET). */
960 cf->lnk_t = wtap_file_encap(cf->wth);
963 /* We got an error reading the capture file.
964 XXX - pop up a dialog box? */
965 return CF_READ_ERROR;
970 #endif /* HAVE_LIBPCAP */
973 cf_get_display_name(capture_file *cf)
975 const gchar *displayname;
977 /* Return a name to use in displays */
978 if (!cf->is_tempfile) {
979 /* Get the last component of the file name, and use that. */
981 displayname = get_basename(cf->filename);
983 displayname="(No file)";
986 /* The file we read is a temporary file from a live capture;
987 we don't mention its name. */
989 displayname = cf->source;
991 displayname = "(Untitled)";
997 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1003 cf->source = g_strdup(source);
1005 cf->source = g_strdup("");
1009 const gchar *cf_get_tempfile_source(capture_file *cf) {
1017 /* XXX - use a macro instead? */
1019 cf_get_packet_count(capture_file *cf)
1024 /* XXX - use a macro instead? */
1026 cf_set_packet_count(capture_file *cf, int packet_count)
1028 cf->count = packet_count;
1031 /* XXX - use a macro instead? */
1033 cf_is_tempfile(capture_file *cf)
1035 return cf->is_tempfile;
1038 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1040 cf->is_tempfile = is_tempfile;
1044 /* XXX - use a macro instead? */
1045 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1047 cf->drops_known = drops_known;
1050 /* XXX - use a macro instead? */
1051 void cf_set_drops(capture_file *cf, guint32 drops)
1056 /* XXX - use a macro instead? */
1057 gboolean cf_get_drops_known(capture_file *cf)
1059 return cf->drops_known;
1062 /* XXX - use a macro instead? */
1063 guint32 cf_get_drops(capture_file *cf)
1068 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1070 cf->rfcode = rfcode;
1074 find_and_mark_frame_depended_upon(gpointer data, gpointer user_data)
1076 frame_data *dependent_fd;
1077 guint32 dependent_frame = GPOINTER_TO_UINT(data);
1078 capture_file *cf = (capture_file *)user_data;
1080 dependent_fd = frame_data_sequence_find(cf->frames, dependent_frame);
1081 dependent_fd->flags.dependent_of_displayed = 1;
1085 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1086 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1088 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1090 gboolean add_to_packet_list)
1092 gboolean create_proto_tree = FALSE;
1097 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1099 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1100 &first_ts, &prev_dis_ts, &prev_cap_ts);
1103 + we have a display filter and are re-applying it;
1104 + we have tap listeners with filters;
1105 + we have tap listeners that require a protocol tree;
1107 allocate a protocol tree root node, so that we'll construct
1108 a protocol tree against which a filter expression can be
1110 if ((dfcode != NULL && refilter) ||
1111 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1112 create_proto_tree = TRUE;
1114 /* Dissect the frame. */
1115 epan_dissect_init(&edt, create_proto_tree, FALSE);
1117 if (dfcode != NULL && refilter) {
1118 epan_dissect_prime_dfilter(&edt, dfcode);
1121 tap_queue_init(&edt);
1122 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1123 tap_push_tapped_queue(&edt);
1125 /* If we have a display filter, apply it if we're refiltering, otherwise
1126 leave the "passed_dfilter" flag alone.
1128 If we don't have a display filter, set "passed_dfilter" to 1. */
1129 if (dfcode != NULL) {
1131 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1133 if (fdata->flags.passed_dfilter) {
1134 /* This frame passed the display filter but it may depend on other
1135 * (potentially not displayed) frames. Find those frames and mark them
1138 g_slist_foreach(edt.pi.dependent_frames, find_and_mark_frame_depended_upon, cf);
1142 fdata->flags.passed_dfilter = 1;
1144 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1145 cf->displayed_count++;
1147 if (add_to_packet_list) {
1148 /* We fill the needed columns from new_packet_list */
1149 row = new_packet_list_append(cinfo, fdata, &edt.pi);
1152 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1154 frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1156 /* If we haven't yet seen the first frame, this is it.
1158 XXX - we must do this before we add the row to the display,
1159 as, if the display's GtkCList's selection mode is
1160 GTK_SELECTION_BROWSE, when the first entry is added to it,
1161 "cf_select_packet()" will be called, and it will fetch the row
1162 data for the 0th row, and will get a null pointer rather than
1163 "fdata", as "gtk_clist_append()" won't yet have returned and
1164 thus "gtk_clist_set_row_data()" won't yet have been called.
1166 We thus need to leave behind bread crumbs so that
1167 "cf_select_packet()" can find this frame. See the comment
1168 in "cf_select_packet()". */
1169 if (cf->first_displayed == 0)
1170 cf->first_displayed = fdata->num;
1172 /* This is the last frame we've seen so far. */
1173 cf->last_displayed = fdata->num;
1176 epan_dissect_cleanup(&edt);
1180 /* read in a new packet */
1181 /* returns the row of the new packet in the packet list or -1 if not displayed */
1183 read_packet(capture_file *cf, dfilter_t *dfcode,
1184 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1186 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1187 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1188 const guchar *buf = wtap_buf_ptr(cf->wth);
1195 /* The frame number of this packet is one more than the count of
1196 frames in this packet. */
1197 framenum = cf->count + 1;
1199 frame_data_init(&fdlocal, framenum, phdr, offset, cum_bytes);
1204 epan_dissect_init(&edt, TRUE, FALSE);
1205 epan_dissect_prime_dfilter(&edt, cf->rfcode);
1206 epan_dissect_run(&edt, pseudo_header, buf, &fdlocal, NULL);
1207 passed = dfilter_apply_edt(cf->rfcode, &edt);
1208 epan_dissect_cleanup(&edt);
1212 /* This does a shallow copy of fdlocal, which is good enough. */
1213 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1216 cf->f_datalen = offset + fdlocal.cap_len;
1218 if (!cf->redissecting) {
1219 row = add_packet_to_packet_list(fdata, cf, dfcode,
1220 filtering_tap_listeners, tap_flags,
1221 pseudo_header, buf, TRUE, TRUE);
1229 cf_merge_files(char **out_filenamep, int in_file_count,
1230 char *const *in_filenames, int file_type, gboolean do_append)
1232 merge_in_file_t *in_files, *in_file;
1237 int open_err, read_err, write_err, close_err;
1241 char errmsg_errno[1024+1];
1243 gboolean got_read_error = FALSE, got_write_error = FALSE;
1245 progdlg_t *progbar = NULL;
1247 gint64 f_len, file_pos;
1249 GTimeVal start_time;
1250 gchar status_str[100];
1251 gint64 progbar_nextstep;
1252 gint64 progbar_quantum;
1254 /* open the input files */
1255 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1256 &open_err, &err_info, &err_fileno)) {
1258 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1263 if (*out_filenamep != NULL) {
1264 out_filename = *out_filenamep;
1265 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1269 out_fd = create_tempfile(&tmpname, "wireshark");
1272 out_filename = g_strdup(tmpname);
1273 *out_filenamep = out_filename;
1277 merge_close_in_files(in_file_count, in_files);
1279 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1283 pdh = wtap_dump_fdopen(out_fd, file_type,
1284 merge_select_frame_type(in_file_count, in_files),
1285 merge_max_snapshot_length(in_file_count, in_files),
1286 FALSE /* compressed */, &open_err);
1289 merge_close_in_files(in_file_count, in_files);
1291 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1296 /* Get the sum of the sizes of all the files. */
1298 for (i = 0; i < in_file_count; i++)
1299 f_len += in_files[i].size;
1301 /* Update the progress bar when it gets to this value. */
1302 progbar_nextstep = 0;
1303 /* When we reach the value that triggers a progress bar update,
1304 bump that value by this amount. */
1305 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1306 /* Progress so far. */
1310 g_get_current_time(&start_time);
1312 /* do the merge (or append) */
1315 in_file = merge_append_read_packet(in_file_count, in_files, &read_err,
1318 in_file = merge_read_packet(in_file_count, in_files, &read_err,
1320 if (in_file == NULL) {
1325 if (read_err != 0) {
1326 /* I/O error reading from in_file */
1327 got_read_error = TRUE;
1331 /* Get the sum of the data offsets in all of the files. */
1333 for (i = 0; i < in_file_count; i++)
1334 data_offset += in_files[i].data_offset;
1336 /* Create the progress bar if necessary.
1337 We check on every iteration of the loop, so that it takes no
1338 longer than the standard time to create it (otherwise, for a
1339 large file, we might take considerably longer than that standard
1340 time in order to get to the next progress bar step). */
1341 if (progbar == NULL) {
1342 progbar = delayed_create_progress_dlg("Merging", "files",
1343 FALSE, &stop_flag, &start_time, progbar_val);
1346 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1347 when we update it, we have to run the GTK+ main loop to get it
1348 to repaint what's pending, and doing so may involve an "ioctl()"
1349 to see if there's any pending input from an X server, and doing
1350 that for every packet can be costly, especially on a big file. */
1351 if (data_offset >= progbar_nextstep) {
1352 /* Get the sum of the seek positions in all of the files. */
1354 for (i = 0; i < in_file_count; i++)
1355 file_pos += wtap_read_so_far(in_files[i].wth);
1356 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1357 if (progbar_val > 1.0f) {
1358 /* Some file probably grew while we were reading it.
1359 That "shouldn't happen", so we'll just clip the progress
1363 if (progbar != NULL) {
1364 g_snprintf(status_str, sizeof(status_str),
1365 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1366 file_pos / 1024, f_len / 1024);
1367 update_progress_dlg(progbar, progbar_val, status_str);
1369 progbar_nextstep += progbar_quantum;
1373 /* Well, the user decided to abort the merge. */
1377 if (!wtap_dump(pdh, wtap_phdr(in_file->wth), wtap_pseudoheader(in_file->wth),
1378 wtap_buf_ptr(in_file->wth), &write_err)) {
1379 got_write_error = TRUE;
1384 /* We're done merging the files; destroy the progress bar if it was created. */
1385 if (progbar != NULL)
1386 destroy_progress_dlg(progbar);
1388 merge_close_in_files(in_file_count, in_files);
1389 if (!got_read_error && !got_write_error) {
1390 if (!wtap_dump_close(pdh, &write_err))
1391 got_write_error = TRUE;
1393 wtap_dump_close(pdh, &close_err);
1395 if (got_read_error) {
1397 * Find the file on which we got the error, and report the error.
1399 for (i = 0; i < in_file_count; i++) {
1400 if (in_files[i].state == GOT_ERROR) {
1401 /* Put up a message box noting that a read failed somewhere along
1405 case WTAP_ERR_UNSUPPORTED_ENCAP:
1406 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1407 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1410 errmsg = errmsg_errno;
1413 case WTAP_ERR_CANT_READ:
1414 errmsg = "An attempt to read from the capture file %s failed for"
1415 " some unknown reason.";
1418 case WTAP_ERR_SHORT_READ:
1419 errmsg = "The capture file %s appears to have been cut short"
1420 " in the middle of a packet.";
1423 case WTAP_ERR_BAD_FILE:
1424 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1425 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1428 errmsg = errmsg_errno;
1431 case WTAP_ERR_DECOMPRESS:
1432 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1433 "The compressed capture file %%s appears to be damaged or corrupt.\n"
1436 errmsg = errmsg_errno;
1440 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1441 "An error occurred while reading the"
1442 " capture file %%s: %s.", wtap_strerror(read_err));
1443 errmsg = errmsg_errno;
1446 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
1451 if (got_write_error) {
1452 /* Put up an alert box for the write error. */
1453 if (write_err < 0) {
1454 /* Wiretap error. */
1455 switch (write_err) {
1457 case WTAP_ERR_UNSUPPORTED_ENCAP:
1459 * This is a problem with the particular frame we're writing;
1460 * note that, and give the frame number.
1462 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1463 "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.",
1464 in_file->packet_num, in_file->filename,
1465 wtap_file_type_string(file_type));
1469 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1470 "An error occurred while writing to the file \"%s\": %s.",
1471 out_filename, wtap_strerror(write_err));
1476 write_failure_alert_box(out_filename, write_err);
1480 if (got_read_error || got_write_error || stop_flag) {
1481 /* Callers aren't expected to treat an error or an explicit abort
1482 differently - we put up error dialogs ourselves, so they don't
1490 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1492 const char *filter_new = dftext ? dftext : "";
1493 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1495 GTimeVal start_time;
1497 /* if new filter equals old one, do nothing unless told to do so */
1498 if (!force && strcmp(filter_new, filter_old) == 0) {
1504 if (dftext == NULL) {
1505 /* The new filter is an empty filter (i.e., display all packets).
1506 * so leave dfcode==NULL
1510 * We have a filter; make a copy of it (as we'll be saving it),
1511 * and try to compile it.
1513 dftext = g_strdup(dftext);
1514 if (!dfilter_compile(dftext, &dfcode)) {
1515 /* The attempt failed; report an error. */
1516 gchar *safe_dftext = simple_dialog_format_message(dftext);
1517 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1519 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1522 "The following display filter isn't a valid display filter:\n%s\n"
1523 "See the help for a description of the display filter syntax.",
1524 simple_dialog_primary_start(), safe_dfilter_error_msg,
1525 simple_dialog_primary_end(), safe_dftext);
1526 g_free(safe_dfilter_error_msg);
1527 g_free(safe_dftext);
1533 if (dfcode == NULL) {
1534 /* Yes - free the filter text, and set it to null. */
1540 /* We have a valid filter. Replace the current filter. */
1541 g_free(cf->dfilter);
1542 cf->dfilter = dftext;
1543 g_get_current_time(&start_time);
1546 /* Now rescan the packet list, applying the new filter, but not
1547 throwing away information constructed on a previous pass. */
1548 if (dftext == NULL) {
1549 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1551 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1554 /* Cleanup and release all dfilter resources */
1555 dfilter_free(dfcode);
1561 cf_reftime_packets(capture_file *cf)
1564 ref_time_packets(cf);
1568 cf_redissect_packets(capture_file *cf)
1570 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1574 cf_read_frame_r(capture_file *cf, frame_data *fdata,
1575 union wtap_pseudo_header *pseudo_header, guint8 *pd)
1579 char errmsg_errno[1024+1];
1581 #ifdef WANT_PACKET_EDITOR
1582 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1583 if (G_UNLIKELY(fdata->file_off == -1)) {
1584 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1587 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "fdata->file_off == -1, but can't find modified frame!");
1591 *pseudo_header = frame->ph;
1592 memcpy(pd, frame->pd, fdata->cap_len);
1597 if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
1598 fdata->cap_len, &err, &err_info)) {
1601 case WTAP_ERR_UNSUPPORTED_ENCAP:
1602 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1603 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1608 case WTAP_ERR_BAD_FILE:
1609 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1610 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
1611 wtap_strerror(err), err_info);
1616 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1617 "An error occurred while reading from the file \"%%s\": %s.",
1618 wtap_strerror(err));
1621 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg_errno, cf->filename);
1628 cf_read_frame(capture_file *cf, frame_data *fdata)
1630 return cf_read_frame_r(cf, fdata, &cf->pseudo_header, cf->pd);
1633 /* Rescan the list of packets, reconstructing the CList.
1635 "action" describes why we're doing this; it's used in the progress
1638 "action_item" describes what we're doing; it's used in the progress
1641 "refilter" is TRUE if we need to re-evaluate the filter expression.
1643 "redissect" is TRUE if we need to make the dissectors reconstruct
1644 any state information they have (because a preference that affects
1645 some dissector has changed, meaning some dissector might construct
1646 its state differently from the way it was constructed the last time). */
1648 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1649 gboolean refilter, gboolean redissect)
1651 /* Rescan packets new packet list */
1654 progdlg_t *progbar = NULL;
1657 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1658 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1659 gboolean selected_frame_seen;
1661 GTimeVal start_time;
1662 gchar status_str[100];
1663 int progbar_nextstep;
1664 int progbar_quantum;
1666 gboolean filtering_tap_listeners;
1668 gboolean add_to_packet_list = FALSE;
1671 /* Compile the current display filter.
1672 * We assume this will not fail since cf->dfilter is only set in
1673 * cf_filter IFF the filter was valid.
1675 compiled = dfilter_compile(cf->dfilter, &dfcode);
1676 g_assert(!cf->dfilter || (compiled && dfcode));
1678 /* Do we have any tap listeners with filters? */
1679 filtering_tap_listeners = have_filtering_tap_listeners();
1681 /* Get the union of the flags for all tap listeners. */
1682 tap_flags = union_of_tap_listener_flags();
1684 reset_tap_listeners();
1685 /* Which frame, if any, is the currently selected frame?
1686 XXX - should the selected frame or the focus frame be the "current"
1687 frame, that frame being the one from which "Find Frame" searches
1689 selected_frame = cf->current_frame;
1691 /* Mark frame num as not found */
1692 selected_frame_num = -1;
1694 /* Freeze the packet list while we redo it, so we don't get any
1695 screen updates while it happens. */
1696 new_packet_list_freeze();
1699 /* We need to re-initialize all the state information that protocols
1700 keep, because some preference that controls a dissector has changed,
1701 which might cause the state information to be constructed differently
1702 by that dissector. */
1704 /* We might receive new packets while redissecting, and we don't
1705 want to dissect those before their time. */
1706 cf->redissecting = TRUE;
1708 /* Cleanup all data structures used for dissection. */
1709 cleanup_dissection();
1710 /* Initialize all data structures used for dissection. */
1713 /* We need to redissect the packets so we have to discard our old
1714 * packet list store. */
1715 new_packet_list_clear();
1716 add_to_packet_list = TRUE;
1719 /* We don't yet know which will be the first and last frames displayed. */
1720 cf->first_displayed = 0;
1721 cf->last_displayed = 0;
1723 /* We currently don't display any packets */
1724 cf->displayed_count = 0;
1726 /* Iterate through the list of frames. Call a routine for each frame
1727 to check whether it should be displayed and, if so, add it to
1728 the display list. */
1729 nstime_set_unset(&first_ts);
1730 nstime_set_unset(&prev_dis_ts);
1731 nstime_set_unset(&prev_cap_ts);
1734 /* Update the progress bar when it gets to this value. */
1735 progbar_nextstep = 0;
1736 /* When we reach the value that triggers a progress bar update,
1737 bump that value by this amount. */
1738 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1739 /* Count of packets at which we've looked. */
1741 /* Progress so far. */
1745 g_get_current_time(&start_time);
1747 /* no previous row yet */
1748 prev_frame_num = -1;
1751 preceding_frame_num = -1;
1752 preceding_frame = NULL;
1753 following_frame_num = -1;
1754 following_frame = NULL;
1756 selected_frame_seen = FALSE;
1758 for (framenum = 1; framenum <= cf->count; framenum++) {
1759 fdata = frame_data_sequence_find(cf->frames, framenum);
1761 /* Create the progress bar if necessary.
1762 We check on every iteration of the loop, so that it takes no
1763 longer than the standard time to create it (otherwise, for a
1764 large file, we might take considerably longer than that standard
1765 time in order to get to the next progress bar step). */
1766 if (progbar == NULL)
1767 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1768 &stop_flag, &start_time,
1771 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1772 when we update it, we have to run the GTK+ main loop to get it
1773 to repaint what's pending, and doing so may involve an "ioctl()"
1774 to see if there's any pending input from an X server, and doing
1775 that for every packet can be costly, especially on a big file. */
1776 if (count >= progbar_nextstep) {
1777 /* let's not divide by zero. I should never be started
1778 * with count == 0, so let's assert that
1780 g_assert(cf->count > 0);
1781 progbar_val = (gfloat) count / cf->count;
1783 if (progbar != NULL) {
1784 g_snprintf(status_str, sizeof(status_str),
1785 "%4u of %u frames", count, cf->count);
1786 update_progress_dlg(progbar, progbar_val, status_str);
1789 progbar_nextstep += progbar_quantum;
1793 /* Well, the user decided to abort the filtering. Just stop.
1795 XXX - go back to the previous filter? Users probably just
1796 want not to wait for a filtering operation to finish;
1797 unless we cancel by having no filter, reverting to the
1798 previous filter will probably be even more expensive than
1799 continuing the filtering, as it involves going back to the
1800 beginning and filtering, and even with no filter we currently
1801 have to re-generate the entire clist, which is also expensive.
1803 I'm not sure what Network Monitor does, but it doesn't appear
1804 to give you an unfiltered display if you cancel. */
1811 /* Since all state for the frame was destroyed, mark the frame
1812 * as not visited, free the GSList referring to the state
1813 * data (the per-frame data itself was freed by
1814 * "init_dissection()"), and null out the GSList pointer. */
1815 fdata->flags.visited = 0;
1816 frame_data_cleanup(fdata);
1819 if (redissect || refilter) {
1820 /* If we're redissecting or refiltering then any frame dependencies
1821 * from the previous dissection/filtering are no longer valid.
1823 fdata->flags.dependent_of_displayed = 0;
1826 if (!cf_read_frame(cf, fdata))
1827 break; /* error reading the frame */
1829 /* If the previous frame is displayed, and we haven't yet seen the
1830 selected frame, remember that frame - it's the closest one we've
1831 yet seen before the selected frame. */
1832 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1833 preceding_frame_num = prev_frame_num;
1834 preceding_frame = prev_frame;
1836 add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1837 tap_flags, &cf->pseudo_header, cf->pd,
1839 add_to_packet_list);
1841 /* If this frame is displayed, and this is the first frame we've
1842 seen displayed after the selected frame, remember this frame -
1843 it's the closest one we've yet seen at or after the selected
1845 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1846 following_frame_num = fdata->num;
1847 following_frame = fdata;
1849 if (fdata == selected_frame) {
1850 selected_frame_seen = TRUE;
1851 if (fdata->flags.passed_dfilter)
1852 selected_frame_num = fdata->num;
1855 /* Remember this frame - it'll be the previous frame
1856 on the next pass through the loop. */
1857 prev_frame_num = fdata->num;
1861 /* We are done redissecting the packet list. */
1862 cf->redissecting = FALSE;
1865 /* Clear out what remains of the visited flags and per-frame data
1868 XXX - that may cause various forms of bogosity when dissecting
1869 these frames, as they won't have been seen by this sequential
1870 pass, but the only alternative I see is to keep scanning them
1871 even though the user requested that the scan stop, and that
1872 would leave the user stuck with an Wireshark grinding on
1873 until it finishes. Should we just stick them with that? */
1874 for (; framenum <= cf->count; framenum++) {
1875 fdata = frame_data_sequence_find(cf->frames, framenum);
1876 fdata->flags.visited = 0;
1877 frame_data_cleanup(fdata);
1881 /* We're done filtering the packets; destroy the progress bar if it
1883 if (progbar != NULL)
1884 destroy_progress_dlg(progbar);
1886 /* Unfreeze the packet list. */
1887 if (!add_to_packet_list)
1888 new_packet_list_recreate_visible_rows();
1890 /* Compute the time it took to filter the file */
1891 compute_elapsed(&start_time);
1893 new_packet_list_thaw();
1895 if (selected_frame_num == -1) {
1896 /* The selected frame didn't pass the filter. */
1897 if (selected_frame == NULL) {
1898 /* That's because there *was* no selected frame. Make the first
1899 displayed frame the current frame. */
1900 selected_frame_num = 0;
1902 /* Find the nearest displayed frame to the selected frame (whether
1903 it's before or after that frame) and make that the current frame.
1904 If the next and previous displayed frames are equidistant from the
1905 selected frame, choose the next one. */
1906 g_assert(following_frame == NULL ||
1907 following_frame->num >= selected_frame->num);
1908 g_assert(preceding_frame == NULL ||
1909 preceding_frame->num <= selected_frame->num);
1910 if (following_frame == NULL) {
1911 /* No frame after the selected frame passed the filter, so we
1912 have to select the last displayed frame before the selected
1914 selected_frame_num = preceding_frame_num;
1915 selected_frame = preceding_frame;
1916 } else if (preceding_frame == NULL) {
1917 /* No frame before the selected frame passed the filter, so we
1918 have to select the first displayed frame after the selected
1920 selected_frame_num = following_frame_num;
1921 selected_frame = following_frame;
1923 /* Frames before and after the selected frame passed the filter, so
1924 we'll select the previous frame */
1925 selected_frame_num = preceding_frame_num;
1926 selected_frame = preceding_frame;
1931 if (selected_frame_num == -1) {
1932 /* There are no frames displayed at all. */
1933 cf_unselect_packet(cf);
1935 /* Either the frame that was selected passed the filter, or we've
1936 found the nearest displayed frame to that frame. Select it, make
1937 it the focus row, and make it visible. */
1938 /* Set to invalid to force update of packet list and packet details */
1939 cf->current_row = -1;
1940 if (selected_frame_num == 0) {
1941 new_packet_list_select_first_row();
1943 if (!new_packet_list_select_row_from_data(selected_frame)) {
1944 /* We didn't find a row corresponding to this frame.
1945 This means that the frame isn't being displayed currently,
1946 so we can't select it. */
1947 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
1948 "%sEnd of capture exceeded!%s\n\n"
1949 "The capture file is probably not fully dissected.",
1950 simple_dialog_primary_start(), simple_dialog_primary_end());
1955 /* Cleanup and release all dfilter resources */
1956 dfilter_free(dfcode);
1961 * Scan trough all frame data and recalculate the ref time
1962 * without rereading the file.
1963 * XXX - do we need a progres bar or is this fast enough?
1966 ref_time_packets(capture_file *cf)
1971 nstime_set_unset(&first_ts);
1972 nstime_set_unset(&prev_dis_ts);
1975 for (framenum = 1; framenum <= cf->count; framenum++) {
1976 fdata = frame_data_sequence_find(cf->frames, framenum);
1978 /* just add some value here until we know if it is being displayed or not */
1979 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1985 /* If we don't have the time stamp of the first packet in the
1986 capture, it's because this is the first packet. Save the time
1987 stamp of this packet as the time stamp of the first packet. */
1988 if (nstime_is_unset(&first_ts)) {
1989 first_ts = fdata->abs_ts;
1991 /* if this frames is marked as a reference time frame, reset
1992 firstsec and firstusec to this frame */
1993 if(fdata->flags.ref_time){
1994 first_ts = fdata->abs_ts;
1997 /* If we don't have the time stamp of the previous displayed packet,
1998 it's because this is the first displayed packet. Save the time
1999 stamp of this packet as the time stamp of the previous displayed
2001 if (nstime_is_unset(&prev_dis_ts)) {
2002 prev_dis_ts = fdata->abs_ts;
2005 /* Get the time elapsed between the first packet and this packet. */
2006 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
2008 /* If it's greater than the current elapsed time, set the elapsed time
2009 to it (we check for "greater than" so as not to be confused by
2010 time moving backwards). */
2011 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
2012 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
2013 cf->elapsed_time = fdata->rel_ts;
2016 /* If this frame is displayed, get the time elapsed between the
2017 previous displayed packet and this packet. */
2018 if( fdata->flags.passed_dfilter ) {
2019 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
2020 prev_dis_ts = fdata->abs_ts;
2026 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
2027 /* This frame either passed the display filter list or is marked as
2028 a time reference frame. All time reference frames are displayed
2029 even if they dont pass the display filter */
2030 if(fdata->flags.ref_time){
2031 /* if this was a TIME REF frame we should reset the cum_bytes field */
2032 cum_bytes = fdata->pkt_len;
2033 fdata->cum_bytes = cum_bytes;
2035 /* increase cum_bytes with this packets length */
2036 cum_bytes += fdata->pkt_len;
2049 process_specified_packets(capture_file *cf, packet_range_t *range,
2050 const char *string1, const char *string2, gboolean terminate_is_stop,
2051 gboolean (*callback)(capture_file *, frame_data *,
2052 union wtap_pseudo_header *, const guint8 *, void *),
2053 void *callback_args)
2057 union wtap_pseudo_header pseudo_header;
2058 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
2059 psp_return_t ret = PSP_FINISHED;
2061 progdlg_t *progbar = NULL;
2064 gboolean progbar_stop_flag;
2065 GTimeVal progbar_start_time;
2066 gchar progbar_status_str[100];
2067 int progbar_nextstep;
2068 int progbar_quantum;
2069 range_process_e process_this;
2071 /* Update the progress bar when it gets to this value. */
2072 progbar_nextstep = 0;
2073 /* When we reach the value that triggers a progress bar update,
2074 bump that value by this amount. */
2075 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2076 /* Count of packets at which we've looked. */
2078 /* Progress so far. */
2081 progbar_stop_flag = FALSE;
2082 g_get_current_time(&progbar_start_time);
2084 packet_range_process_init(range);
2086 /* Iterate through all the packets, printing the packets that
2087 were selected by the current display filter. */
2088 for (framenum = 1; framenum <= cf->count; framenum++) {
2089 fdata = frame_data_sequence_find(cf->frames, framenum);
2091 /* Create the progress bar if necessary.
2092 We check on every iteration of the loop, so that it takes no
2093 longer than the standard time to create it (otherwise, for a
2094 large file, we might take considerably longer than that standard
2095 time in order to get to the next progress bar step). */
2096 if (progbar == NULL)
2097 progbar = delayed_create_progress_dlg(string1, string2,
2100 &progbar_start_time,
2103 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2104 when we update it, we have to run the GTK+ main loop to get it
2105 to repaint what's pending, and doing so may involve an "ioctl()"
2106 to see if there's any pending input from an X server, and doing
2107 that for every packet can be costly, especially on a big file. */
2108 if (progbar_count >= progbar_nextstep) {
2109 /* let's not divide by zero. I should never be started
2110 * with count == 0, so let's assert that
2112 g_assert(cf->count > 0);
2113 progbar_val = (gfloat) progbar_count / cf->count;
2115 if (progbar != NULL) {
2116 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2117 "%4u of %u packets", progbar_count, cf->count);
2118 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2121 progbar_nextstep += progbar_quantum;
2124 if (progbar_stop_flag) {
2125 /* Well, the user decided to abort the operation. Just stop,
2126 and arrange to return PSP_STOPPED to our caller, so they know
2127 it was stopped explicitly. */
2134 /* do we have to process this packet? */
2135 process_this = packet_range_process_packet(range, fdata);
2136 if (process_this == range_process_next) {
2137 /* this packet uninteresting, continue with next one */
2139 } else if (process_this == range_processing_finished) {
2140 /* all interesting packets processed, stop the loop */
2144 /* Get the packet */
2145 if (!cf_read_frame_r(cf, fdata, &pseudo_header, pd)) {
2146 /* Attempt to get the packet failed. */
2150 /* Process the packet */
2151 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
2152 /* Callback failed. We assume it reported the error appropriately. */
2158 /* We're done printing the packets; destroy the progress bar if
2160 if (progbar != NULL)
2161 destroy_progress_dlg(progbar);
2167 gboolean construct_protocol_tree;
2169 } retap_callback_args_t;
2172 retap_packet(capture_file *cf _U_, frame_data *fdata,
2173 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2176 retap_callback_args_t *args = argsp;
2179 epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
2180 tap_queue_init(&edt);
2181 epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
2182 tap_push_tapped_queue(&edt);
2183 epan_dissect_cleanup(&edt);
2189 cf_retap_packets(capture_file *cf)
2191 packet_range_t range;
2192 retap_callback_args_t callback_args;
2193 gboolean filtering_tap_listeners;
2196 /* Do we have any tap listeners with filters? */
2197 filtering_tap_listeners = have_filtering_tap_listeners();
2199 tap_flags = union_of_tap_listener_flags();
2201 /* If any tap listeners have filters, or require the protocol tree,
2202 construct the protocol tree. */
2203 callback_args.construct_protocol_tree = filtering_tap_listeners ||
2204 (tap_flags & TL_REQUIRES_PROTO_TREE);
2206 /* If any tap listeners require the columns, construct them. */
2207 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2209 /* Reset the tap listeners. */
2210 reset_tap_listeners();
2212 /* Iterate through the list of packets, dissecting all packets and
2213 re-running the taps. */
2214 packet_range_init(&range);
2215 packet_range_process_init(&range);
2216 switch (process_specified_packets(cf, &range, "Recalculating statistics on",
2217 "all packets", TRUE, retap_packet,
2220 /* Completed successfully. */
2224 /* Well, the user decided to abort the refiltering.
2225 Return CF_READ_ABORTED so our caller knows they did that. */
2226 return CF_READ_ABORTED;
2229 /* Error while retapping. */
2230 return CF_READ_ERROR;
2233 g_assert_not_reached();
2238 print_args_t *print_args;
2239 gboolean print_header_line;
2240 char *header_line_buf;
2241 int header_line_buf_len;
2242 gboolean print_formfeed;
2243 gboolean print_separator;
2247 } print_callback_args_t;
2250 print_packet(capture_file *cf, frame_data *fdata,
2251 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2254 print_callback_args_t *args = argsp;
2261 gboolean proto_tree_needed;
2262 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2263 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2265 /* Create the protocol tree, and make it visible, if we're printing
2266 the dissection or the hex data.
2267 XXX - do we need it if we're just printing the hex data? */
2269 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2270 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2272 /* Fill in the column information if we're printing the summary
2274 if (args->print_args->print_summary) {
2275 col_custom_prime_edt(&edt, &cf->cinfo);
2276 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2277 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2279 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2281 if (args->print_formfeed) {
2282 if (!new_page(args->print_args->stream))
2285 if (args->print_separator) {
2286 if (!print_line(args->print_args->stream, 0, ""))
2292 * We generate bookmarks, if the output format supports them.
2293 * The name is "__frameN__".
2295 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2297 if (args->print_args->print_summary) {
2298 if (args->print_header_line) {
2299 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2301 args->print_header_line = FALSE; /* we might not need to print any more */
2303 cp = &args->line_buf[0];
2305 for (i = 0; i < cf->cinfo.num_cols; i++) {
2306 /* Find the length of the string for this column. */
2307 column_len = (int) strlen(cf->cinfo.col_data[i]);
2308 if (args->col_widths[i] > column_len)
2309 column_len = args->col_widths[i];
2311 /* Make sure there's room in the line buffer for the column; if not,
2312 double its length. */
2313 line_len += column_len + 1; /* "+1" for space */
2314 if (line_len > args->line_buf_len) {
2315 cp_off = (int) (cp - args->line_buf);
2316 args->line_buf_len = 2 * line_len;
2317 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2318 cp = args->line_buf + cp_off;
2321 /* Right-justify the packet number column. */
2322 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2323 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
2325 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
2327 if (i != cf->cinfo.num_cols - 1)
2333 * Generate a bookmark, using the summary line as the title.
2335 if (!print_bookmark(args->print_args->stream, bookmark_name,
2339 if (!print_line(args->print_args->stream, 0, args->line_buf))
2343 * Generate a bookmark, using "Frame N" as the title, as we're not
2344 * printing the summary line.
2346 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2347 if (!print_bookmark(args->print_args->stream, bookmark_name,
2350 } /* if (print_summary) */
2352 if (args->print_args->print_dissections != print_dissections_none) {
2353 if (args->print_args->print_summary) {
2354 /* Separate the summary line from the tree with a blank line. */
2355 if (!print_line(args->print_args->stream, 0, ""))
2359 /* Print the information in that tree. */
2360 if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
2363 /* Print a blank line if we print anything after this (aka more than one packet). */
2364 args->print_separator = TRUE;
2366 /* Print a header line if we print any more packet summaries */
2367 args->print_header_line = TRUE;
2370 if (args->print_args->print_hex) {
2371 /* Print the full packet data as hex. */
2372 if (!print_hex_data(args->print_args->stream, &edt))
2375 /* Print a blank line if we print anything after this (aka more than one packet). */
2376 args->print_separator = TRUE;
2378 /* Print a header line if we print any more packet summaries */
2379 args->print_header_line = TRUE;
2380 } /* if (args->print_args->print_dissections != print_dissections_none) */
2382 epan_dissect_cleanup(&edt);
2384 /* do we want to have a formfeed between each packet from now on? */
2385 if(args->print_args->print_formfeed) {
2386 args->print_formfeed = TRUE;
2392 epan_dissect_cleanup(&edt);
2397 cf_print_packets(capture_file *cf, print_args_t *print_args)
2400 print_callback_args_t callback_args;
2408 callback_args.print_args = print_args;
2409 callback_args.print_header_line = TRUE;
2410 callback_args.header_line_buf = NULL;
2411 callback_args.header_line_buf_len = 256;
2412 callback_args.print_formfeed = FALSE;
2413 callback_args.print_separator = FALSE;
2414 callback_args.line_buf = NULL;
2415 callback_args.line_buf_len = 256;
2416 callback_args.col_widths = NULL;
2418 if (!print_preamble(print_args->stream, cf->filename)) {
2419 destroy_print_stream(print_args->stream);
2420 return CF_PRINT_WRITE_ERROR;
2423 if (print_args->print_summary) {
2424 /* We're printing packet summaries. Allocate the header line buffer
2425 and get the column widths. */
2426 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2428 /* Find the widths for each of the columns - maximum of the
2429 width of the title and the width of the data - and construct
2430 a buffer with a line containing the column titles. */
2431 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2432 cp = &callback_args.header_line_buf[0];
2434 for (i = 0; i < cf->cinfo.num_cols; i++) {
2435 /* Don't pad the last column. */
2436 if (i == cf->cinfo.num_cols - 1)
2437 callback_args.col_widths[i] = 0;
2439 callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
2440 data_width = get_column_char_width(get_column_format(i));
2441 if (data_width > callback_args.col_widths[i])
2442 callback_args.col_widths[i] = data_width;
2445 /* Find the length of the string for this column. */
2446 column_len = (int) strlen(cf->cinfo.col_title[i]);
2447 if (callback_args.col_widths[i] > column_len)
2448 column_len = callback_args.col_widths[i];
2450 /* Make sure there's room in the line buffer for the column; if not,
2451 double its length. */
2452 line_len += column_len + 1; /* "+1" for space */
2453 if (line_len > callback_args.header_line_buf_len) {
2454 cp_off = (int) (cp - callback_args.header_line_buf);
2455 callback_args.header_line_buf_len = 2 * line_len;
2456 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2457 callback_args.header_line_buf_len + 1);
2458 cp = callback_args.header_line_buf + cp_off;
2461 /* Right-justify the packet number column. */
2462 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2463 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2465 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2467 if (i != cf->cinfo.num_cols - 1)
2472 /* Now start out the main line buffer with the same length as the
2473 header line buffer. */
2474 callback_args.line_buf_len = callback_args.header_line_buf_len;
2475 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2476 } /* if (print_summary) */
2478 /* Iterate through the list of packets, printing the packets we were
2480 ret = process_specified_packets(cf, &print_args->range, "Printing",
2481 "selected packets", TRUE, print_packet,
2484 g_free(callback_args.header_line_buf);
2485 g_free(callback_args.line_buf);
2486 g_free(callback_args.col_widths);
2491 /* Completed successfully. */
2495 /* Well, the user decided to abort the printing.
2497 XXX - note that what got generated before they did that
2498 will get printed if we're piping to a print program; we'd
2499 have to write to a file and then hand that to the print
2500 program to make it actually not print anything. */
2504 /* Error while printing.
2506 XXX - note that what got generated before they did that
2507 will get printed if we're piping to a print program; we'd
2508 have to write to a file and then hand that to the print
2509 program to make it actually not print anything. */
2510 destroy_print_stream(print_args->stream);
2511 return CF_PRINT_WRITE_ERROR;
2514 if (!print_finale(print_args->stream)) {
2515 destroy_print_stream(print_args->stream);
2516 return CF_PRINT_WRITE_ERROR;
2519 if (!destroy_print_stream(print_args->stream))
2520 return CF_PRINT_WRITE_ERROR;
2526 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2527 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2533 /* Create the protocol tree, but don't fill in the column information. */
2534 epan_dissect_init(&edt, TRUE, TRUE);
2535 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2537 /* Write out the information in that tree. */
2538 proto_tree_write_pdml(&edt, fh);
2540 epan_dissect_cleanup(&edt);
2546 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2551 fh = ws_fopen(print_args->file, "w");
2553 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2555 write_pdml_preamble(fh, cf->filename);
2558 return CF_PRINT_WRITE_ERROR;
2561 /* Iterate through the list of packets, printing the packets we were
2563 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2564 "selected packets", TRUE,
2565 write_pdml_packet, fh);
2570 /* Completed successfully. */
2574 /* Well, the user decided to abort the printing. */
2578 /* Error while printing. */
2580 return CF_PRINT_WRITE_ERROR;
2583 write_pdml_finale(fh);
2586 return CF_PRINT_WRITE_ERROR;
2589 /* XXX - check for an error */
2596 write_psml_packet(capture_file *cf, frame_data *fdata,
2597 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2602 gboolean proto_tree_needed;
2604 /* Fill in the column information, only create the protocol tree
2605 if having custom columns. */
2606 proto_tree_needed = have_custom_cols(&cf->cinfo);
2607 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2608 col_custom_prime_edt(&edt, &cf->cinfo);
2609 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2610 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2612 /* Write out the information in that tree. */
2613 proto_tree_write_psml(&edt, fh);
2615 epan_dissect_cleanup(&edt);
2621 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2626 fh = ws_fopen(print_args->file, "w");
2628 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2630 write_psml_preamble(fh);
2633 return CF_PRINT_WRITE_ERROR;
2636 /* Iterate through the list of packets, printing the packets we were
2638 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2639 "selected packets", TRUE,
2640 write_psml_packet, fh);
2645 /* Completed successfully. */
2649 /* Well, the user decided to abort the printing. */
2653 /* Error while printing. */
2655 return CF_PRINT_WRITE_ERROR;
2658 write_psml_finale(fh);
2661 return CF_PRINT_WRITE_ERROR;
2664 /* XXX - check for an error */
2671 write_csv_packet(capture_file *cf, frame_data *fdata,
2672 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2677 gboolean proto_tree_needed;
2679 /* Fill in the column information, only create the protocol tree
2680 if having custom columns. */
2681 proto_tree_needed = have_custom_cols(&cf->cinfo);
2682 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2683 col_custom_prime_edt(&edt, &cf->cinfo);
2684 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2685 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2687 /* Write out the information in that tree. */
2688 proto_tree_write_csv(&edt, fh);
2690 epan_dissect_cleanup(&edt);
2696 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2701 fh = ws_fopen(print_args->file, "w");
2703 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2705 write_csv_preamble(fh);
2708 return CF_PRINT_WRITE_ERROR;
2711 /* Iterate through the list of packets, printing the packets we were
2713 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2714 "selected packets", TRUE,
2715 write_csv_packet, fh);
2720 /* Completed successfully. */
2724 /* Well, the user decided to abort the printing. */
2728 /* Error while printing. */
2730 return CF_PRINT_WRITE_ERROR;
2733 write_csv_finale(fh);
2736 return CF_PRINT_WRITE_ERROR;
2739 /* XXX - check for an error */
2746 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
2747 union wtap_pseudo_header *pseudo_header,
2748 const guint8 *pd, void *argsp)
2753 epan_dissect_init(&edt, TRUE, TRUE);
2754 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2755 proto_tree_write_carrays(fdata->num, fh, &edt);
2756 epan_dissect_cleanup(&edt);
2762 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2767 fh = ws_fopen(print_args->file, "w");
2770 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2772 write_carrays_preamble(fh);
2776 return CF_PRINT_WRITE_ERROR;
2779 /* Iterate through the list of packets, printing the packets we were
2781 ret = process_specified_packets(cf, &print_args->range,
2783 "selected packets", TRUE,
2784 write_carrays_packet, fh);
2787 /* Completed successfully. */
2790 /* Well, the user decided to abort the printing. */
2793 /* Error while printing. */
2795 return CF_PRINT_WRITE_ERROR;
2798 write_carrays_finale(fh);
2802 return CF_PRINT_WRITE_ERROR;
2810 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2811 search_direction dir)
2815 mdata.string = string;
2816 mdata.string_len = strlen(string);
2817 return find_packet(cf, match_protocol_tree, &mdata, dir);
2821 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2823 mdata->frame_matched = FALSE;
2824 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2825 mdata->string_len = strlen(mdata->string);
2827 /* Iterate through all the nodes looking for matching text */
2828 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2829 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2833 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2835 match_data *mdata = criterion;
2838 /* Load the frame's data. */
2839 if (!cf_read_frame(cf, fdata)) {
2840 /* Attempt to get the packet failed. */
2844 /* Construct the protocol tree, including the displayed text */
2845 epan_dissect_init(&edt, TRUE, TRUE);
2846 /* We don't need the column information */
2847 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2849 /* Iterate through all the nodes, seeing if they have text that matches. */
2851 mdata->frame_matched = FALSE;
2852 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2853 epan_dissect_cleanup(&edt);
2854 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2858 match_subtree_text(proto_node *node, gpointer data)
2860 match_data *mdata = (match_data *) data;
2861 const gchar *string = mdata->string;
2862 size_t string_len = mdata->string_len;
2863 capture_file *cf = mdata->cf;
2864 field_info *fi = PNODE_FINFO(node);
2865 gchar label_str[ITEM_LABEL_LENGTH];
2872 g_assert(fi && "dissection with an invisible proto tree?");
2874 if (mdata->frame_matched) {
2875 /* We already had a match; don't bother doing any more work. */
2879 /* Don't match invisible entries. */
2880 if (PROTO_ITEM_IS_HIDDEN(node))
2883 /* was a free format label produced? */
2885 label_ptr = fi->rep->representation;
2887 /* no, make a generic label */
2888 label_ptr = label_str;
2889 proto_item_fill_label(fi, label_str);
2892 /* Does that label match? */
2893 label_len = strlen(label_ptr);
2894 for (i = 0; i < label_len; i++) {
2895 c_char = label_ptr[i];
2897 c_char = toupper(c_char);
2898 if (c_char == string[c_match]) {
2900 if (c_match == string_len) {
2901 /* No need to look further; we have a match */
2902 mdata->frame_matched = TRUE;
2910 /* Recurse into the subtree, if it exists */
2911 if (node->first_child != NULL)
2912 proto_tree_children_foreach(node, match_subtree_text, mdata);
2916 cf_find_packet_summary_line(capture_file *cf, const char *string,
2917 search_direction dir)
2921 mdata.string = string;
2922 mdata.string_len = strlen(string);
2923 return find_packet(cf, match_summary_line, &mdata, dir);
2927 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2929 match_data *mdata = criterion;
2930 const gchar *string = mdata->string;
2931 size_t string_len = mdata->string_len;
2933 const char *info_column;
2934 size_t info_column_len;
2935 match_result result = MR_NOTMATCHED;
2941 /* Load the frame's data. */
2942 if (!cf_read_frame(cf, fdata)) {
2943 /* Attempt to get the packet failed. */
2947 /* Don't bother constructing the protocol tree */
2948 epan_dissect_init(&edt, FALSE, FALSE);
2949 /* Get the column information */
2950 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2952 /* Find the Info column */
2953 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2954 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2955 /* Found it. See if we match. */
2956 info_column = edt.pi.cinfo->col_data[colx];
2957 info_column_len = strlen(info_column);
2958 for (i = 0; i < info_column_len; i++) {
2959 c_char = info_column[i];
2961 c_char = toupper(c_char);
2962 if (c_char == string[c_match]) {
2964 if (c_match == string_len) {
2965 result = MR_MATCHED;
2974 epan_dissect_cleanup(&edt);
2981 } cbs_t; /* "Counted byte string" */
2984 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
2985 search_direction dir)
2990 info.data_len = string_size;
2992 /* String or hex search? */
2994 /* String search - what type of string? */
2995 switch (cf->scs_type) {
2997 case SCS_ASCII_AND_UNICODE:
2998 return find_packet(cf, match_ascii_and_unicode, &info, dir);
3001 return find_packet(cf, match_ascii, &info, dir);
3004 return find_packet(cf, match_unicode, &info, dir);
3007 g_assert_not_reached();
3011 return find_packet(cf, match_binary, &info, dir);
3015 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3017 cbs_t *info = criterion;
3018 const guint8 *ascii_text = info->data;
3019 size_t textlen = info->data_len;
3020 match_result result;
3026 /* Load the frame's data. */
3027 if (!cf_read_frame(cf, fdata)) {
3028 /* Attempt to get the packet failed. */
3032 result = MR_NOTMATCHED;
3033 buf_len = fdata->pkt_len;
3035 while (i < buf_len) {
3038 c_char = toupper(c_char);
3039 if (c_char != '\0') {
3040 if (c_char == ascii_text[c_match]) {
3042 if (c_match == textlen) {
3043 result = MR_MATCHED;
3044 cf->search_pos = i; /* Save the position of the last character
3045 for highlighting the field. */
3050 g_assert(i>=c_match);
3051 i -= (guint32)c_match;
3061 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
3063 cbs_t *info = criterion;
3064 const guint8 *ascii_text = info->data;
3065 size_t textlen = info->data_len;
3066 match_result result;
3072 /* Load the frame's data. */
3073 if (!cf_read_frame(cf, fdata)) {
3074 /* Attempt to get the packet failed. */
3078 result = MR_NOTMATCHED;
3079 buf_len = fdata->pkt_len;
3081 while (i < buf_len) {
3084 c_char = toupper(c_char);
3085 if (c_char == ascii_text[c_match]) {
3087 if (c_match == textlen) {
3088 result = MR_MATCHED;
3089 cf->search_pos = i; /* Save the position of the last character
3090 for highlighting the field. */
3095 g_assert(i>=c_match);
3096 i -= (guint32)c_match;
3106 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3108 cbs_t *info = criterion;
3109 const guint8 *ascii_text = info->data;
3110 size_t textlen = info->data_len;
3111 match_result result;
3117 /* Load the frame's data. */
3118 if (!cf_read_frame(cf, fdata)) {
3119 /* Attempt to get the packet failed. */
3123 result = MR_NOTMATCHED;
3124 buf_len = fdata->pkt_len;
3126 while (i < buf_len) {
3129 c_char = toupper(c_char);
3130 if (c_char == ascii_text[c_match]) {
3132 if (c_match == textlen) {
3133 result = MR_MATCHED;
3134 cf->search_pos = i; /* Save the position of the last character
3135 for highlighting the field. */
3141 g_assert(i>=(c_match*2));
3142 i -= (guint32)c_match*2;
3151 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3153 cbs_t *info = criterion;
3154 const guint8 *binary_data = info->data;
3155 size_t datalen = info->data_len;
3156 match_result result;
3161 /* Load the frame's data. */
3162 if (!cf_read_frame(cf, fdata)) {
3163 /* Attempt to get the packet failed. */
3167 result = MR_NOTMATCHED;
3168 buf_len = fdata->pkt_len;
3170 while (i < buf_len) {
3171 if (cf->pd[i] == binary_data[c_match]) {
3173 if (c_match == datalen) {
3174 result = MR_MATCHED;
3175 cf->search_pos = i; /* Save the position of the last character
3176 for highlighting the field. */
3181 g_assert(i>=c_match);
3182 i -= (guint32)c_match;
3191 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3192 search_direction dir)
3194 return find_packet(cf, match_dfilter, sfcode, dir);
3198 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3199 search_direction dir)
3204 if (!dfilter_compile(filter, &sfcode)) {
3206 * XXX - this shouldn't happen, as the filter string is machine
3211 if (sfcode == NULL) {
3213 * XXX - this shouldn't happen, as the filter string is machine
3218 result = find_packet(cf, match_dfilter, sfcode, dir);
3219 dfilter_free(sfcode);
3224 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3226 dfilter_t *sfcode = criterion;
3228 match_result result;
3230 /* Load the frame's data. */
3231 if (!cf_read_frame(cf, fdata)) {
3232 /* Attempt to get the packet failed. */
3236 epan_dissect_init(&edt, TRUE, FALSE);
3237 epan_dissect_prime_dfilter(&edt, sfcode);
3238 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3239 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3240 epan_dissect_cleanup(&edt);
3245 cf_find_packet_marked(capture_file *cf, search_direction dir)
3247 return find_packet(cf, match_marked, NULL, dir);
3251 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3253 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3257 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3259 return find_packet(cf, match_time_reference, NULL, dir);
3263 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3265 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3269 find_packet(capture_file *cf,
3270 match_result (*match_function)(capture_file *, frame_data *, void *),
3271 void *criterion, search_direction dir)
3273 frame_data *start_fd;
3276 frame_data *new_fd = NULL;
3277 progdlg_t *progbar = NULL;
3282 GTimeVal start_time;
3283 gchar status_str[100];
3284 int progbar_nextstep;
3285 int progbar_quantum;
3287 match_result result;
3289 start_fd = cf->current_frame;
3290 if (start_fd != NULL) {
3291 /* Iterate through the list of packets, starting at the packet we've
3292 picked, calling a routine to run the filter on the packet, see if
3293 it matches, and stop if so. */
3295 framenum = start_fd->num;
3297 /* Update the progress bar when it gets to this value. */
3298 progbar_nextstep = 0;
3299 /* When we reach the value that triggers a progress bar update,
3300 bump that value by this amount. */
3301 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3302 /* Progress so far. */
3306 g_get_current_time(&start_time);
3308 title = cf->sfilter?cf->sfilter:"";
3310 /* Create the progress bar if necessary.
3311 We check on every iteration of the loop, so that it takes no
3312 longer than the standard time to create it (otherwise, for a
3313 large file, we might take considerably longer than that standard
3314 time in order to get to the next progress bar step). */
3315 if (progbar == NULL)
3316 progbar = delayed_create_progress_dlg("Searching", title,
3317 FALSE, &stop_flag, &start_time, progbar_val);
3319 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3320 when we update it, we have to run the GTK+ main loop to get it
3321 to repaint what's pending, and doing so may involve an "ioctl()"
3322 to see if there's any pending input from an X server, and doing
3323 that for every packet can be costly, especially on a big file. */
3324 if (count >= progbar_nextstep) {
3325 /* let's not divide by zero. I should never be started
3326 * with count == 0, so let's assert that
3328 g_assert(cf->count > 0);
3330 progbar_val = (gfloat) count / cf->count;
3332 if (progbar != NULL) {
3333 g_snprintf(status_str, sizeof(status_str),
3334 "%4u of %u packets", count, cf->count);
3335 update_progress_dlg(progbar, progbar_val, status_str);
3338 progbar_nextstep += progbar_quantum;
3342 /* Well, the user decided to abort the search. Go back to the
3343 frame where we started. */
3348 /* Go past the current frame. */
3349 if (dir == SD_BACKWARD) {
3350 /* Go on to the previous frame. */
3351 if (framenum == 1) {
3353 * XXX - other apps have a bit more of a detailed message
3354 * for this, and instead of offering "OK" and "Cancel",
3355 * they offer things such as "Continue" and "Cancel";
3356 * we need an API for popping up alert boxes with
3357 * {Verb} and "Cancel".
3360 if (prefs.gui_find_wrap)
3362 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3363 framenum = cf->count; /* wrap around */
3367 statusbar_push_temporary_msg("Search reached the beginning.");
3368 framenum = start_fd->num; /* stay on previous packet */
3373 /* Go on to the next frame. */
3374 if (framenum == cf->count) {
3375 if (prefs.gui_find_wrap)
3377 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3378 framenum = 1; /* wrap around */
3382 statusbar_push_temporary_msg("Search reached the end.");
3383 framenum = start_fd->num; /* stay on previous packet */
3388 fdata = frame_data_sequence_find(cf->frames, framenum);
3392 /* Is this packet in the display? */
3393 if (fdata->flags.passed_dfilter) {
3394 /* Yes. Does it match the search criterion? */
3395 result = (*match_function)(cf, fdata, criterion);
3396 if (result == MR_ERROR) {
3397 /* Error; our caller has reported the error. Go back to the frame
3398 where we started. */
3401 } else if (result == MR_MATCHED) {
3402 /* Yes. Go to the new frame. */
3408 if (fdata == start_fd) {
3409 /* We're back to the frame we were on originally, and that frame
3410 doesn't match the search filter. The search failed. */
3415 /* We're done scanning the packets; destroy the progress bar if it
3417 if (progbar != NULL)
3418 destroy_progress_dlg(progbar);
3421 if (new_fd != NULL) {
3422 /* Find and select */
3423 cf->search_in_progress = TRUE;
3424 found = new_packet_list_select_row_from_data(new_fd);
3425 cf->search_in_progress = FALSE;
3426 cf->search_pos = 0; /* Reset the position */
3428 /* We didn't find a row corresponding to this frame.
3429 This means that the frame isn't being displayed currently,
3430 so we can't select it. */
3431 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3432 "%sEnd of capture exceeded!%s\n\n"
3433 "The capture file is probably not fully dissected.",
3434 simple_dialog_primary_start(), simple_dialog_primary_end());
3437 return TRUE; /* success */
3439 return FALSE; /* failure */
3443 cf_goto_frame(capture_file *cf, guint fnumber)
3447 fdata = frame_data_sequence_find(cf->frames, fnumber);
3449 if (fdata == NULL) {
3450 /* we didn't find a packet with that packet number */
3451 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3452 return FALSE; /* we failed to go to that packet */
3454 if (!fdata->flags.passed_dfilter) {
3455 /* that packet currently isn't displayed */
3456 /* XXX - add it to the set of displayed packets? */
3457 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3458 return FALSE; /* we failed to go to that packet */
3461 if (!new_packet_list_select_row_from_data(fdata)) {
3462 /* We didn't find a row corresponding to this frame.
3463 This means that the frame isn't being displayed currently,
3464 so we can't select it. */
3465 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3466 "%sEnd of capture exceeded!%s\n\n"
3467 "The capture file is probably not fully dissected.",
3468 simple_dialog_primary_start(), simple_dialog_primary_end());
3471 return TRUE; /* we got to that packet */
3475 cf_goto_top_frame(void)
3477 /* Find and select */
3478 new_packet_list_select_first_row();
3479 return TRUE; /* we got to that packet */
3483 cf_goto_bottom_frame(void)
3485 /* Find and select */
3486 new_packet_list_select_last_row();
3487 return TRUE; /* we got to that packet */
3491 * Go to frame specified by currently selected protocol tree item.
3494 cf_goto_framenum(capture_file *cf)
3496 header_field_info *hfinfo;
3499 if (cf->finfo_selected) {
3500 hfinfo = cf->finfo_selected->hfinfo;
3502 if (hfinfo->type == FT_FRAMENUM) {
3503 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3505 return cf_goto_frame(cf, framenum);
3512 /* Select the packet on a given row. */
3514 cf_select_packet(capture_file *cf, int row)
3518 /* Get the frame data struct pointer for this frame */
3519 fdata = new_packet_list_get_row_data(row);
3521 if (fdata == NULL) {
3522 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3523 the first entry is added to it by "real_insert_row()", that row
3524 is selected (see "real_insert_row()", in "ui/gtk/gtkclist.c", in both
3525 our version and the vanilla GTK+ version).
3527 This means that a "select-row" signal is emitted; this causes
3528 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3531 "cf_select_packet()" fetches, above, the data associated with the
3532 row that was selected; however, as "gtk_clist_append()", which
3533 called "real_insert_row()", hasn't yet returned, we haven't yet
3534 associated any data with that row, so we get back a null pointer.
3536 We can't assume that there's only one frame in the frame list,
3537 either, as we may be filtering the display.
3539 We therefore assume that, if "row" is 0, i.e. the first row
3540 is being selected, and "cf->first_displayed" equals
3541 "cf->last_displayed", i.e. there's only one frame being
3542 displayed, that frame is the frame we want.
3544 This means we have to set "cf->first_displayed" and
3545 "cf->last_displayed" before adding the row to the
3546 GtkCList; see the comment in "add_packet_to_packet_list()". */
3548 if (row == 0 && cf->first_displayed == cf->last_displayed)
3549 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3552 /* If fdata _still_ isn't set simply give up. */
3553 if (fdata == NULL) {
3557 /* Get the data in that frame. */
3558 if (!cf_read_frame (cf, fdata)) {
3562 /* Record that this frame is the current frame. */
3563 cf->current_frame = fdata;
3564 cf->current_row = row;
3566 /* Create the logical protocol tree. */
3567 if (cf->edt != NULL)
3568 epan_dissect_free(cf->edt);
3570 /* We don't need the columns here. */
3571 cf->edt = epan_dissect_new(TRUE, TRUE);
3573 tap_build_interesting(cf->edt);
3574 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3577 dfilter_macro_build_ftv_cache(cf->edt->tree);
3579 cf_callback_invoke(cf_cb_packet_selected, cf);
3582 /* Unselect the selected packet, if any. */
3584 cf_unselect_packet(capture_file *cf)
3586 /* Destroy the epan_dissect_t for the unselected packet. */
3587 if (cf->edt != NULL) {
3588 epan_dissect_free(cf->edt);
3592 /* No packet is selected. */
3593 cf->current_frame = NULL;
3594 cf->current_row = 0;
3596 cf_callback_invoke(cf_cb_packet_unselected, cf);
3598 /* No protocol tree means no selected field. */
3599 cf_unselect_field(cf);
3602 /* Unset the selected protocol tree field, if any. */
3604 cf_unselect_field(capture_file *cf)
3606 cf->finfo_selected = NULL;
3608 cf_callback_invoke(cf_cb_field_unselected, cf);
3612 * Mark a particular frame.
3615 cf_mark_frame(capture_file *cf, frame_data *frame)
3617 if (! frame->flags.marked) {
3618 frame->flags.marked = TRUE;
3619 if (cf->count > cf->marked_count)
3625 * Unmark a particular frame.
3628 cf_unmark_frame(capture_file *cf, frame_data *frame)
3630 if (frame->flags.marked) {
3631 frame->flags.marked = FALSE;
3632 if (cf->marked_count > 0)
3638 * Ignore a particular frame.
3641 cf_ignore_frame(capture_file *cf, frame_data *frame)
3643 if (! frame->flags.ignored) {
3644 frame->flags.ignored = TRUE;
3645 if (cf->count > cf->ignored_count)
3646 cf->ignored_count++;
3651 * Un-ignore a particular frame.
3654 cf_unignore_frame(capture_file *cf, frame_data *frame)
3656 if (frame->flags.ignored) {
3657 frame->flags.ignored = FALSE;
3658 if (cf->ignored_count > 0)
3659 cf->ignored_count--;
3664 * Read the comment in SHB block
3668 cf_read_shb_comment(capture_file *cf)
3670 wtapng_section_t *shb_inf;
3671 const gchar *temp_str;
3673 /* Get info from SHB */
3674 shb_inf = wtap_file_get_shb_info(cf->wth);
3677 temp_str = shb_inf->opt_comment;
3685 cf_update_capture_comment(capture_file *cf, gchar *comment)
3687 wtapng_section_t *shb_inf;
3689 /* Get info from SHB */
3690 shb_inf = wtap_file_get_shb_info(cf->wth);
3692 /* See if the comment has changed or not */
3693 if (shb_inf && shb_inf->opt_comment) {
3694 if (strcmp(shb_inf->opt_comment, comment) == 0) {
3703 /* The comment has changed, let's update it */
3704 wtap_write_shb_comment(cf->wth, comment);
3705 /* Mark the file as having unsaved changes */
3706 cf->unsaved_changes = TRUE;
3713 } save_callback_args_t;
3716 * Save a capture to a file, in a particular format, saving either
3717 * all packets, all currently-displayed packets, or all marked packets.
3719 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3720 * up a message box for the failure.
3723 save_packet(capture_file *cf _U_, frame_data *fdata,
3724 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3727 save_callback_args_t *args = argsp;
3728 struct wtap_pkthdr hdr;
3731 /* init the wtap header for saving */
3732 /* XXX - these are the only flags that correspond to data that we have
3733 in the frame_data structure and that matter on a per-packet basis.
3735 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
3736 and "on the wire" lengths, or it doesn't.
3738 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
3741 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
3742 from the packet flags. */
3743 hdr.presence_flags = 0;
3744 if (fdata->flags.has_ts)
3745 hdr.presence_flags |= WTAP_HAS_TS;
3746 if (fdata->flags.has_ts)
3747 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
3748 hdr.ts.secs = fdata->abs_ts.secs;
3749 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3750 hdr.caplen = fdata->cap_len;
3751 hdr.len = fdata->pkt_len;
3752 hdr.pkt_encap = fdata->lnk_t;
3754 hdr.interface_id = fdata->interface_id; /* identifier of the interface. */
3756 hdr.opt_comment = fdata->opt_comment; /* NULL if not available */
3759 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
3761 /* and save the packet */
3762 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3764 /* Wiretap error. */
3767 case WTAP_ERR_UNSUPPORTED_ENCAP:
3769 * This is a problem with the particular frame we're writing;
3770 * note that, and give the frame number.
3772 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3773 "Frame %u has a network type that can't be saved in a \"%s\" file.",
3774 fdata->num, wtap_file_type_string(args->file_type));
3778 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3779 "An error occurred while writing to the file \"%s\": %s.",
3780 args->fname, wtap_strerror(err));
3785 write_failure_alert_box(args->fname, err);
3793 * Can this capture file be saved in any format except by copying the raw data?
3796 cf_can_save_as(capture_file *cf)
3800 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
3801 /* To save a file with Wiretap, Wiretap has to handle that format,
3802 and its code to handle that format must be able to write a file
3803 with this file's encapsulation type. */
3804 if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
3805 /* OK, we can write it out in this type. */
3810 /* No, we couldn't save it in any format. */
3815 cf_save_packets(capture_file *cf, const char *fname, guint save_format,
3816 gboolean compressed, gboolean dont_reopen)
3818 gchar *fname_new = NULL;
3822 packet_range_t range;
3823 save_callback_args_t callback_args;
3825 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
3827 if (save_format == cf->cd_t && compressed == cf->iscompressed
3828 && !cf->unsaved_changes) {
3829 /* We're saving in the format it's already in, and there are no
3830 changes we have in memory that aren't saved to the file, so
3831 we can just move or copy the raw data. */
3833 if (cf->is_tempfile) {
3834 /* The file being saved is a temporary file from a live
3835 capture, so it doesn't need to stay around under that name;
3836 first, try renaming the capture buffer file to the new name.
3837 This acts as a "safe save", in that, if the file already
3838 exists, the existing file will be removed only if the rename
3841 Sadly, on Windows, as we have the current capture file
3842 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
3843 (to cause the rename to remove an existing target), as
3844 done by ws_stdio_rename() (ws_rename() is #defined to
3845 be ws_stdio_rename() on Windows) will fail.
3847 According to the MSDN documentation for CreateFile(), if,
3848 when we open a capture file, we were to directly do a CreateFile(),
3849 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
3850 convert it to a file descriptor with _open_osfhandle(),
3851 that would allow the file to be renamed out from under us.
3853 It would also allow it to be deleted out from under us; according
3854 to the MSDN documentation on DeleteFile(), "The DeleteFile function
3855 marks a file for deletion on close. Therefore, the file deletion
3856 does not occur until the last handle to the file is closed.
3857 Subsequent calls to CreateFile to open the file fail with
3858 ERROR_ACCESS_DENIED.", so it sounds as if deleting it out from
3859 under us would be safe. */
3861 if (ws_rename(cf->filename, fname) == 0) {
3862 /* That succeeded - there's no need to copy the source file. */
3865 if (errno == EXDEV) {
3866 /* They're on different file systems, so we have to copy the
3870 /* The rename failed, but not because they're on different
3871 file systems - put up an error message. (Or should we
3872 just punt and try to copy? The only reason why I'd
3873 expect the rename to fail and the copy to succeed would
3874 be if we didn't have permission to remove the file from
3875 the temporary directory, and that might be fixable - but
3876 is it worth requiring the user to go off and fix it?) */
3877 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3878 file_rename_error_message(errno), fname);
3886 /* It's a permanent file, so we should copy it, and not remove the
3892 /* Copy the file, if we haven't moved it. If we're overwriting
3893 an existing file, we do it with a "safe save", by writing
3894 to a new file and, if the write succeeds, renaming the
3895 new file on top of the old file. */
3896 if (file_exists(fname)) {
3897 fname_new = g_strdup_printf("%s~", fname);
3898 if (!copy_file_binary_mode(cf->filename, fname_new))
3901 if (!copy_file_binary_mode(cf->filename, fname))
3906 /* Either we're saving in a different format or we're saving changes,
3907 such as added, modified, or removed comments, that haven't yet
3908 been written to the underlying file; we can't do that by copying
3909 or moving the capture file, we have to do it by writing the packets
3912 wtapng_section_t *shb_hdr = NULL;
3913 wtapng_iface_descriptions_t *idb_inf = NULL;
3915 shb_hdr = wtap_file_get_shb_info(cf->wth);
3916 idb_inf = wtap_file_get_idb_info(cf->wth);
3918 if (file_exists(fname)) {
3919 /* We're overwriting an existing file; write out to a new file,
3920 and, if that succeeds, rename the new file on top of the
3921 old file. That makes this a "safe save", so that we don't
3922 lose the old file if we have a problem writing out the new
3923 file. (If the existing file is the current capture file,
3924 we *HAVE* to do that, otherwise we're overwriting the file
3925 from which we're reading the packets that we're writing!) */
3926 fname_new = g_strdup_printf("%s~", fname);
3927 pdh = wtap_dump_open_ng(fname_new, save_format, cf->lnk_t, cf->snap,
3928 compressed, shb_hdr, idb_inf, &err);
3930 pdh = wtap_dump_open_ng(fname, save_format, cf->lnk_t, cf->snap,
3931 compressed, shb_hdr, idb_inf, &err);
3937 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3941 /* Add address resolution */
3942 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
3944 /* Create a packet range that's set to the default "save everything"
3946 packet_range_init(&range);
3948 /* Iterate through the list of packets, processing all the packets. */
3949 callback_args.pdh = pdh;
3950 callback_args.fname = fname;
3951 callback_args.file_type = save_format;
3952 switch (process_specified_packets(cf, &range, "Saving", "selected packets",
3953 TRUE, save_packet, &callback_args)) {
3956 /* Completed successfully. */
3960 /* The user decided to abort the saving.
3961 XXX - remove the output file? */
3965 /* Error while saving. */
3966 wtap_dump_close(pdh, &err);
3970 if (!wtap_dump_close(pdh, &err)) {
3971 cf_close_failure_alert_box(fname, err);
3976 if (fname_new != NULL) {
3977 /* We wrote out to fname_new, and should rename it on top of
3978 fname; fname is now closed, so that should be possible even
3979 on Windows. Do the rename. */
3980 if (ws_rename(fname_new, fname) == -1) {
3981 /* Well, the rename failed. */
3982 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3983 file_rename_error_message(errno), fname);
3988 cf_callback_invoke(cf_cb_file_save_finished, NULL);
3989 cf->unsaved_changes = FALSE;
3992 /* Open and read the file we saved to.
3994 XXX - this is somewhat of a waste; we already have the
3995 packets, all this gets us is updated file type information
3996 (which we could just stuff into "cf"), and having the new
3997 file be the one we have opened and from which we're reading
3998 the data, and it means we have to spend time opening and
3999 reading the file, which could be a significant amount of
4000 time if the file is large.
4002 If the capture-file-writing code were to return the
4003 seek offset of each packet it writes, we could save that
4004 in the frame_data structure for the frame, and just open
4005 the file without reading it again. */
4007 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
4008 /* XXX - report errors if this fails?
4009 What should we return if it fails or is aborted? */
4011 switch (cf_read(cf, TRUE)) {
4015 /* Just because we got an error, that doesn't mean we were unable
4016 to read any of the file; we handle what we could get from the
4020 case CF_READ_ABORTED:
4021 /* The user bailed out of re-reading the capture file; the
4022 capture file has been closed - just return (without
4023 changing any menu settings; "cf_close()" set them
4024 correctly for the "no capture file open" state). */
4032 if (fname_new != NULL) {
4033 /* We were trying to write to a temporary file; get rid of it if it
4034 exists. (We don't care whether this fails, as, if it fails,
4035 there's not much we can do about it. I guess if it failed for
4036 a reason other than "it doesn't exist", we could report an
4037 error, so the user knows there's a junk file that they might
4038 want to clean up.) */
4039 ws_unlink(fname_new);
4042 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4047 cf_export_specified_packets(capture_file *cf, const char *fname,
4048 packet_range_t *range, guint save_format,
4049 gboolean compressed)
4051 gchar *fname_new = NULL;
4054 save_callback_args_t callback_args;
4055 wtapng_section_t *shb_hdr = NULL;
4056 wtapng_iface_descriptions_t *idb_inf = NULL;
4058 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4060 packet_range_process_init(range);
4062 /* We're writing out specified packets from the specified capture
4063 file to another file. Even if all captured packets are to be
4064 written, don't special-case the operation - read each packet
4065 and then write it out if it's one of the specified ones. */
4067 shb_hdr = wtap_file_get_shb_info(cf->wth);
4068 idb_inf = wtap_file_get_idb_info(cf->wth);
4070 if (file_exists(fname)) {
4071 /* We're overwriting an existing file; write out to a new file,
4072 and, if that succeeds, rename the new file on top of the
4073 old file. That makes this a "safe save", so that we don't
4074 lose the old file if we have a problem writing out the new
4075 file. (If the existing file is the current capture file,
4076 we *HAVE* to do that, otherwise we're overwriting the file
4077 from which we're reading the packets that we're writing!) */
4078 fname_new = g_strdup_printf("%s~", fname);
4079 pdh = wtap_dump_open_ng(fname_new, save_format, cf->lnk_t, cf->snap,
4080 compressed, shb_hdr, idb_inf, &err);
4082 pdh = wtap_dump_open_ng(fname, save_format, cf->lnk_t, cf->snap,
4083 compressed, shb_hdr, idb_inf, &err);
4089 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4093 /* Add address resolution */
4094 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4096 /* Iterate through the list of packets, processing the packets we were
4099 XXX - we've already called "packet_range_process_init(range)", but
4100 "process_specified_packets()" will do it again. Fortunately,
4101 that's harmless in this case, as we haven't done anything to
4102 "range" since we initialized it. */
4103 callback_args.pdh = pdh;
4104 callback_args.fname = fname;
4105 callback_args.file_type = save_format;
4106 switch (process_specified_packets(cf, range, "Writing", "specified packets",
4107 TRUE, save_packet, &callback_args)) {
4110 /* Completed successfully. */
4114 /* The user decided to abort the writing.
4115 XXX - remove the output file? */
4119 /* Error while writing. */
4120 wtap_dump_close(pdh, &err);
4124 if (!wtap_dump_close(pdh, &err)) {
4125 cf_close_failure_alert_box(fname, err);
4129 if (fname_new != NULL) {
4130 /* We wrote out to fname_new, and should rename it on top of
4131 fname; fname is now closed, so that should be possible even
4132 on Windows. Do the rename. */
4133 if (ws_rename(fname_new, fname) == -1) {
4134 /* Well, the rename failed. */
4135 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4136 file_rename_error_message(errno), fname);
4141 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4145 if (fname_new != NULL) {
4146 /* We were trying to write to a temporary file; get rid of it if it
4147 exists. (We don't care whether this fails, as, if it fails,
4148 there's not much we can do about it. I guess if it failed for
4149 a reason other than "it doesn't exist", we could report an
4150 error, so the user knows there's a junk file that they might
4151 want to clean up.) */
4152 ws_unlink(fname_new);
4155 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4160 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
4161 gboolean for_writing, int file_type)
4164 /* Wiretap error. */
4167 case WTAP_ERR_NOT_REGULAR_FILE:
4168 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4169 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4173 case WTAP_ERR_RANDOM_OPEN_PIPE:
4174 /* Seen only when opening a capture file for reading. */
4175 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4176 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.\n"
4177 "To capture from a pipe or FIFO use wireshark -i -",
4181 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
4182 /* Seen only when opening a capture file for reading. */
4183 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4184 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
4188 case WTAP_ERR_UNSUPPORTED:
4189 /* Seen only when opening a capture file for reading. */
4190 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4191 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
4193 filename, err_info);
4197 case WTAP_ERR_CANT_WRITE_TO_PIPE:
4198 /* Seen only when opening a capture file for writing. */
4199 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4200 "The file \"%s\" is a pipe, and %s capture files can't be "
4201 "written to a pipe.",
4202 filename, wtap_file_type_string(file_type));
4205 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
4206 /* Seen only when opening a capture file for writing. */
4207 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4208 "Wireshark doesn't support writing capture files in that format.");
4211 case WTAP_ERR_UNSUPPORTED_ENCAP:
4213 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4214 "Wireshark can't save this capture in that format.");
4216 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4217 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
4219 filename, err_info);
4224 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
4226 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4227 "Wireshark can't save this capture in that format.");
4229 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4230 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
4235 case WTAP_ERR_BAD_FILE:
4236 /* Seen only when opening a capture file for reading. */
4237 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4238 "The file \"%s\" appears to be damaged or corrupt.\n"
4240 filename, err_info);
4244 case WTAP_ERR_CANT_OPEN:
4246 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4247 "The file \"%s\" could not be created for some unknown reason.",
4250 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4251 "The file \"%s\" could not be opened for some unknown reason.",
4256 case WTAP_ERR_SHORT_READ:
4257 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4258 "The file \"%s\" appears to have been cut short"
4259 " in the middle of a packet or other data.",
4263 case WTAP_ERR_SHORT_WRITE:
4264 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4265 "A full header couldn't be written to the file \"%s\".",
4269 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4270 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4271 "This file type cannot be written as a compressed file.");
4274 case WTAP_ERR_DECOMPRESS:
4275 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4276 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
4277 "(%s)", filename, err_info);
4282 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4283 "The file \"%s\" could not be %s: %s.",
4285 for_writing ? "created" : "opened",
4286 wtap_strerror(err));
4291 open_failure_alert_box(filename, err, for_writing);
4296 * XXX - whether we mention the source pathname, the target pathname,
4297 * or both depends on the error and on what we find if we look for
4298 * one or both of them.
4301 file_rename_error_message(int err)
4304 static char errmsg_errno[1024+1];
4309 /* XXX - should check whether the source exists and, if not,
4310 report it as the problem and, if so, report the destination
4312 errmsg = "The path to the file \"%s\" doesn't exist.";
4316 /* XXX - if we're doing a rename after a safe save, we should
4317 probably say something else. */
4318 errmsg = "You don't have permission to move the capture file to \"%s\".";
4322 /* XXX - this should probably mention both the source and destination
4324 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4325 "The file \"%%s\" could not be moved: %s.",
4326 wtap_strerror(err));
4327 errmsg = errmsg_errno;
4333 /* Check for write errors - if the file is being written to an NFS server,
4334 a write error may not show up until the file is closed, as NFS clients
4335 might not send writes to the server until the "write()" call finishes,
4336 so that the write may fail on the server but the "write()" may succeed. */
4338 cf_close_failure_alert_box(const char *filename, int err)
4341 /* Wiretap error. */
4344 case WTAP_ERR_CANT_CLOSE:
4345 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4346 "The file \"%s\" couldn't be closed for some unknown reason.",
4350 case WTAP_ERR_SHORT_WRITE:
4351 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4352 "Not all the packets could be written to the file \"%s\".",
4357 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4358 "An error occurred while closing the file \"%s\": %s.",
4359 filename, wtap_strerror(err));
4364 We assume that a close error from the OS is really a write error. */
4365 write_failure_alert_box(filename, err);
4369 /* Reload the current capture file. */
4371 cf_reload(capture_file *cf) {
4373 gboolean is_tempfile;
4376 /* If the file could be opened, "cf_open()" calls "cf_close()"
4377 to get rid of state for the old capture file before filling in state
4378 for the new capture file. "cf_close()" will remove the file if
4379 it's a temporary file; we don't want that to happen (for one thing,
4380 it'd prevent subsequent reopens from working). Remember whether it's
4381 a temporary file, mark it as not being a temporary file, and then
4382 reopen it as the type of file it was.
4384 Also, "cf_close()" will free "cf->filename", so we must make
4385 a copy of it first. */
4386 filename = g_strdup(cf->filename);
4387 is_tempfile = cf->is_tempfile;
4388 cf->is_tempfile = FALSE;
4389 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4390 switch (cf_read(cf, TRUE)) {
4394 /* Just because we got an error, that doesn't mean we were unable
4395 to read any of the file; we handle what we could get from the
4399 case CF_READ_ABORTED:
4400 /* The user bailed out of re-reading the capture file; the
4401 capture file has been closed - just free the capture file name
4402 string and return (without changing the last containing
4408 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4409 Instead, the file was left open, so we should restore "cf->is_tempfile"
4412 XXX - change the menu? Presumably "cf_open()" will do that;
4413 make sure it does! */
4414 cf->is_tempfile = is_tempfile;
4416 /* "cf_open()" made a copy of the file name we handed it, so
4417 we should free up our copy. */
4427 * indent-tabs-mode: nil
4430 * ex: set shiftwidth=2 tabstop=8 expandtab:
4431 * :indentSize=2:tabSize=8:noTabs=true: