6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #include <epan/epan.h>
47 #include <epan/filesystem.h>
50 #include "color_filters.h"
52 #include <epan/column.h>
53 #include <epan/packet.h>
54 #include <epan/column-utils.h>
55 #include "packet-range.h"
61 #include "alert_box.h"
62 #include "simple_dialog.h"
63 #include "main_statusbar.h"
64 #include "progress_dlg.h"
66 #include <epan/prefs.h>
67 #include <epan/dfilter/dfilter.h>
68 #include <epan/epan_dissect.h>
70 #include <epan/dissectors/packet-data.h>
71 #include <epan/dissectors/packet-ber.h>
72 #include <epan/timestamp.h>
73 #include <epan/dfilter/dfilter-macro.h>
74 #include <wsutil/file_util.h>
75 #include <epan/strutil.h>
76 #include <epan/addr_resolv.h>
79 gboolean auto_scroll_live;
82 static guint32 cum_bytes;
83 static nstime_t first_ts;
84 static nstime_t prev_dis_ts;
85 static nstime_t prev_cap_ts;
87 static gulong computed_elapsed;
89 static void cf_reset_state(capture_file *cf);
91 static int read_packet(capture_file *cf, dfilter_t *dfcode,
92 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset);
94 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
95 gboolean refilter, gboolean redissect);
102 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
104 static void match_subtree_text(proto_node *node, gpointer data);
105 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
107 static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
109 static match_result match_ascii(capture_file *cf, frame_data *fdata,
111 static match_result match_unicode(capture_file *cf, frame_data *fdata,
113 static match_result match_binary(capture_file *cf, frame_data *fdata,
115 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
117 static match_result match_marked(capture_file *cf, frame_data *fdata,
119 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
121 static gboolean find_packet(capture_file *cf,
122 match_result (*match_function)(capture_file *, frame_data *, void *),
123 void *criterion, search_direction dir);
125 static void cf_open_failure_alert_box(const char *filename, int err,
126 gchar *err_info, gboolean for_writing,
128 static const char *file_rename_error_message(int err);
129 static void cf_write_failure_alert_box(const char *filename, int err);
130 static void cf_close_failure_alert_box(const char *filename, int err);
131 static void ref_time_packets(capture_file *cf);
132 /* Update the progress bar this many times when reading a file. */
133 #define N_PROGBAR_UPDATES 100
134 /* We read around 200k/100ms don't update the progress bar more often than that */
135 #define MIN_QUANTUM 200000
136 #define MIN_NUMBER_OF_PACKET 1500
138 /* Number of "frame_data" structures per memory chunk.
139 XXX - is this the right number? */
140 #define FRAME_DATA_CHUNK_SIZE 1024
144 * We could probably use g_signal_...() instead of the callbacks below but that
145 * would require linking our CLI programs to libgobject and creating an object
146 * instance for the signals.
149 cf_callback_t cb_fct;
151 } cf_callback_data_t;
153 static GList *cf_callbacks = NULL;
156 cf_callback_invoke(int event, gpointer data)
158 cf_callback_data_t *cb;
159 GList *cb_item = cf_callbacks;
161 /* there should be at least one interested */
162 g_assert(cb_item != NULL);
164 while(cb_item != NULL) {
166 cb->cb_fct(event, data, cb->user_data);
167 cb_item = g_list_next(cb_item);
173 cf_callback_add(cf_callback_t func, gpointer user_data)
175 cf_callback_data_t *cb;
177 cb = g_malloc(sizeof(cf_callback_data_t));
179 cb->user_data = user_data;
181 cf_callbacks = g_list_append(cf_callbacks, cb);
185 cf_callback_remove(cf_callback_t func)
187 cf_callback_data_t *cb;
188 GList *cb_item = cf_callbacks;
190 while(cb_item != NULL) {
192 if(cb->cb_fct == func) {
193 cf_callbacks = g_list_remove(cf_callbacks, cb);
197 cb_item = g_list_next(cb_item);
200 g_assert_not_reached();
204 cf_timestamp_auto_precision(capture_file *cf)
207 int prec = timestamp_get_precision();
210 /* don't try to get the file's precision if none is opened */
211 if(cf->state == FILE_CLOSED) {
215 /* if we are in auto mode, set precision of current file */
216 if(prec == TS_PREC_AUTO ||
217 prec == TS_PREC_AUTO_SEC ||
218 prec == TS_PREC_AUTO_DSEC ||
219 prec == TS_PREC_AUTO_CSEC ||
220 prec == TS_PREC_AUTO_MSEC ||
221 prec == TS_PREC_AUTO_USEC ||
222 prec == TS_PREC_AUTO_NSEC)
224 switch(wtap_file_tsprecision(cf->wth)) {
225 case(WTAP_FILE_TSPREC_SEC):
226 timestamp_set_precision(TS_PREC_AUTO_SEC);
228 case(WTAP_FILE_TSPREC_DSEC):
229 timestamp_set_precision(TS_PREC_AUTO_DSEC);
231 case(WTAP_FILE_TSPREC_CSEC):
232 timestamp_set_precision(TS_PREC_AUTO_CSEC);
234 case(WTAP_FILE_TSPREC_MSEC):
235 timestamp_set_precision(TS_PREC_AUTO_MSEC);
237 case(WTAP_FILE_TSPREC_USEC):
238 timestamp_set_precision(TS_PREC_AUTO_USEC);
240 case(WTAP_FILE_TSPREC_NSEC):
241 timestamp_set_precision(TS_PREC_AUTO_NSEC);
244 g_assert_not_reached();
247 /* Set the column widths of those columns that show the time in
248 "command-line-specified" format. */
249 for (i = 0; i < cf->cinfo.num_cols; i++) {
250 if (col_has_time_fmt(&cf->cinfo, i)) {
251 new_packet_list_resize_column(i);
257 cf_get_computed_elapsed(void)
259 return computed_elapsed;
262 static void reset_elapsed(void)
264 computed_elapsed = 0;
267 static void compute_elapsed(GTimeVal *start_time)
272 g_get_current_time(&time_now);
274 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
275 time_now.tv_usec - start_time->tv_usec;
277 computed_elapsed = (gulong) (delta_time / 1000); /* ms*/
281 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
286 wth = wtap_open_offline(fname, err, &err_info, TRUE);
290 /* The open succeeded. Close whatever capture file we had open,
291 and fill in the information for this file. */
294 /* Cleanup all data structures used for dissection. */
295 cleanup_dissection();
296 /* Initialize all data structures used for dissection. */
299 /* We're about to start reading the file. */
300 cf->state = FILE_READ_IN_PROGRESS;
305 /* Set the file name because we need it to set the follow stream filter.
306 XXX - is that still true? We need it for other reasons, though,
308 cf->filename = g_strdup(fname);
310 /* Indicate whether it's a permanent or temporary file. */
311 cf->is_tempfile = is_tempfile;
313 /* If it's a temporary capture buffer file, mark it as not saved. */
314 cf->user_saved = !is_tempfile;
318 cf->cd_t = wtap_file_type(cf->wth);
320 cf->displayed_count = 0;
321 cf->marked_count = 0;
322 cf->ignored_count = 0;
323 cf->ref_time_count = 0;
324 cf->drops_known = FALSE;
326 cf->snap = wtap_snapshot_length(cf->wth);
328 /* Snapshot length not known. */
329 cf->has_snap = FALSE;
330 cf->snap = WTAP_MAX_PACKET_SIZE;
334 /* Allocate a frame_data_sequence for the frames in this file */
335 cf->frames = new_frame_data_sequence();
337 nstime_set_zero(&cf->elapsed_time);
338 nstime_set_unset(&first_ts);
339 nstime_set_unset(&prev_dis_ts);
340 nstime_set_unset(&prev_cap_ts);
343 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
344 cf_timestamp_auto_precision(cf);
346 new_packet_list_queue_draw();
347 fileset_file_opened(fname);
349 if(cf->cd_t == WTAP_FILE_BER) {
350 /* tell the BER dissector the file name */
351 ber_set_filename(cf->filename);
354 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
355 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
360 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
366 * Reset the state for the currently closed file, but don't do the
367 * UI callbacks; this is for use in "cf_open()", where we don't
368 * want the UI to go from "file open" to "file closed" back to
369 * "file open", we want it to go from "old file open" to "new file
370 * open and being read".
373 cf_reset_state(capture_file *cf)
375 /* Die if we're in the middle of reading a file. */
376 g_assert(cf->state != FILE_READ_IN_PROGRESS);
382 /* We have no file open... */
383 if (cf->filename != NULL) {
384 /* If it's a temporary file, remove it. */
386 ws_unlink(cf->filename);
387 g_free(cf->filename);
390 /* ...which means we have nothing to save. */
391 cf->user_saved = FALSE;
393 dfilter_free(cf->rfcode);
395 if (cf->frames != NULL) {
396 free_frame_data_sequence(cf->frames);
399 cf_unselect_packet(cf); /* nothing to select */
400 cf->first_displayed = 0;
401 cf->last_displayed = 0;
403 /* No frame selected, no field in that frame selected. */
404 cf->current_frame = 0;
406 cf->finfo_selected = NULL;
408 /* Clear the packet list. */
409 new_packet_list_freeze();
410 new_packet_list_clear();
411 new_packet_list_thaw();
414 nstime_set_zero(&cf->elapsed_time);
416 reset_tap_listeners();
418 /* We have no file open. */
419 cf->state = FILE_CLOSED;
421 fileset_file_closed();
424 /* Reset everything to a pristine state */
426 cf_close(capture_file *cf)
428 /* do GUI things even if file is already closed,
429 * e.g. to cleanup things if a capture couldn't be started */
430 cf_callback_invoke(cf_cb_file_closing, cf);
432 /* close things, if not already closed before */
433 if(cf->state != FILE_CLOSED) {
434 color_filters_cleanup();
436 cleanup_dissection();
439 cf_callback_invoke(cf_cb_file_closed, cf);
442 /* an out of memory exception occured, wait for a user button press to exit */
443 static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
449 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
453 progbar_val = (gfloat) file_pos / (gfloat) size;
454 if (progbar_val > 1.0) {
456 /* The file probably grew while we were reading it.
457 * Update file size, and try again.
459 size = wtap_file_size(cf->wth, NULL);
461 /* Another possibility is that we're reading a compressed file and we've
462 * read more (uncompressed) data from the file than exists in the
463 * (compressed) file. So check how much data we've actually read.
465 * This is inside this "if val > 1.0" check to avoid the lseek() when
466 * reading uncompressed files. Testing has (thus far) shown no progress
467 * bar weirdness resulting from switching from the data offset (when
468 * reading the first part of the file) to the real file position.
470 file_pos = wtap_read_so_far(cf->wth, NULL);
473 progbar_val = (gfloat) file_pos / (gfloat) size;
475 /* If it's still > 1, either "wtap_file_size()" failed (in which
476 * case there's not much we can do about it), or the file
477 * *shrank* (in which case there's not much we can do about
478 * it); just clip the progress value at 1.0.
480 if (progbar_val > 1.0f)
484 g_snprintf(status_str, status_size,
485 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
486 file_pos / 1024, size / 1024);
492 cf_read(capture_file *cf, gboolean from_save)
496 const gchar *name_ptr;
498 char errmsg_errno[1024+1];
500 progdlg_t *volatile progbar = NULL;
502 volatile gint64 size;
503 volatile float progbar_val;
505 gchar status_str[100];
506 volatile gint64 progbar_nextstep;
507 volatile gint64 progbar_quantum;
509 gboolean filtering_tap_listeners;
511 volatile int count = 0;
513 volatile int displayed_once = 0;
517 /* Compile the current display filter.
518 * We assume this will not fail since cf->dfilter is only set in
519 * cf_filter IFF the filter was valid.
521 compiled = dfilter_compile(cf->dfilter, &dfcode);
522 g_assert(!cf->dfilter || (compiled && dfcode));
524 /* Do we have any tap listeners with filters? */
525 filtering_tap_listeners = have_filtering_tap_listeners();
527 /* Get the union of the flags for all tap listeners. */
528 tap_flags = union_of_tap_listener_flags();
530 reset_tap_listeners();
532 name_ptr = get_basename(cf->filename);
534 if (from_save == FALSE)
535 cf_callback_invoke(cf_cb_file_read_started, cf);
537 cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr);
539 /* Find the size of the file. */
540 size = wtap_file_size(cf->wth, NULL);
542 /* Update the progress bar when it gets to this value. */
543 progbar_nextstep = 0;
544 /* When we reach the value that triggers a progress bar update,
545 bump that value by this amount. */
547 progbar_quantum = size/N_PROGBAR_UPDATES;
548 if (progbar_quantum < MIN_QUANTUM)
549 progbar_quantum = MIN_QUANTUM;
552 /* Progress so far. */
555 /* The packet list window will be empty untill the file is completly loaded */
556 new_packet_list_freeze();
559 g_get_current_time(&start_time);
561 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
564 /* Create the progress bar if necessary.
565 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
567 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
568 progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str));
569 if (from_save == FALSE)
570 progbar = delayed_create_progress_dlg("Loading", name_ptr,
571 TRUE, &stop_flag, &start_time, progbar_val);
573 progbar = delayed_create_progress_dlg("Saving", name_ptr,
574 TRUE, &stop_flag, &start_time, progbar_val);
577 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
578 when we update it, we have to run the GTK+ main loop to get it
579 to repaint what's pending, and doing so may involve an "ioctl()"
580 to see if there's any pending input from an X server, and doing
581 that for every packet can be costly, especially on a big file. */
582 if (data_offset >= progbar_nextstep) {
583 if (progbar != NULL) {
584 progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str));
585 /* update the packet bar content on the first run or frequently on very large files */
587 if (progbar_quantum > 500000 || displayed_once == 0) {
588 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
590 packets_bar_update();
593 #endif /* HAVE_LIBPCAP */
594 update_progress_dlg(progbar, progbar_val, status_str);
596 progbar_nextstep += progbar_quantum;
601 /* Well, the user decided to abort the read. He/She will be warned and
602 it might be enough for him/her to work with the already loaded
604 This is especially true for very large capture files, where you don't
605 want to wait loading the whole file (which may last minutes or even
606 hours even on fast machines) just to see that it was the wrong file. */
610 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
612 CATCH(OutOfMemoryError) {
615 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
616 "%sOut Of Memory!%s\n"
618 "Sorry, but Wireshark has to terminate now!\n"
620 "Some infos / workarounds can be found at:\n"
621 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
622 simple_dialog_primary_start(), simple_dialog_primary_end());
623 /* we have to terminate, as we cannot recover from the memory error */
624 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
626 main_window_update();
627 /* XXX - how to avoid a busy wait? */
635 /* Cleanup and release all dfilter resources */
637 dfilter_free(dfcode);
640 /* We're done reading the file; destroy the progress bar if it was created. */
642 destroy_progress_dlg(progbar);
644 /* We're done reading sequentially through the file. */
645 cf->state = FILE_READ_DONE;
647 /* Close the sequential I/O side, to free up memory it requires. */
648 wtap_sequential_close(cf->wth);
650 /* Allow the protocol dissectors to free up memory that they
651 * don't need after the sequential run-through of the packets. */
652 postseq_cleanup_all_protocols();
654 /* compute the time it took to load the file */
655 compute_elapsed(&start_time);
657 /* Set the file encapsulation type now; we don't know what it is until
658 we've looked at all the packets, as we don't know until then whether
659 there's more than one type (and thus whether it's
660 WTAP_ENCAP_PER_PACKET). */
661 cf->lnk_t = wtap_file_encap(cf->wth);
663 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
666 new_packet_list_thaw();
667 if (from_save == FALSE)
668 cf_callback_invoke(cf_cb_file_read_finished, cf);
670 cf_callback_invoke(cf_cb_file_save_finished, cf);
672 /* If we have any displayed packets to select, select the first of those
673 packets by making the first row the selected row. */
674 if (cf->first_displayed != 0){
675 new_packet_list_select_first_row();
679 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
680 "%sFile loading was cancelled!%s\n"
682 "The remaining packets in the file were discarded.\n"
684 "As a lot of packets from the original file will be missing,\n"
685 "remember to be careful when saving the current content to a file.\n",
686 simple_dialog_primary_start(), simple_dialog_primary_end());
687 return CF_READ_ERROR;
691 /* Put up a message box noting that the read failed somewhere along
692 the line. Don't throw out the stuff we managed to read, though,
696 case WTAP_ERR_UNSUPPORTED_ENCAP:
697 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
698 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
701 errmsg = errmsg_errno;
704 case WTAP_ERR_CANT_READ:
705 errmsg = "An attempt to read from the capture file failed for"
706 " some unknown reason.";
709 case WTAP_ERR_SHORT_READ:
710 errmsg = "The capture file appears to have been cut short"
711 " in the middle of a packet.";
714 case WTAP_ERR_BAD_RECORD:
715 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
716 "The capture file appears to be damaged or corrupt.\n(%s)",
719 errmsg = errmsg_errno;
722 case WTAP_ERR_DECOMPRESS:
723 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
724 "The compressed capture file appears to be damaged or corrupt.\n"
727 errmsg = errmsg_errno;
731 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
732 "An error occurred while reading the"
733 " capture file: %s.", wtap_strerror(err));
734 errmsg = errmsg_errno;
737 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
738 return CF_READ_ERROR;
745 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
747 cf_status_t cf_status;
749 cf_status = cf_open(cf, fname, is_tempfile, err);
754 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
756 gint64 data_offset = 0;
758 volatile int newly_displayed_packets = 0;
760 gboolean filtering_tap_listeners;
764 /* Compile the current display filter.
765 * We assume this will not fail since cf->dfilter is only set in
766 * cf_filter IFF the filter was valid.
768 compiled = dfilter_compile(cf->dfilter, &dfcode);
769 g_assert(!cf->dfilter || (compiled && dfcode));
771 /* Do we have any tap listeners with filters? */
772 filtering_tap_listeners = have_filtering_tap_listeners();
774 /* Get the union of the flags for all tap listeners. */
775 tap_flags = union_of_tap_listener_flags();
779 new_packet_list_check_end();
780 /* Don't freeze/thaw the list when doing live capture */
781 /*new_packet_list_freeze();*/
783 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
785 while (to_read != 0) {
786 wtap_cleareof(cf->wth);
787 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
790 if (cf->state == FILE_READ_ABORTED) {
791 /* Well, the user decided to exit Wireshark. Break out of the
792 loop, and let the code below (which is called even if there
793 aren't any packets left to read) exit. */
797 if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
798 data_offset) != -1) {
799 newly_displayed_packets++;
802 CATCH(OutOfMemoryError) {
805 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
806 "%sOut Of Memory!%s\n"
808 "Sorry, but Wireshark has to terminate now!\n"
810 "The capture file is not lost, it can be found at:\n"
813 "Some infos / workarounds can be found at:\n"
814 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
815 simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
816 /* we have to terminate, as we cannot recover from the memory error */
817 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
819 main_window_update();
820 /* XXX - how to avoid a busy wait? */
823 /* Don't freeze/thaw the list when doing live capture */
824 /*new_packet_list_thaw();*/
825 return CF_READ_ABORTED;
831 /* Cleanup and release all dfilter resources */
833 dfilter_free(dfcode);
836 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
837 cf->count, cf->state, *err);*/
839 /* Don't freeze/thaw the list when doing live capture */
840 /*new_packet_list_thaw();*/
841 /* With the new packet list the first packet
842 * isn't automatically selected.
844 if(!cf->current_frame)
845 new_packet_list_select_first_row();
847 /* moving to the end of the packet list - if the user requested so and
848 we have some new packets. */
849 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
850 new_packet_list_moveto_end();
852 if (cf->state == FILE_READ_ABORTED) {
853 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
854 so that our caller can kill off the capture child process;
855 this will cause an EOF on the pipe from the child, so
856 "cf_finish_tail()" will be called, and it will clean up
858 return CF_READ_ABORTED;
859 } else if (*err != 0) {
860 /* We got an error reading the capture file.
861 XXX - pop up a dialog box instead? */
862 g_warning("Error \"%s\" while reading: \"%s\"\n",
863 wtap_strerror(*err), cf->filename);
865 return CF_READ_ERROR;
871 cf_fake_continue_tail(capture_file *cf) {
872 cf->state = FILE_READ_DONE;
876 cf_finish_tail(capture_file *cf, int *err)
881 gboolean filtering_tap_listeners;
885 /* Compile the current display filter.
886 * We assume this will not fail since cf->dfilter is only set in
887 * cf_filter IFF the filter was valid.
889 compiled = dfilter_compile(cf->dfilter, &dfcode);
890 g_assert(!cf->dfilter || (compiled && dfcode));
892 /* Do we have any tap listeners with filters? */
893 filtering_tap_listeners = have_filtering_tap_listeners();
895 /* Get the union of the flags for all tap listeners. */
896 tap_flags = union_of_tap_listener_flags();
898 if(cf->wth == NULL) {
900 return CF_READ_ERROR;
903 new_packet_list_check_end();
904 /* Don't freeze/thaw the list when doing live capture */
905 /*new_packet_list_freeze();*/
907 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
908 if (cf->state == FILE_READ_ABORTED) {
909 /* Well, the user decided to abort the read. Break out of the
910 loop, and let the code below (which is called even if there
911 aren't any packets left to read) exit. */
914 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
917 /* Cleanup and release all dfilter resources */
919 dfilter_free(dfcode);
922 /* Don't freeze/thaw the list when doing live capture */
923 /*new_packet_list_thaw();*/
925 if (cf->state == FILE_READ_ABORTED) {
926 /* Well, the user decided to abort the read. We're only called
927 when the child capture process closes the pipe to us (meaning
928 it's probably exited), so we can just close the capture
929 file; we return CF_READ_ABORTED so our caller can do whatever
930 is appropriate when that happens. */
932 return CF_READ_ABORTED;
935 if (auto_scroll_live && cf->count != 0)
936 new_packet_list_moveto_end();
938 /* We're done reading sequentially through the file. */
939 cf->state = FILE_READ_DONE;
941 /* We're done reading sequentially through the file; close the
942 sequential I/O side, to free up memory it requires. */
943 wtap_sequential_close(cf->wth);
945 /* Allow the protocol dissectors to free up memory that they
946 * don't need after the sequential run-through of the packets. */
947 postseq_cleanup_all_protocols();
949 /* Set the file encapsulation type now; we don't know what it is until
950 we've looked at all the packets, as we don't know until then whether
951 there's more than one type (and thus whether it's
952 WTAP_ENCAP_PER_PACKET). */
953 cf->lnk_t = wtap_file_encap(cf->wth);
956 /* We got an error reading the capture file.
957 XXX - pop up a dialog box? */
958 return CF_READ_ERROR;
963 #endif /* HAVE_LIBPCAP */
966 cf_get_display_name(capture_file *cf)
968 const gchar *displayname;
970 /* Return a name to use in displays */
971 if (!cf->is_tempfile) {
972 /* Get the last component of the file name, and use that. */
974 displayname = get_basename(cf->filename);
976 displayname="(No file)";
979 /* The file we read is a temporary file from a live capture;
980 we don't mention its name. */
982 displayname = cf->source;
984 displayname = "(Untitled)";
990 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
996 cf->source = g_strdup(source);
998 cf->source = g_strdup("");
1002 const gchar *cf_get_tempfile_source(capture_file *cf) {
1010 /* XXX - use a macro instead? */
1012 cf_get_packet_count(capture_file *cf)
1017 /* XXX - use a macro instead? */
1019 cf_set_packet_count(capture_file *cf, int packet_count)
1021 cf->count = packet_count;
1024 /* XXX - use a macro instead? */
1026 cf_is_tempfile(capture_file *cf)
1028 return cf->is_tempfile;
1031 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1033 cf->is_tempfile = is_tempfile;
1037 /* XXX - use a macro instead? */
1038 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1040 cf->drops_known = drops_known;
1043 /* XXX - use a macro instead? */
1044 void cf_set_drops(capture_file *cf, guint32 drops)
1049 /* XXX - use a macro instead? */
1050 gboolean cf_get_drops_known(capture_file *cf)
1052 return cf->drops_known;
1055 /* XXX - use a macro instead? */
1056 guint32 cf_get_drops(capture_file *cf)
1061 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1063 cf->rfcode = rfcode;
1067 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1068 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1070 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1072 gboolean add_to_packet_list)
1074 gboolean create_proto_tree = FALSE;
1079 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1081 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1082 &first_ts, &prev_dis_ts, &prev_cap_ts);
1085 + we have a display filter and are re-applying it;
1086 + we have tap listeners with filters;
1087 + we have tap listeners that require a protocol tree;
1089 allocate a protocol tree root node, so that we'll construct
1090 a protocol tree against which a filter expression can be
1092 if ((dfcode != NULL && refilter) ||
1093 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1094 create_proto_tree = TRUE;
1096 /* Dissect the frame. */
1097 epan_dissect_init(&edt, create_proto_tree, FALSE);
1099 if (dfcode != NULL && refilter) {
1100 epan_dissect_prime_dfilter(&edt, dfcode);
1103 tap_queue_init(&edt);
1104 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1105 tap_push_tapped_queue(&edt);
1107 /* If we have a display filter, apply it if we're refiltering, otherwise
1108 leave the "passed_dfilter" flag alone.
1110 If we don't have a display filter, set "passed_dfilter" to 1. */
1111 if (dfcode != NULL) {
1113 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1116 fdata->flags.passed_dfilter = 1;
1118 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1119 cf->displayed_count++;
1121 if (add_to_packet_list) {
1122 /* We fill the needed columns from new_packet_list */
1123 row = new_packet_list_append(cinfo, fdata, &edt.pi);
1126 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1128 frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1130 /* If we haven't yet seen the first frame, this is it.
1132 XXX - we must do this before we add the row to the display,
1133 as, if the display's GtkCList's selection mode is
1134 GTK_SELECTION_BROWSE, when the first entry is added to it,
1135 "cf_select_packet()" will be called, and it will fetch the row
1136 data for the 0th row, and will get a null pointer rather than
1137 "fdata", as "gtk_clist_append()" won't yet have returned and
1138 thus "gtk_clist_set_row_data()" won't yet have been called.
1140 We thus need to leave behind bread crumbs so that
1141 "cf_select_packet()" can find this frame. See the comment
1142 in "cf_select_packet()". */
1143 if (cf->first_displayed == 0)
1144 cf->first_displayed = fdata->num;
1146 /* This is the last frame we've seen so far. */
1147 cf->last_displayed = fdata->num;
1150 epan_dissect_cleanup(&edt);
1154 /* read in a new packet */
1155 /* returns the row of the new packet in the packet list or -1 if not displayed */
1157 read_packet(capture_file *cf, dfilter_t *dfcode,
1158 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1160 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1161 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1162 const guchar *buf = wtap_buf_ptr(cf->wth);
1169 /* The frame number of this packet is one more than the count of
1170 frames in this packet. */
1171 framenum = cf->count + 1;
1173 frame_data_init(&fdlocal, framenum, phdr, offset, cum_bytes);
1178 epan_dissect_init(&edt, TRUE, FALSE);
1179 epan_dissect_prime_dfilter(&edt, cf->rfcode);
1180 epan_dissect_run(&edt, pseudo_header, buf, &fdlocal, NULL);
1181 passed = dfilter_apply_edt(cf->rfcode, &edt);
1182 epan_dissect_cleanup(&edt);
1186 /* This does a shallow copy of fdlocal, which is good enough. */
1187 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1190 cf->f_datalen = offset + fdlocal.cap_len;
1192 if (!cf->redissecting) {
1193 row = add_packet_to_packet_list(fdata, cf, dfcode,
1194 filtering_tap_listeners, tap_flags,
1195 pseudo_header, buf, TRUE, TRUE);
1203 cf_merge_files(char **out_filenamep, int in_file_count,
1204 char *const *in_filenames, int file_type, gboolean do_append)
1206 merge_in_file_t *in_files;
1212 int open_err, read_err, write_err, close_err;
1216 char errmsg_errno[1024+1];
1218 gboolean got_read_error = FALSE, got_write_error = FALSE;
1220 progdlg_t *progbar = NULL;
1222 gint64 f_len, file_pos;
1224 GTimeVal start_time;
1225 gchar status_str[100];
1226 gint64 progbar_nextstep;
1227 gint64 progbar_quantum;
1229 /* open the input files */
1230 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1231 &open_err, &err_info, &err_fileno)) {
1233 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1238 if (*out_filenamep != NULL) {
1239 out_filename = *out_filenamep;
1240 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1244 out_fd = create_tempfile(&tmpname, "wireshark");
1247 out_filename = g_strdup(tmpname);
1248 *out_filenamep = out_filename;
1252 merge_close_in_files(in_file_count, in_files);
1254 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1258 pdh = wtap_dump_fdopen(out_fd, file_type,
1259 merge_select_frame_type(in_file_count, in_files),
1260 merge_max_snapshot_length(in_file_count, in_files),
1261 FALSE /* compressed */, &open_err);
1264 merge_close_in_files(in_file_count, in_files);
1266 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1271 /* Get the sum of the sizes of all the files. */
1273 for (i = 0; i < in_file_count; i++)
1274 f_len += in_files[i].size;
1276 /* Update the progress bar when it gets to this value. */
1277 progbar_nextstep = 0;
1278 /* When we reach the value that triggers a progress bar update,
1279 bump that value by this amount. */
1280 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1281 /* Progress so far. */
1285 g_get_current_time(&start_time);
1287 /* do the merge (or append) */
1290 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1293 wth = merge_read_packet(in_file_count, in_files, &read_err,
1297 got_read_error = TRUE;
1301 /* Get the sum of the data offsets in all of the files. */
1303 for (i = 0; i < in_file_count; i++)
1304 data_offset += in_files[i].data_offset;
1306 /* Create the progress bar if necessary.
1307 We check on every iteration of the loop, so that it takes no
1308 longer than the standard time to create it (otherwise, for a
1309 large file, we might take considerably longer than that standard
1310 time in order to get to the next progress bar step). */
1311 if (progbar == NULL) {
1312 progbar = delayed_create_progress_dlg("Merging", "files",
1313 FALSE, &stop_flag, &start_time, progbar_val);
1316 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1317 when we update it, we have to run the GTK+ main loop to get it
1318 to repaint what's pending, and doing so may involve an "ioctl()"
1319 to see if there's any pending input from an X server, and doing
1320 that for every packet can be costly, especially on a big file. */
1321 if (data_offset >= progbar_nextstep) {
1322 /* Get the sum of the seek positions in all of the files. */
1324 for (i = 0; i < in_file_count; i++)
1325 file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1326 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1327 if (progbar_val > 1.0f) {
1328 /* Some file probably grew while we were reading it.
1329 That "shouldn't happen", so we'll just clip the progress
1333 if (progbar != NULL) {
1334 g_snprintf(status_str, sizeof(status_str),
1335 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1336 file_pos / 1024, f_len / 1024);
1337 update_progress_dlg(progbar, progbar_val, status_str);
1339 progbar_nextstep += progbar_quantum;
1343 /* Well, the user decided to abort the merge. */
1347 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1348 wtap_buf_ptr(wth), &write_err)) {
1349 got_write_error = TRUE;
1354 /* We're done merging the files; destroy the progress bar if it was created. */
1355 if (progbar != NULL)
1356 destroy_progress_dlg(progbar);
1358 merge_close_in_files(in_file_count, in_files);
1359 if (!got_read_error && !got_write_error) {
1360 if (!wtap_dump_close(pdh, &write_err))
1361 got_write_error = TRUE;
1363 wtap_dump_close(pdh, &close_err);
1365 if (got_read_error) {
1367 * Find the file on which we got the error, and report the error.
1369 for (i = 0; i < in_file_count; i++) {
1370 if (in_files[i].state == GOT_ERROR) {
1371 /* Put up a message box noting that a read failed somewhere along
1375 case WTAP_ERR_UNSUPPORTED_ENCAP:
1376 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1377 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1380 errmsg = errmsg_errno;
1383 case WTAP_ERR_CANT_READ:
1384 errmsg = "An attempt to read from the capture file %s failed for"
1385 " some unknown reason.";
1388 case WTAP_ERR_SHORT_READ:
1389 errmsg = "The capture file %s appears to have been cut short"
1390 " in the middle of a packet.";
1393 case WTAP_ERR_BAD_RECORD:
1394 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1395 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1398 errmsg = errmsg_errno;
1401 case WTAP_ERR_DECOMPRESS:
1402 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1403 "The compressed capture file %%s appears to be damaged or corrupt.\n"
1406 errmsg = errmsg_errno;
1410 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1411 "An error occurred while reading the"
1412 " capture file %%s: %s.", wtap_strerror(read_err));
1413 errmsg = errmsg_errno;
1416 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
1421 if (got_write_error) {
1422 /* Put up an alert box for the write error. */
1423 cf_write_failure_alert_box(out_filename, write_err);
1426 if (got_read_error || got_write_error || stop_flag) {
1427 /* Callers aren't expected to treat an error or an explicit abort
1428 differently - we put up error dialogs ourselves, so they don't
1436 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1438 const char *filter_new = dftext ? dftext : "";
1439 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1441 GTimeVal start_time;
1443 /* if new filter equals old one, do nothing unless told to do so */
1444 if (!force && strcmp(filter_new, filter_old) == 0) {
1450 if (dftext == NULL) {
1451 /* The new filter is an empty filter (i.e., display all packets).
1452 * so leave dfcode==NULL
1456 * We have a filter; make a copy of it (as we'll be saving it),
1457 * and try to compile it.
1459 dftext = g_strdup(dftext);
1460 if (!dfilter_compile(dftext, &dfcode)) {
1461 /* The attempt failed; report an error. */
1462 gchar *safe_dftext = simple_dialog_format_message(dftext);
1463 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1465 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1468 "The following display filter isn't a valid display filter:\n%s\n"
1469 "See the help for a description of the display filter syntax.",
1470 simple_dialog_primary_start(), safe_dfilter_error_msg,
1471 simple_dialog_primary_end(), safe_dftext);
1472 g_free(safe_dfilter_error_msg);
1473 g_free(safe_dftext);
1479 if (dfcode == NULL) {
1480 /* Yes - free the filter text, and set it to null. */
1486 /* We have a valid filter. Replace the current filter. */
1487 g_free(cf->dfilter);
1488 cf->dfilter = dftext;
1489 g_get_current_time(&start_time);
1492 /* Now rescan the packet list, applying the new filter, but not
1493 throwing away information constructed on a previous pass. */
1494 if (dftext == NULL) {
1495 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1497 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1500 /* Cleanup and release all dfilter resources */
1501 dfilter_free(dfcode);
1507 cf_reftime_packets(capture_file *cf)
1510 ref_time_packets(cf);
1514 cf_redissect_packets(capture_file *cf)
1516 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1520 cf_read_frame_r(capture_file *cf, frame_data *fdata,
1521 union wtap_pseudo_header *pseudo_header, guint8 *pd)
1525 char errmsg_errno[1024+1];
1527 if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
1528 fdata->cap_len, &err, &err_info)) {
1531 case WTAP_ERR_UNSUPPORTED_ENCAP:
1532 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1533 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1538 case WTAP_ERR_BAD_RECORD:
1539 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1540 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
1541 wtap_strerror(err), err_info);
1546 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1547 "An error occurred while reading from the file \"%%s\": %s.",
1548 wtap_strerror(err));
1551 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg_errno, cf->filename);
1558 cf_read_frame(capture_file *cf, frame_data *fdata)
1560 return cf_read_frame_r(cf, fdata, &cf->pseudo_header, cf->pd);
1563 /* Rescan the list of packets, reconstructing the CList.
1565 "action" describes why we're doing this; it's used in the progress
1568 "action_item" describes what we're doing; it's used in the progress
1571 "refilter" is TRUE if we need to re-evaluate the filter expression.
1573 "redissect" is TRUE if we need to make the dissectors reconstruct
1574 any state information they have (because a preference that affects
1575 some dissector has changed, meaning some dissector might construct
1576 its state differently from the way it was constructed the last time). */
1578 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1579 gboolean refilter, gboolean redissect)
1581 /* Rescan packets new packet list */
1584 progdlg_t *progbar = NULL;
1587 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1588 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1589 gboolean selected_frame_seen;
1591 GTimeVal start_time;
1592 gchar status_str[100];
1593 int progbar_nextstep;
1594 int progbar_quantum;
1596 gboolean filtering_tap_listeners;
1598 gboolean add_to_packet_list = FALSE;
1601 /* Compile the current display filter.
1602 * We assume this will not fail since cf->dfilter is only set in
1603 * cf_filter IFF the filter was valid.
1605 compiled = dfilter_compile(cf->dfilter, &dfcode);
1606 g_assert(!cf->dfilter || (compiled && dfcode));
1608 /* Do we have any tap listeners with filters? */
1609 filtering_tap_listeners = have_filtering_tap_listeners();
1611 /* Get the union of the flags for all tap listeners. */
1612 tap_flags = union_of_tap_listener_flags();
1614 reset_tap_listeners();
1615 /* Which frame, if any, is the currently selected frame?
1616 XXX - should the selected frame or the focus frame be the "current"
1617 frame, that frame being the one from which "Find Frame" searches
1619 selected_frame = cf->current_frame;
1621 /* Mark frame num as not found */
1622 selected_frame_num = -1;
1624 /* Freeze the packet list while we redo it, so we don't get any
1625 screen updates while it happens. */
1626 new_packet_list_freeze();
1629 /* We need to re-initialize all the state information that protocols
1630 keep, because some preference that controls a dissector has changed,
1631 which might cause the state information to be constructed differently
1632 by that dissector. */
1634 /* We might receive new packets while redissecting, and we don't
1635 want to dissect those before their time. */
1636 cf->redissecting = TRUE;
1638 /* Cleanup all data structures used for dissection. */
1639 cleanup_dissection();
1640 /* Initialize all data structures used for dissection. */
1643 /* We need to redissect the packets so we have to discard our old
1644 * packet list store. */
1645 new_packet_list_clear();
1646 add_to_packet_list = TRUE;
1649 /* We don't yet know which will be the first and last frames displayed. */
1650 cf->first_displayed = 0;
1651 cf->last_displayed = 0;
1653 /* We currently don't display any packets */
1654 cf->displayed_count = 0;
1656 /* Iterate through the list of frames. Call a routine for each frame
1657 to check whether it should be displayed and, if so, add it to
1658 the display list. */
1659 nstime_set_unset(&first_ts);
1660 nstime_set_unset(&prev_dis_ts);
1661 nstime_set_unset(&prev_cap_ts);
1664 /* Update the progress bar when it gets to this value. */
1665 progbar_nextstep = 0;
1666 /* When we reach the value that triggers a progress bar update,
1667 bump that value by this amount. */
1668 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1669 /* Count of packets at which we've looked. */
1671 /* Progress so far. */
1675 g_get_current_time(&start_time);
1677 /* no previous row yet */
1678 prev_frame_num = -1;
1681 preceding_frame_num = -1;
1682 preceding_frame = NULL;
1683 following_frame_num = -1;
1684 following_frame = NULL;
1686 selected_frame_seen = FALSE;
1688 for (framenum = 1; framenum <= cf->count; framenum++) {
1689 fdata = frame_data_sequence_find(cf->frames, framenum);
1691 /* Create the progress bar if necessary.
1692 We check on every iteration of the loop, so that it takes no
1693 longer than the standard time to create it (otherwise, for a
1694 large file, we might take considerably longer than that standard
1695 time in order to get to the next progress bar step). */
1696 if (progbar == NULL)
1697 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1698 &stop_flag, &start_time,
1701 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1702 when we update it, we have to run the GTK+ main loop to get it
1703 to repaint what's pending, and doing so may involve an "ioctl()"
1704 to see if there's any pending input from an X server, and doing
1705 that for every packet can be costly, especially on a big file. */
1706 if (count >= progbar_nextstep) {
1707 /* let's not divide by zero. I should never be started
1708 * with count == 0, so let's assert that
1710 g_assert(cf->count > 0);
1711 progbar_val = (gfloat) count / cf->count;
1713 if (progbar != NULL) {
1714 g_snprintf(status_str, sizeof(status_str),
1715 "%4u of %u frames", count, cf->count);
1716 update_progress_dlg(progbar, progbar_val, status_str);
1719 progbar_nextstep += progbar_quantum;
1723 /* Well, the user decided to abort the filtering. Just stop.
1725 XXX - go back to the previous filter? Users probably just
1726 want not to wait for a filtering operation to finish;
1727 unless we cancel by having no filter, reverting to the
1728 previous filter will probably be even more expensive than
1729 continuing the filtering, as it involves going back to the
1730 beginning and filtering, and even with no filter we currently
1731 have to re-generate the entire clist, which is also expensive.
1733 I'm not sure what Network Monitor does, but it doesn't appear
1734 to give you an unfiltered display if you cancel. */
1741 /* Since all state for the frame was destroyed, mark the frame
1742 * as not visited, free the GSList referring to the state
1743 * data (the per-frame data itself was freed by
1744 * "init_dissection()"), and null out the GSList pointer. */
1745 fdata->flags.visited = 0;
1746 frame_data_cleanup(fdata);
1749 if (!cf_read_frame(cf, fdata))
1750 break; /* error reading the frame */
1752 /* If the previous frame is displayed, and we haven't yet seen the
1753 selected frame, remember that frame - it's the closest one we've
1754 yet seen before the selected frame. */
1755 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1756 preceding_frame_num = prev_frame_num;
1757 preceding_frame = prev_frame;
1759 add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1760 tap_flags, &cf->pseudo_header, cf->pd,
1762 add_to_packet_list);
1764 /* If this frame is displayed, and this is the first frame we've
1765 seen displayed after the selected frame, remember this frame -
1766 it's the closest one we've yet seen at or after the selected
1768 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1769 following_frame_num = fdata->num;
1770 following_frame = fdata;
1772 if (fdata == selected_frame) {
1773 selected_frame_seen = TRUE;
1774 if (fdata->flags.passed_dfilter)
1775 selected_frame_num = fdata->num;
1778 /* Remember this frame - it'll be the previous frame
1779 on the next pass through the loop. */
1780 prev_frame_num = fdata->num;
1784 /* We are done redissecting the packet list. */
1785 cf->redissecting = FALSE;
1788 /* Clear out what remains of the visited flags and per-frame data
1791 XXX - that may cause various forms of bogosity when dissecting
1792 these frames, as they won't have been seen by this sequential
1793 pass, but the only alternative I see is to keep scanning them
1794 even though the user requested that the scan stop, and that
1795 would leave the user stuck with an Wireshark grinding on
1796 until it finishes. Should we just stick them with that? */
1797 for (; framenum <= cf->count; framenum++) {
1798 fdata = frame_data_sequence_find(cf->frames, framenum);
1799 fdata->flags.visited = 0;
1800 frame_data_cleanup(fdata);
1804 /* We're done filtering the packets; destroy the progress bar if it
1806 if (progbar != NULL)
1807 destroy_progress_dlg(progbar);
1809 /* Unfreeze the packet list. */
1810 if (!add_to_packet_list)
1811 new_packet_list_recreate_visible_rows();
1813 /* Compute the time it took to filter the file */
1814 compute_elapsed(&start_time);
1816 new_packet_list_thaw();
1818 if (selected_frame_num == -1) {
1819 /* The selected frame didn't pass the filter. */
1820 if (selected_frame == NULL) {
1821 /* That's because there *was* no selected frame. Make the first
1822 displayed frame the current frame. */
1823 selected_frame_num = 0;
1825 /* Find the nearest displayed frame to the selected frame (whether
1826 it's before or after that frame) and make that the current frame.
1827 If the next and previous displayed frames are equidistant from the
1828 selected frame, choose the next one. */
1829 g_assert(following_frame == NULL ||
1830 following_frame->num >= selected_frame->num);
1831 g_assert(preceding_frame == NULL ||
1832 preceding_frame->num <= selected_frame->num);
1833 if (following_frame == NULL) {
1834 /* No frame after the selected frame passed the filter, so we
1835 have to select the last displayed frame before the selected
1837 selected_frame_num = preceding_frame_num;
1838 selected_frame = preceding_frame;
1839 } else if (preceding_frame == NULL) {
1840 /* No frame before the selected frame passed the filter, so we
1841 have to select the first displayed frame after the selected
1843 selected_frame_num = following_frame_num;
1844 selected_frame = following_frame;
1846 /* Frames before and after the selected frame passed the filter, so
1847 we'll select the previous frame */
1848 selected_frame_num = preceding_frame_num;
1849 selected_frame = preceding_frame;
1854 if (selected_frame_num == -1) {
1855 /* There are no frames displayed at all. */
1856 cf_unselect_packet(cf);
1858 /* Either the frame that was selected passed the filter, or we've
1859 found the nearest displayed frame to that frame. Select it, make
1860 it the focus row, and make it visible. */
1861 /* Set to invalid to force update of packet list and packet details */
1862 cf->current_row = -1;
1863 if (selected_frame_num == 0) {
1864 new_packet_list_select_first_row();
1866 if (!new_packet_list_select_row_from_data(selected_frame)) {
1867 /* We didn't find a row corresponding to this frame.
1868 This means that the frame isn't being displayed currently,
1869 so we can't select it. */
1870 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
1871 "%sEnd of capture exceeded!%s\n\n"
1872 "The capture file is probably not fully dissected.",
1873 simple_dialog_primary_start(), simple_dialog_primary_end());
1878 /* Cleanup and release all dfilter resources */
1879 dfilter_free(dfcode);
1884 * Scan trough all frame data and recalculate the ref time
1885 * without rereading the file.
1886 * XXX - do we need a progres bar or is this fast enough?
1889 ref_time_packets(capture_file *cf)
1894 nstime_set_unset(&first_ts);
1895 nstime_set_unset(&prev_dis_ts);
1898 for (framenum = 1; framenum <= cf->count; framenum++) {
1899 fdata = frame_data_sequence_find(cf->frames, framenum);
1901 /* just add some value here until we know if it is being displayed or not */
1902 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1908 /* If we don't have the time stamp of the first packet in the
1909 capture, it's because this is the first packet. Save the time
1910 stamp of this packet as the time stamp of the first packet. */
1911 if (nstime_is_unset(&first_ts)) {
1912 first_ts = fdata->abs_ts;
1914 /* if this frames is marked as a reference time frame, reset
1915 firstsec and firstusec to this frame */
1916 if(fdata->flags.ref_time){
1917 first_ts = fdata->abs_ts;
1920 /* If we don't have the time stamp of the previous displayed packet,
1921 it's because this is the first displayed packet. Save the time
1922 stamp of this packet as the time stamp of the previous displayed
1924 if (nstime_is_unset(&prev_dis_ts)) {
1925 prev_dis_ts = fdata->abs_ts;
1928 /* Get the time elapsed between the first packet and this packet. */
1929 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
1931 /* If it's greater than the current elapsed time, set the elapsed time
1932 to it (we check for "greater than" so as not to be confused by
1933 time moving backwards). */
1934 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
1935 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
1936 cf->elapsed_time = fdata->rel_ts;
1939 /* Get the time elapsed between the previous displayed packet and
1941 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
1943 prev_dis_ts = fdata->abs_ts;
1948 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
1949 /* This frame either passed the display filter list or is marked as
1950 a time reference frame. All time reference frames are displayed
1951 even if they dont pass the display filter */
1952 if(fdata->flags.ref_time){
1953 /* if this was a TIME REF frame we should reset the cum_bytes field */
1954 cum_bytes = fdata->pkt_len;
1955 fdata->cum_bytes = cum_bytes;
1957 /* increase cum_bytes with this packets length */
1958 cum_bytes += fdata->pkt_len;
1971 process_specified_packets(capture_file *cf, packet_range_t *range,
1972 const char *string1, const char *string2, gboolean terminate_is_stop,
1973 gboolean (*callback)(capture_file *, frame_data *,
1974 union wtap_pseudo_header *, const guint8 *, void *),
1975 void *callback_args)
1979 union wtap_pseudo_header pseudo_header;
1980 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1981 psp_return_t ret = PSP_FINISHED;
1983 progdlg_t *progbar = NULL;
1986 gboolean progbar_stop_flag;
1987 GTimeVal progbar_start_time;
1988 gchar progbar_status_str[100];
1989 int progbar_nextstep;
1990 int progbar_quantum;
1991 range_process_e process_this;
1993 /* Update the progress bar when it gets to this value. */
1994 progbar_nextstep = 0;
1995 /* When we reach the value that triggers a progress bar update,
1996 bump that value by this amount. */
1997 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1998 /* Count of packets at which we've looked. */
2000 /* Progress so far. */
2003 progbar_stop_flag = FALSE;
2004 g_get_current_time(&progbar_start_time);
2006 packet_range_process_init(range);
2008 /* Iterate through all the packets, printing the packets that
2009 were selected by the current display filter. */
2010 for (framenum = 1; framenum <= cf->count; framenum++) {
2011 fdata = frame_data_sequence_find(cf->frames, framenum);
2013 /* Create the progress bar if necessary.
2014 We check on every iteration of the loop, so that it takes no
2015 longer than the standard time to create it (otherwise, for a
2016 large file, we might take considerably longer than that standard
2017 time in order to get to the next progress bar step). */
2018 if (progbar == NULL)
2019 progbar = delayed_create_progress_dlg(string1, string2,
2022 &progbar_start_time,
2025 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2026 when we update it, we have to run the GTK+ main loop to get it
2027 to repaint what's pending, and doing so may involve an "ioctl()"
2028 to see if there's any pending input from an X server, and doing
2029 that for every packet can be costly, especially on a big file. */
2030 if (progbar_count >= progbar_nextstep) {
2031 /* let's not divide by zero. I should never be started
2032 * with count == 0, so let's assert that
2034 g_assert(cf->count > 0);
2035 progbar_val = (gfloat) progbar_count / cf->count;
2037 if (progbar != NULL) {
2038 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2039 "%4u of %u packets", progbar_count, cf->count);
2040 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2043 progbar_nextstep += progbar_quantum;
2046 if (progbar_stop_flag) {
2047 /* Well, the user decided to abort the operation. Just stop,
2048 and arrange to return PSP_STOPPED to our caller, so they know
2049 it was stopped explicitly. */
2056 /* do we have to process this packet? */
2057 process_this = packet_range_process_packet(range, fdata);
2058 if (process_this == range_process_next) {
2059 /* this packet uninteresting, continue with next one */
2061 } else if (process_this == range_processing_finished) {
2062 /* all interesting packets processed, stop the loop */
2066 /* Get the packet */
2067 if (!cf_read_frame_r(cf, fdata, &pseudo_header, pd)) {
2068 /* Attempt to get the packet failed. */
2072 /* Process the packet */
2073 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
2074 /* Callback failed. We assume it reported the error appropriately. */
2080 /* We're done printing the packets; destroy the progress bar if
2082 if (progbar != NULL)
2083 destroy_progress_dlg(progbar);
2089 gboolean construct_protocol_tree;
2091 } retap_callback_args_t;
2094 retap_packet(capture_file *cf _U_, frame_data *fdata,
2095 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2098 retap_callback_args_t *args = argsp;
2101 epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
2102 tap_queue_init(&edt);
2103 epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
2104 tap_push_tapped_queue(&edt);
2105 epan_dissect_cleanup(&edt);
2111 cf_retap_packets(capture_file *cf)
2113 packet_range_t range;
2114 retap_callback_args_t callback_args;
2115 gboolean filtering_tap_listeners;
2118 /* Do we have any tap listeners with filters? */
2119 filtering_tap_listeners = have_filtering_tap_listeners();
2121 tap_flags = union_of_tap_listener_flags();
2123 /* If any tap listeners have filters, or require the protocol tree,
2124 construct the protocol tree. */
2125 callback_args.construct_protocol_tree = filtering_tap_listeners ||
2126 (tap_flags & TL_REQUIRES_PROTO_TREE);
2128 /* If any tap listeners require the columns, construct them. */
2129 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2131 /* Reset the tap listeners. */
2132 reset_tap_listeners();
2134 /* Iterate through the list of packets, dissecting all packets and
2135 re-running the taps. */
2136 packet_range_init(&range);
2137 packet_range_process_init(&range);
2138 switch (process_specified_packets(cf, &range, "Recalculating statistics on",
2139 "all packets", TRUE, retap_packet,
2142 /* Completed successfully. */
2146 /* Well, the user decided to abort the refiltering.
2147 Return CF_READ_ABORTED so our caller knows they did that. */
2148 return CF_READ_ABORTED;
2151 /* Error while retapping. */
2152 return CF_READ_ERROR;
2155 g_assert_not_reached();
2160 print_args_t *print_args;
2161 gboolean print_header_line;
2162 char *header_line_buf;
2163 int header_line_buf_len;
2164 gboolean print_formfeed;
2165 gboolean print_separator;
2169 } print_callback_args_t;
2172 print_packet(capture_file *cf, frame_data *fdata,
2173 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2176 print_callback_args_t *args = argsp;
2183 gboolean proto_tree_needed;
2184 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2185 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2187 /* Create the protocol tree, and make it visible, if we're printing
2188 the dissection or the hex data.
2189 XXX - do we need it if we're just printing the hex data? */
2191 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2192 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2194 /* Fill in the column information if we're printing the summary
2196 if (args->print_args->print_summary) {
2197 col_custom_prime_edt(&edt, &cf->cinfo);
2198 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2199 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2201 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2203 if (args->print_formfeed) {
2204 if (!new_page(args->print_args->stream))
2207 if (args->print_separator) {
2208 if (!print_line(args->print_args->stream, 0, ""))
2214 * We generate bookmarks, if the output format supports them.
2215 * The name is "__frameN__".
2217 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2219 if (args->print_args->print_summary) {
2220 if (args->print_header_line) {
2221 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2223 args->print_header_line = FALSE; /* we might not need to print any more */
2225 cp = &args->line_buf[0];
2227 for (i = 0; i < cf->cinfo.num_cols; i++) {
2228 /* Find the length of the string for this column. */
2229 column_len = (int) strlen(cf->cinfo.col_data[i]);
2230 if (args->col_widths[i] > column_len)
2231 column_len = args->col_widths[i];
2233 /* Make sure there's room in the line buffer for the column; if not,
2234 double its length. */
2235 line_len += column_len + 1; /* "+1" for space */
2236 if (line_len > args->line_buf_len) {
2237 cp_off = (int) (cp - args->line_buf);
2238 args->line_buf_len = 2 * line_len;
2239 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2240 cp = args->line_buf + cp_off;
2243 /* Right-justify the packet number column. */
2244 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2245 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
2247 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
2249 if (i != cf->cinfo.num_cols - 1)
2255 * Generate a bookmark, using the summary line as the title.
2257 if (!print_bookmark(args->print_args->stream, bookmark_name,
2261 if (!print_line(args->print_args->stream, 0, args->line_buf))
2265 * Generate a bookmark, using "Frame N" as the title, as we're not
2266 * printing the summary line.
2268 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2269 if (!print_bookmark(args->print_args->stream, bookmark_name,
2272 } /* if (print_summary) */
2274 if (args->print_args->print_dissections != print_dissections_none) {
2275 if (args->print_args->print_summary) {
2276 /* Separate the summary line from the tree with a blank line. */
2277 if (!print_line(args->print_args->stream, 0, ""))
2281 /* Print the information in that tree. */
2282 if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
2285 /* Print a blank line if we print anything after this (aka more than one packet). */
2286 args->print_separator = TRUE;
2288 /* Print a header line if we print any more packet summaries */
2289 args->print_header_line = TRUE;
2292 if (args->print_args->print_hex) {
2293 /* Print the full packet data as hex. */
2294 if (!print_hex_data(args->print_args->stream, &edt))
2297 /* Print a blank line if we print anything after this (aka more than one packet). */
2298 args->print_separator = TRUE;
2300 /* Print a header line if we print any more packet summaries */
2301 args->print_header_line = TRUE;
2302 } /* if (args->print_args->print_dissections != print_dissections_none) */
2304 epan_dissect_cleanup(&edt);
2306 /* do we want to have a formfeed between each packet from now on? */
2307 if(args->print_args->print_formfeed) {
2308 args->print_formfeed = TRUE;
2314 epan_dissect_cleanup(&edt);
2319 cf_print_packets(capture_file *cf, print_args_t *print_args)
2322 print_callback_args_t callback_args;
2330 callback_args.print_args = print_args;
2331 callback_args.print_header_line = TRUE;
2332 callback_args.header_line_buf = NULL;
2333 callback_args.header_line_buf_len = 256;
2334 callback_args.print_formfeed = FALSE;
2335 callback_args.print_separator = FALSE;
2336 callback_args.line_buf = NULL;
2337 callback_args.line_buf_len = 256;
2338 callback_args.col_widths = NULL;
2340 if (!print_preamble(print_args->stream, cf->filename)) {
2341 destroy_print_stream(print_args->stream);
2342 return CF_PRINT_WRITE_ERROR;
2345 if (print_args->print_summary) {
2346 /* We're printing packet summaries. Allocate the header line buffer
2347 and get the column widths. */
2348 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2350 /* Find the widths for each of the columns - maximum of the
2351 width of the title and the width of the data - and construct
2352 a buffer with a line containing the column titles. */
2353 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2354 cp = &callback_args.header_line_buf[0];
2356 for (i = 0; i < cf->cinfo.num_cols; i++) {
2357 /* Don't pad the last column. */
2358 if (i == cf->cinfo.num_cols - 1)
2359 callback_args.col_widths[i] = 0;
2361 callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
2362 data_width = get_column_char_width(get_column_format(i));
2363 if (data_width > callback_args.col_widths[i])
2364 callback_args.col_widths[i] = data_width;
2367 /* Find the length of the string for this column. */
2368 column_len = (int) strlen(cf->cinfo.col_title[i]);
2369 if (callback_args.col_widths[i] > column_len)
2370 column_len = callback_args.col_widths[i];
2372 /* Make sure there's room in the line buffer for the column; if not,
2373 double its length. */
2374 line_len += column_len + 1; /* "+1" for space */
2375 if (line_len > callback_args.header_line_buf_len) {
2376 cp_off = (int) (cp - callback_args.header_line_buf);
2377 callback_args.header_line_buf_len = 2 * line_len;
2378 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2379 callback_args.header_line_buf_len + 1);
2380 cp = callback_args.header_line_buf + cp_off;
2383 /* Right-justify the packet number column. */
2384 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2385 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2387 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2389 if (i != cf->cinfo.num_cols - 1)
2394 /* Now start out the main line buffer with the same length as the
2395 header line buffer. */
2396 callback_args.line_buf_len = callback_args.header_line_buf_len;
2397 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2398 } /* if (print_summary) */
2400 /* Iterate through the list of packets, printing the packets we were
2402 ret = process_specified_packets(cf, &print_args->range, "Printing",
2403 "selected packets", TRUE, print_packet,
2406 g_free(callback_args.header_line_buf);
2407 g_free(callback_args.line_buf);
2408 g_free(callback_args.col_widths);
2413 /* Completed successfully. */
2417 /* Well, the user decided to abort the printing.
2419 XXX - note that what got generated before they did that
2420 will get printed if we're piping to a print program; we'd
2421 have to write to a file and then hand that to the print
2422 program to make it actually not print anything. */
2426 /* Error while printing.
2428 XXX - note that what got generated before they did that
2429 will get printed if we're piping to a print program; we'd
2430 have to write to a file and then hand that to the print
2431 program to make it actually not print anything. */
2432 destroy_print_stream(print_args->stream);
2433 return CF_PRINT_WRITE_ERROR;
2436 if (!print_finale(print_args->stream)) {
2437 destroy_print_stream(print_args->stream);
2438 return CF_PRINT_WRITE_ERROR;
2441 if (!destroy_print_stream(print_args->stream))
2442 return CF_PRINT_WRITE_ERROR;
2448 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2449 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2455 /* Create the protocol tree, but don't fill in the column information. */
2456 epan_dissect_init(&edt, TRUE, TRUE);
2457 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2459 /* Write out the information in that tree. */
2460 proto_tree_write_pdml(&edt, fh);
2462 epan_dissect_cleanup(&edt);
2468 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2473 fh = ws_fopen(print_args->file, "w");
2475 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2477 write_pdml_preamble(fh);
2480 return CF_PRINT_WRITE_ERROR;
2483 /* Iterate through the list of packets, printing the packets we were
2485 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2486 "selected packets", TRUE,
2487 write_pdml_packet, fh);
2492 /* Completed successfully. */
2496 /* Well, the user decided to abort the printing. */
2500 /* Error while printing. */
2502 return CF_PRINT_WRITE_ERROR;
2505 write_pdml_finale(fh);
2508 return CF_PRINT_WRITE_ERROR;
2511 /* XXX - check for an error */
2518 write_psml_packet(capture_file *cf, frame_data *fdata,
2519 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2524 gboolean proto_tree_needed;
2526 /* Fill in the column information, only create the protocol tree
2527 if having custom columns. */
2528 proto_tree_needed = have_custom_cols(&cf->cinfo);
2529 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2530 col_custom_prime_edt(&edt, &cf->cinfo);
2531 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2532 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2534 /* Write out the information in that tree. */
2535 proto_tree_write_psml(&edt, fh);
2537 epan_dissect_cleanup(&edt);
2543 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2548 fh = ws_fopen(print_args->file, "w");
2550 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2552 write_psml_preamble(fh);
2555 return CF_PRINT_WRITE_ERROR;
2558 /* Iterate through the list of packets, printing the packets we were
2560 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2561 "selected packets", TRUE,
2562 write_psml_packet, fh);
2567 /* Completed successfully. */
2571 /* Well, the user decided to abort the printing. */
2575 /* Error while printing. */
2577 return CF_PRINT_WRITE_ERROR;
2580 write_psml_finale(fh);
2583 return CF_PRINT_WRITE_ERROR;
2586 /* XXX - check for an error */
2593 write_csv_packet(capture_file *cf, frame_data *fdata,
2594 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2599 gboolean proto_tree_needed;
2601 /* Fill in the column information, only create the protocol tree
2602 if having custom columns. */
2603 proto_tree_needed = have_custom_cols(&cf->cinfo);
2604 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2605 col_custom_prime_edt(&edt, &cf->cinfo);
2606 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2607 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2609 /* Write out the information in that tree. */
2610 proto_tree_write_csv(&edt, fh);
2612 epan_dissect_cleanup(&edt);
2618 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2623 fh = ws_fopen(print_args->file, "w");
2625 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2627 write_csv_preamble(fh);
2630 return CF_PRINT_WRITE_ERROR;
2633 /* Iterate through the list of packets, printing the packets we were
2635 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2636 "selected packets", TRUE,
2637 write_csv_packet, fh);
2642 /* Completed successfully. */
2646 /* Well, the user decided to abort the printing. */
2650 /* Error while printing. */
2652 return CF_PRINT_WRITE_ERROR;
2655 write_csv_finale(fh);
2658 return CF_PRINT_WRITE_ERROR;
2661 /* XXX - check for an error */
2668 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
2669 union wtap_pseudo_header *pseudo_header _U_,
2670 const guint8 *pd, void *argsp)
2674 proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh);
2679 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2684 fh = ws_fopen(print_args->file, "w");
2687 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2689 write_carrays_preamble(fh);
2693 return CF_PRINT_WRITE_ERROR;
2696 /* Iterate through the list of packets, printing the packets we were
2698 ret = process_specified_packets(cf, &print_args->range,
2700 "selected packets", TRUE,
2701 write_carrays_packet, fh);
2704 /* Completed successfully. */
2707 /* Well, the user decided to abort the printing. */
2710 /* Error while printing. */
2712 return CF_PRINT_WRITE_ERROR;
2715 write_carrays_finale(fh);
2719 return CF_PRINT_WRITE_ERROR;
2727 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2728 search_direction dir)
2732 mdata.string = string;
2733 mdata.string_len = strlen(string);
2734 return find_packet(cf, match_protocol_tree, &mdata, dir);
2738 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2740 mdata->frame_matched = FALSE;
2741 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2742 mdata->string_len = strlen(mdata->string);
2744 /* Iterate through all the nodes looking for matching text */
2745 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2746 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2750 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2752 match_data *mdata = criterion;
2755 /* Load the frame's data. */
2756 if (!cf_read_frame(cf, fdata)) {
2757 /* Attempt to get the packet failed. */
2761 /* Construct the protocol tree, including the displayed text */
2762 epan_dissect_init(&edt, TRUE, TRUE);
2763 /* We don't need the column information */
2764 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2766 /* Iterate through all the nodes, seeing if they have text that matches. */
2768 mdata->frame_matched = FALSE;
2769 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2770 epan_dissect_cleanup(&edt);
2771 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2775 match_subtree_text(proto_node *node, gpointer data)
2777 match_data *mdata = (match_data*) data;
2778 const gchar *string = mdata->string;
2779 size_t string_len = mdata->string_len;
2780 capture_file *cf = mdata->cf;
2781 field_info *fi = PNODE_FINFO(node);
2782 gchar label_str[ITEM_LABEL_LENGTH];
2789 g_assert(fi && "dissection with an invisible proto tree?");
2791 if (mdata->frame_matched) {
2792 /* We already had a match; don't bother doing any more work. */
2796 /* Don't match invisible entries. */
2797 if (PROTO_ITEM_IS_HIDDEN(node))
2800 /* was a free format label produced? */
2802 label_ptr = fi->rep->representation;
2804 /* no, make a generic label */
2805 label_ptr = label_str;
2806 proto_item_fill_label(fi, label_str);
2809 /* Does that label match? */
2810 label_len = strlen(label_ptr);
2811 for (i = 0; i < label_len; i++) {
2812 c_char = label_ptr[i];
2814 c_char = toupper(c_char);
2815 if (c_char == string[c_match]) {
2817 if (c_match == string_len) {
2818 /* No need to look further; we have a match */
2819 mdata->frame_matched = TRUE;
2827 /* Recurse into the subtree, if it exists */
2828 if (node->first_child != NULL)
2829 proto_tree_children_foreach(node, match_subtree_text, mdata);
2833 cf_find_packet_summary_line(capture_file *cf, const char *string,
2834 search_direction dir)
2838 mdata.string = string;
2839 mdata.string_len = strlen(string);
2840 return find_packet(cf, match_summary_line, &mdata, dir);
2844 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2846 match_data *mdata = criterion;
2847 const gchar *string = mdata->string;
2848 size_t string_len = mdata->string_len;
2850 const char *info_column;
2851 size_t info_column_len;
2852 match_result result = MR_NOTMATCHED;
2858 /* Load the frame's data. */
2859 if (!cf_read_frame(cf, fdata)) {
2860 /* Attempt to get the packet failed. */
2864 /* Don't bother constructing the protocol tree */
2865 epan_dissect_init(&edt, FALSE, FALSE);
2866 /* Get the column information */
2867 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2869 /* Find the Info column */
2870 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2871 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2872 /* Found it. See if we match. */
2873 info_column = edt.pi.cinfo->col_data[colx];
2874 info_column_len = strlen(info_column);
2875 for (i = 0; i < info_column_len; i++) {
2876 c_char = info_column[i];
2878 c_char = toupper(c_char);
2879 if (c_char == string[c_match]) {
2881 if (c_match == string_len) {
2882 result = MR_MATCHED;
2891 epan_dissect_cleanup(&edt);
2898 } cbs_t; /* "Counted byte string" */
2901 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
2902 search_direction dir)
2907 info.data_len = string_size;
2909 /* String or hex search? */
2911 /* String search - what type of string? */
2912 switch (cf->scs_type) {
2914 case SCS_ASCII_AND_UNICODE:
2915 return find_packet(cf, match_ascii_and_unicode, &info, dir);
2918 return find_packet(cf, match_ascii, &info, dir);
2921 return find_packet(cf, match_unicode, &info, dir);
2924 g_assert_not_reached();
2928 return find_packet(cf, match_binary, &info, dir);
2932 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2934 cbs_t *info = criterion;
2935 const guint8 *ascii_text = info->data;
2936 size_t textlen = info->data_len;
2937 match_result result;
2943 /* Load the frame's data. */
2944 if (!cf_read_frame(cf, fdata)) {
2945 /* Attempt to get the packet failed. */
2949 result = MR_NOTMATCHED;
2950 buf_len = fdata->pkt_len;
2951 for (i = 0; i < buf_len; i++) {
2954 c_char = toupper(c_char);
2956 if (c_char == ascii_text[c_match]) {
2958 if (c_match == textlen) {
2959 result = MR_MATCHED;
2960 cf->search_pos = i; /* Save the position of the last character
2961 for highlighting the field. */
2972 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2974 cbs_t *info = criterion;
2975 const guint8 *ascii_text = info->data;
2976 size_t textlen = info->data_len;
2977 match_result result;
2983 /* Load the frame's data. */
2984 if (!cf_read_frame(cf, fdata)) {
2985 /* Attempt to get the packet failed. */
2989 result = MR_NOTMATCHED;
2990 buf_len = fdata->pkt_len;
2991 for (i = 0; i < buf_len; i++) {
2994 c_char = toupper(c_char);
2995 if (c_char == ascii_text[c_match]) {
2997 if (c_match == textlen) {
2998 result = MR_MATCHED;
2999 cf->search_pos = i; /* Save the position of the last character
3000 for highlighting the field. */
3010 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3012 cbs_t *info = criterion;
3013 const guint8 *ascii_text = info->data;
3014 size_t textlen = info->data_len;
3015 match_result result;
3021 /* Load the frame's data. */
3022 if (!cf_read_frame(cf, fdata)) {
3023 /* Attempt to get the packet failed. */
3027 result = MR_NOTMATCHED;
3028 buf_len = fdata->pkt_len;
3029 for (i = 0; i < buf_len; i++) {
3032 c_char = toupper(c_char);
3033 if (c_char == ascii_text[c_match]) {
3036 if (c_match == textlen) {
3037 result = MR_MATCHED;
3038 cf->search_pos = i; /* Save the position of the last character
3039 for highlighting the field. */
3049 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3051 cbs_t *info = criterion;
3052 const guint8 *binary_data = info->data;
3053 size_t datalen = info->data_len;
3054 match_result result;
3059 /* Load the frame's data. */
3060 if (!cf_read_frame(cf, fdata)) {
3061 /* Attempt to get the packet failed. */
3065 result = MR_NOTMATCHED;
3066 buf_len = fdata->pkt_len;
3067 for (i = 0; i < buf_len; i++) {
3068 if (cf->pd[i] == binary_data[c_match]) {
3070 if (c_match == datalen) {
3071 result = MR_MATCHED;
3072 cf->search_pos = i; /* Save the position of the last character
3073 for highlighting the field. */
3083 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3084 search_direction dir)
3086 return find_packet(cf, match_dfilter, sfcode, dir);
3090 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3091 search_direction dir)
3096 if (!dfilter_compile(filter, &sfcode)) {
3098 * XXX - this shouldn't happen, as the filter string is machine
3103 if (sfcode == NULL) {
3105 * XXX - this shouldn't happen, as the filter string is machine
3110 result = find_packet(cf, match_dfilter, sfcode, dir);
3111 dfilter_free(sfcode);
3116 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3118 dfilter_t *sfcode = criterion;
3120 match_result result;
3122 /* Load the frame's data. */
3123 if (!cf_read_frame(cf, fdata)) {
3124 /* Attempt to get the packet failed. */
3128 epan_dissect_init(&edt, TRUE, FALSE);
3129 epan_dissect_prime_dfilter(&edt, sfcode);
3130 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3131 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3132 epan_dissect_cleanup(&edt);
3137 cf_find_packet_marked(capture_file *cf, search_direction dir)
3139 return find_packet(cf, match_marked, NULL, dir);
3143 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3145 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3149 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3151 return find_packet(cf, match_time_reference, NULL, dir);
3155 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3157 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3161 find_packet(capture_file *cf,
3162 match_result (*match_function)(capture_file *, frame_data *, void *),
3163 void *criterion, search_direction dir)
3165 frame_data *start_fd;
3168 frame_data *new_fd = NULL;
3169 progdlg_t *progbar = NULL;
3174 GTimeVal start_time;
3175 gchar status_str[100];
3176 int progbar_nextstep;
3177 int progbar_quantum;
3179 match_result result;
3181 start_fd = cf->current_frame;
3182 if (start_fd != NULL) {
3183 /* Iterate through the list of packets, starting at the packet we've
3184 picked, calling a routine to run the filter on the packet, see if
3185 it matches, and stop if so. */
3187 framenum = start_fd->num;
3189 /* Update the progress bar when it gets to this value. */
3190 progbar_nextstep = 0;
3191 /* When we reach the value that triggers a progress bar update,
3192 bump that value by this amount. */
3193 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3194 /* Progress so far. */
3198 g_get_current_time(&start_time);
3200 title = cf->sfilter?cf->sfilter:"";
3202 /* Create the progress bar if necessary.
3203 We check on every iteration of the loop, so that it takes no
3204 longer than the standard time to create it (otherwise, for a
3205 large file, we might take considerably longer than that standard
3206 time in order to get to the next progress bar step). */
3207 if (progbar == NULL)
3208 progbar = delayed_create_progress_dlg("Searching", title,
3209 FALSE, &stop_flag, &start_time, progbar_val);
3211 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3212 when we update it, we have to run the GTK+ main loop to get it
3213 to repaint what's pending, and doing so may involve an "ioctl()"
3214 to see if there's any pending input from an X server, and doing
3215 that for every packet can be costly, especially on a big file. */
3216 if (count >= progbar_nextstep) {
3217 /* let's not divide by zero. I should never be started
3218 * with count == 0, so let's assert that
3220 g_assert(cf->count > 0);
3222 progbar_val = (gfloat) count / cf->count;
3224 if (progbar != NULL) {
3225 g_snprintf(status_str, sizeof(status_str),
3226 "%4u of %u packets", count, cf->count);
3227 update_progress_dlg(progbar, progbar_val, status_str);
3230 progbar_nextstep += progbar_quantum;
3234 /* Well, the user decided to abort the search. Go back to the
3235 frame where we started. */
3240 /* Go past the current frame. */
3241 if (dir == SD_BACKWARD) {
3242 /* Go on to the previous frame. */
3243 if (framenum == 1) {
3245 * XXX - other apps have a bit more of a detailed message
3246 * for this, and instead of offering "OK" and "Cancel",
3247 * they offer things such as "Continue" and "Cancel";
3248 * we need an API for popping up alert boxes with
3249 * {Verb} and "Cancel".
3252 if (prefs.gui_find_wrap)
3254 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3255 framenum = cf->count; /* wrap around */
3259 statusbar_push_temporary_msg("Search reached the beginning.");
3260 framenum = start_fd->num; /* stay on previous packet */
3265 /* Go on to the next frame. */
3266 if (framenum == cf->count) {
3267 if (prefs.gui_find_wrap)
3269 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3270 framenum = 1; /* wrap around */
3274 statusbar_push_temporary_msg("Search reached the end.");
3275 framenum = start_fd->num; /* stay on previous packet */
3280 fdata = frame_data_sequence_find(cf->frames, framenum);
3284 /* Is this packet in the display? */
3285 if (fdata->flags.passed_dfilter) {
3286 /* Yes. Does it match the search criterion? */
3287 result = (*match_function)(cf, fdata, criterion);
3288 if (result == MR_ERROR) {
3289 /* Error; our caller has reported the error. Go back to the frame
3290 where we started. */
3293 } else if (result == MR_MATCHED) {
3294 /* Yes. Go to the new frame. */
3300 if (fdata == start_fd) {
3301 /* We're back to the frame we were on originally, and that frame
3302 doesn't match the search filter. The search failed. */
3307 /* We're done scanning the packets; destroy the progress bar if it
3309 if (progbar != NULL)
3310 destroy_progress_dlg(progbar);
3313 if (new_fd != NULL) {
3314 /* Find and select */
3315 cf->search_in_progress = TRUE;
3316 found = new_packet_list_select_row_from_data(new_fd);
3317 cf->search_in_progress = FALSE;
3318 cf->search_pos = 0; /* Reset the position */
3320 /* We didn't find a row corresponding to this frame.
3321 This means that the frame isn't being displayed currently,
3322 so we can't select it. */
3323 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3324 "%sEnd of capture exceeded!%s\n\n"
3325 "The capture file is probably not fully dissected.",
3326 simple_dialog_primary_start(), simple_dialog_primary_end());
3329 return TRUE; /* success */
3331 return FALSE; /* failure */
3335 cf_goto_frame(capture_file *cf, guint fnumber)
3339 fdata = frame_data_sequence_find(cf->frames, fnumber);
3341 if (fdata == NULL) {
3342 /* we didn't find a packet with that packet number */
3343 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3344 return FALSE; /* we failed to go to that packet */
3346 if (!fdata->flags.passed_dfilter) {
3347 /* that packet currently isn't displayed */
3348 /* XXX - add it to the set of displayed packets? */
3349 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3350 return FALSE; /* we failed to go to that packet */
3353 if (!new_packet_list_select_row_from_data(fdata)) {
3354 /* We didn't find a row corresponding to this frame.
3355 This means that the frame isn't being displayed currently,
3356 so we can't select it. */
3357 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3358 "%sEnd of capture exceeded!%s\n\n"
3359 "The capture file is probably not fully dissected.",
3360 simple_dialog_primary_start(), simple_dialog_primary_end());
3363 return TRUE; /* we got to that packet */
3369 /* Find and select */
3370 new_packet_list_select_first_row();
3371 return TRUE; /* we got to that packet */
3375 cf_goto_bottom_frame()
3377 /* Find and select */
3378 new_packet_list_select_last_row();
3379 return TRUE; /* we got to that packet */
3383 * Go to frame specified by currently selected protocol tree item.
3386 cf_goto_framenum(capture_file *cf)
3388 header_field_info *hfinfo;
3391 if (cf->finfo_selected) {
3392 hfinfo = cf->finfo_selected->hfinfo;
3394 if (hfinfo->type == FT_FRAMENUM) {
3395 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3397 return cf_goto_frame(cf, framenum);
3404 /* Select the packet on a given row. */
3406 cf_select_packet(capture_file *cf, int row)
3410 /* Get the frame data struct pointer for this frame */
3411 fdata = new_packet_list_get_row_data(row);
3413 if (fdata == NULL) {
3414 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3415 the first entry is added to it by "real_insert_row()", that row
3416 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3417 our version and the vanilla GTK+ version).
3419 This means that a "select-row" signal is emitted; this causes
3420 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3423 "cf_select_packet()" fetches, above, the data associated with the
3424 row that was selected; however, as "gtk_clist_append()", which
3425 called "real_insert_row()", hasn't yet returned, we haven't yet
3426 associated any data with that row, so we get back a null pointer.
3428 We can't assume that there's only one frame in the frame list,
3429 either, as we may be filtering the display.
3431 We therefore assume that, if "row" is 0, i.e. the first row
3432 is being selected, and "cf->first_displayed" equals
3433 "cf->last_displayed", i.e. there's only one frame being
3434 displayed, that frame is the frame we want.
3436 This means we have to set "cf->first_displayed" and
3437 "cf->last_displayed" before adding the row to the
3438 GtkCList; see the comment in "add_packet_to_packet_list()". */
3440 if (row == 0 && cf->first_displayed == cf->last_displayed)
3441 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3444 /* If fdata _still_ isn't set simply give up. */
3445 if (fdata == NULL) {
3449 /* Get the data in that frame. */
3450 if (!cf_read_frame (cf, fdata)) {
3454 /* Record that this frame is the current frame. */
3455 cf->current_frame = fdata;
3456 cf->current_row = row;
3458 /* Create the logical protocol tree. */
3459 if (cf->edt != NULL)
3460 epan_dissect_free(cf->edt);
3462 /* We don't need the columns here. */
3463 cf->edt = epan_dissect_new(TRUE, TRUE);
3465 tap_build_interesting(cf->edt);
3466 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3469 dfilter_macro_build_ftv_cache(cf->edt->tree);
3471 cf_callback_invoke(cf_cb_packet_selected, cf);
3474 /* Unselect the selected packet, if any. */
3476 cf_unselect_packet(capture_file *cf)
3478 /* Destroy the epan_dissect_t for the unselected packet. */
3479 if (cf->edt != NULL) {
3480 epan_dissect_free(cf->edt);
3484 /* No packet is selected. */
3485 cf->current_frame = NULL;
3486 cf->current_row = 0;
3488 cf_callback_invoke(cf_cb_packet_unselected, cf);
3490 /* No protocol tree means no selected field. */
3491 cf_unselect_field(cf);
3494 /* Unset the selected protocol tree field, if any. */
3496 cf_unselect_field(capture_file *cf)
3498 cf->finfo_selected = NULL;
3500 cf_callback_invoke(cf_cb_field_unselected, cf);
3504 * Mark a particular frame.
3507 cf_mark_frame(capture_file *cf, frame_data *frame)
3509 if (! frame->flags.marked) {
3510 frame->flags.marked = TRUE;
3511 if (cf->count > cf->marked_count)
3517 * Unmark a particular frame.
3520 cf_unmark_frame(capture_file *cf, frame_data *frame)
3522 if (frame->flags.marked) {
3523 frame->flags.marked = FALSE;
3524 if (cf->marked_count > 0)
3530 * Ignore a particular frame.
3533 cf_ignore_frame(capture_file *cf, frame_data *frame)
3535 if (! frame->flags.ignored) {
3536 frame->flags.ignored = TRUE;
3537 if (cf->count > cf->ignored_count)
3538 cf->ignored_count++;
3543 * Un-ignore a particular frame.
3546 cf_unignore_frame(capture_file *cf, frame_data *frame)
3548 if (frame->flags.ignored) {
3549 frame->flags.ignored = FALSE;
3550 if (cf->ignored_count > 0)
3551 cf->ignored_count--;
3558 } save_callback_args_t;
3561 * Save a capture to a file, in a particular format, saving either
3562 * all packets, all currently-displayed packets, or all marked packets.
3564 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3565 * up a message box for the failure.
3568 save_packet(capture_file *cf _U_, frame_data *fdata,
3569 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3572 save_callback_args_t *args = argsp;
3573 struct wtap_pkthdr hdr;
3576 /* init the wtap header for saving */
3577 hdr.ts.secs = fdata->abs_ts.secs;
3578 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3579 hdr.caplen = fdata->cap_len;
3580 hdr.len = fdata->pkt_len;
3581 hdr.pkt_encap = fdata->lnk_t;
3583 /* and save the packet */
3584 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3585 cf_write_failure_alert_box(args->fname, err);
3592 * Can this capture file be saved in any format except by copying the raw data?
3595 cf_can_save_as(capture_file *cf)
3599 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
3600 /* To save a file with Wiretap, Wiretap has to handle that format,
3601 and its code to handle that format must be able to write a file
3602 with this file's encapsulation type. */
3603 if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
3604 /* OK, we can write it out in this type. */
3609 /* No, we couldn't save it in any format. */
3614 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3616 gchar *from_filename;
3620 save_callback_args_t callback_args;
3622 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
3624 /* don't write over an existing file. */
3625 /* this should've been already checked by our caller, just to be sure... */
3626 if (file_exists(fname)) {
3627 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3628 "%sCapture file: \"%s\" already exists!%s\n\n"
3629 "Please choose a different filename.",
3630 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3634 packet_range_process_init(range);
3636 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3637 /* We're not filtering packets, and we're saving it in the format
3638 it's already in, so we can just move or copy the raw data. */
3640 if (cf->is_tempfile) {
3641 /* The file being saved is a temporary file from a live
3642 capture, so it doesn't need to stay around under that name;
3643 first, try renaming the capture buffer file to the new name. */
3645 if (ws_rename(cf->filename, fname) == 0) {
3646 /* That succeeded - there's no need to copy the source file. */
3647 from_filename = NULL;
3650 if (errno == EXDEV) {
3651 /* They're on different file systems, so we have to copy the
3654 from_filename = cf->filename;
3656 /* The rename failed, but not because they're on different
3657 file systems - put up an error message. (Or should we
3658 just punt and try to copy? The only reason why I'd
3659 expect the rename to fail and the copy to succeed would
3660 be if we didn't have permission to remove the file from
3661 the temporary directory, and that might be fixable - but
3662 is it worth requiring the user to go off and fix it?) */
3663 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3664 file_rename_error_message(errno), fname);
3670 from_filename = cf->filename;
3673 /* It's a permanent file, so we should copy it, and not remove the
3676 from_filename = cf->filename;
3680 /* Copy the file, if we haven't moved it. */
3681 if (!copy_file_binary_mode(from_filename, fname))
3685 /* Either we're filtering packets, or we're saving in a different
3686 format; we can't do that by copying or moving the capture file,
3687 we have to do it by writing the packets out in Wiretap. */
3688 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3691 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3695 /* XXX - we let the user save a subset of the packets.
3697 If we do that, should we make that file the current file? If so,
3698 it means we can no longer get at the other packets. What does
3701 /* Iterate through the list of packets, processing the packets we were
3704 XXX - we've already called "packet_range_process_init(range)", but
3705 "process_specified_packets()" will do it again. Fortunately,
3706 that's harmless in this case, as we haven't done anything to
3707 "range" since we initialized it. */
3708 callback_args.pdh = pdh;
3709 callback_args.fname = fname;
3710 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3711 TRUE, save_packet, &callback_args)) {
3714 /* Completed successfully. */
3718 /* The user decided to abort the saving.
3719 XXX - remove the output file? */
3723 /* Error while saving. */
3724 wtap_dump_close(pdh, &err);
3728 if (!wtap_dump_close(pdh, &err)) {
3729 cf_close_failure_alert_box(fname, err);
3734 cf_callback_invoke(cf_cb_file_save_finished, NULL);
3736 if (packet_range_process_all(range)) {
3737 /* We saved the entire capture, not just some packets from it.
3738 Open and read the file we saved it to.
3740 XXX - this is somewhat of a waste; we already have the
3741 packets, all this gets us is updated file type information
3742 (which we could just stuff into "cf"), and having the new
3743 file be the one we have opened and from which we're reading
3744 the data, and it means we have to spend time opening and
3745 reading the file, which could be a significant amount of
3746 time if the file is large. */
3747 cf->user_saved = TRUE;
3749 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3750 /* XXX - report errors if this fails?
3751 What should we return if it fails or is aborted? */
3753 switch (cf_read(cf, TRUE)) {
3757 /* Just because we got an error, that doesn't mean we were unable
3758 to read any of the file; we handle what we could get from the
3762 case CF_READ_ABORTED:
3763 /* The user bailed out of re-reading the capture file; the
3764 capture file has been closed - just return (without
3765 changing any menu settings; "cf_close()" set them
3766 correctly for the "no capture file open" state). */
3769 cf_callback_invoke(cf_cb_file_save_reload_finished, cf);
3775 cf_callback_invoke(cf_cb_file_save_failed, NULL);
3780 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3781 gboolean for_writing, int file_type)
3784 /* Wiretap error. */
3787 case WTAP_ERR_NOT_REGULAR_FILE:
3788 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3789 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3793 case WTAP_ERR_RANDOM_OPEN_PIPE:
3794 /* Seen only when opening a capture file for reading. */
3795 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3796 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
3800 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3801 /* Seen only when opening a capture file for reading. */
3802 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3803 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
3807 case WTAP_ERR_UNSUPPORTED:
3808 /* Seen only when opening a capture file for reading. */
3809 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3810 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
3812 filename, err_info);
3816 case WTAP_ERR_CANT_WRITE_TO_PIPE:
3817 /* Seen only when opening a capture file for writing. */
3818 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3819 "The file \"%s\" is a pipe, and %s capture files can't be "
3820 "written to a pipe.",
3821 filename, wtap_file_type_string(file_type));
3824 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3825 /* Seen only when opening a capture file for writing. */
3826 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3827 "Wireshark doesn't support writing capture files in that format.");
3830 case WTAP_ERR_UNSUPPORTED_ENCAP:
3832 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3833 "Wireshark can't save this capture in that format.");
3835 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3836 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
3838 filename, err_info);
3843 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3845 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3846 "Wireshark can't save this capture in that format.");
3848 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3849 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
3854 case WTAP_ERR_BAD_RECORD:
3855 /* Seen only when opening a capture file for reading. */
3856 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3857 "The file \"%s\" appears to be damaged or corrupt.\n"
3859 filename, err_info);
3863 case WTAP_ERR_CANT_OPEN:
3865 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3866 "The file \"%s\" could not be created for some unknown reason.",
3869 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3870 "The file \"%s\" could not be opened for some unknown reason.",
3875 case WTAP_ERR_SHORT_READ:
3876 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3877 "The file \"%s\" appears to have been cut short"
3878 " in the middle of a packet or other data.",
3882 case WTAP_ERR_SHORT_WRITE:
3883 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3884 "A full header couldn't be written to the file \"%s\".",
3888 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
3889 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3890 "Gzip compression not supported by this file type.");
3893 case WTAP_ERR_DECOMPRESS:
3894 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3895 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
3896 "(%s)", filename, err_info);
3901 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3902 "The file \"%s\" could not be %s: %s.",
3904 for_writing ? "created" : "opened",
3905 wtap_strerror(err));
3910 open_failure_alert_box(filename, err, for_writing);
3915 file_rename_error_message(int err)
3918 static char errmsg_errno[1024+1];
3923 errmsg = "The path to the file \"%s\" doesn't exist.";
3927 errmsg = "You don't have permission to move the capture file to \"%s\".";
3931 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3932 "The file \"%%s\" could not be moved: %s.",
3933 wtap_strerror(err));
3934 errmsg = errmsg_errno;
3941 cf_write_failure_alert_box(const char *filename, int err)
3944 /* Wiretap error. */
3945 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3946 "An error occurred while writing to the file \"%s\": %s.",
3947 filename, wtap_strerror(err));
3950 write_failure_alert_box(filename, err);
3954 /* Check for write errors - if the file is being written to an NFS server,
3955 a write error may not show up until the file is closed, as NFS clients
3956 might not send writes to the server until the "write()" call finishes,
3957 so that the write may fail on the server but the "write()" may succeed. */
3959 cf_close_failure_alert_box(const char *filename, int err)
3962 /* Wiretap error. */
3965 case WTAP_ERR_CANT_CLOSE:
3966 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3967 "The file \"%s\" couldn't be closed for some unknown reason.",
3971 case WTAP_ERR_SHORT_WRITE:
3972 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3973 "Not all the packets could be written to the file \"%s\".",
3978 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3979 "An error occurred while closing the file \"%s\": %s.",
3980 filename, wtap_strerror(err));
3985 We assume that a close error from the OS is really a write error. */
3986 write_failure_alert_box(filename, err);
3990 /* Reload the current capture file. */
3992 cf_reload(capture_file *cf) {
3994 gboolean is_tempfile;
3997 /* If the file could be opened, "cf_open()" calls "cf_close()"
3998 to get rid of state for the old capture file before filling in state
3999 for the new capture file. "cf_close()" will remove the file if
4000 it's a temporary file; we don't want that to happen (for one thing,
4001 it'd prevent subsequent reopens from working). Remember whether it's
4002 a temporary file, mark it as not being a temporary file, and then
4003 reopen it as the type of file it was.
4005 Also, "cf_close()" will free "cf->filename", so we must make
4006 a copy of it first. */
4007 filename = g_strdup(cf->filename);
4008 is_tempfile = cf->is_tempfile;
4009 cf->is_tempfile = FALSE;
4010 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4011 switch (cf_read(cf, FALSE)) {
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 free the capture file name
4023 string and return (without changing the last containing
4029 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4030 Instead, the file was left open, so we should restore "cf->is_tempfile"
4033 XXX - change the menu? Presumably "cf_open()" will do that;
4034 make sure it does! */
4035 cf->is_tempfile = is_tempfile;
4037 /* "cf_open()" made a copy of the file name we handed it, so
4038 we should free up our copy. */
4048 * indent-tabs-mode: nil
4051 * ex: set shiftwidth=2 tabstop=8 expandtab
4052 * :indentSize=2:tabSize=8:noTabs=true: