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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
44 #include <epan/epan.h>
45 #include <epan/filesystem.h>
48 #include "color_filters.h"
50 #include <epan/column.h>
51 #include <epan/packet.h>
52 #include <epan/column-utils.h>
53 #include "packet-range.h"
60 #include <epan/prefs.h>
61 #include <epan/dfilter/dfilter.h>
62 #include <epan/epan_dissect.h>
64 #include <epan/dissectors/packet-data.h>
65 #include <epan/dissectors/packet-ber.h>
66 #include <epan/timestamp.h>
67 #include <epan/dfilter/dfilter-macro.h>
68 #include <wsutil/file_util.h>
69 #include <epan/strutil.h>
70 #include <epan/addr_resolv.h>
72 #include "ui/alert_box.h"
73 #include "ui/simple_dialog.h"
74 #include "ui/main_statusbar.h"
75 #include "ui/progress_dlg.h"
76 #include "ui/ui_util.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 void cf_rename_failure_alert_box(const char *filename, int err);
129 static void cf_close_failure_alert_box(const char *filename, int err);
130 static void ref_time_packets(capture_file *cf);
131 /* Update the progress bar this many times when reading a file. */
132 #define N_PROGBAR_UPDATES 100
133 /* We read around 200k/100ms don't update the progress bar more often than that */
134 #define MIN_QUANTUM 200000
135 #define MIN_NUMBER_OF_PACKET 1500
138 * We could probably use g_signal_...() instead of the callbacks below but that
139 * would require linking our CLI programs to libgobject and creating an object
140 * instance for the signals.
143 cf_callback_t cb_fct;
145 } cf_callback_data_t;
147 static GList *cf_callbacks = NULL;
150 cf_callback_invoke(int event, gpointer data)
152 cf_callback_data_t *cb;
153 GList *cb_item = cf_callbacks;
155 /* there should be at least one interested */
156 g_assert(cb_item != NULL);
158 while (cb_item != NULL) {
160 cb->cb_fct(event, data, cb->user_data);
161 cb_item = g_list_next(cb_item);
167 cf_callback_add(cf_callback_t func, gpointer user_data)
169 cf_callback_data_t *cb;
171 cb = g_malloc(sizeof(cf_callback_data_t));
173 cb->user_data = user_data;
175 cf_callbacks = g_list_append(cf_callbacks, cb);
179 cf_callback_remove(cf_callback_t func)
181 cf_callback_data_t *cb;
182 GList *cb_item = cf_callbacks;
184 while (cb_item != NULL) {
186 if (cb->cb_fct == func) {
187 cf_callbacks = g_list_remove(cf_callbacks, cb);
191 cb_item = g_list_next(cb_item);
194 g_assert_not_reached();
198 cf_timestamp_auto_precision(capture_file *cf)
201 int prec = timestamp_get_precision();
204 /* don't try to get the file's precision if none is opened */
205 if (cf->state == FILE_CLOSED) {
209 /* if we are in auto mode, set precision of current file */
210 if (prec == TS_PREC_AUTO ||
211 prec == TS_PREC_AUTO_SEC ||
212 prec == TS_PREC_AUTO_DSEC ||
213 prec == TS_PREC_AUTO_CSEC ||
214 prec == TS_PREC_AUTO_MSEC ||
215 prec == TS_PREC_AUTO_USEC ||
216 prec == TS_PREC_AUTO_NSEC)
218 switch(wtap_file_tsprecision(cf->wth)) {
219 case(WTAP_FILE_TSPREC_SEC):
220 timestamp_set_precision(TS_PREC_AUTO_SEC);
222 case(WTAP_FILE_TSPREC_DSEC):
223 timestamp_set_precision(TS_PREC_AUTO_DSEC);
225 case(WTAP_FILE_TSPREC_CSEC):
226 timestamp_set_precision(TS_PREC_AUTO_CSEC);
228 case(WTAP_FILE_TSPREC_MSEC):
229 timestamp_set_precision(TS_PREC_AUTO_MSEC);
231 case(WTAP_FILE_TSPREC_USEC):
232 timestamp_set_precision(TS_PREC_AUTO_USEC);
234 case(WTAP_FILE_TSPREC_NSEC):
235 timestamp_set_precision(TS_PREC_AUTO_NSEC);
238 g_assert_not_reached();
241 /* Set the column widths of those columns that show the time in
242 "command-line-specified" format. */
243 for (i = 0; i < cf->cinfo.num_cols; i++) {
244 if (col_has_time_fmt(&cf->cinfo, i)) {
245 packet_list_resize_column(i);
251 cf_get_computed_elapsed(void)
253 return computed_elapsed;
256 static void reset_elapsed(void)
258 computed_elapsed = 0;
261 static void compute_elapsed(GTimeVal *start_time)
266 g_get_current_time(&time_now);
268 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
269 time_now.tv_usec - start_time->tv_usec;
271 computed_elapsed = (gulong) (delta_time / 1000); /* ms */
275 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
280 wth = wtap_open_offline(fname, err, &err_info, TRUE);
284 /* The open succeeded. Close whatever capture file we had open,
285 and fill in the information for this file. */
288 /* Cleanup all data structures used for dissection. */
289 cleanup_dissection();
290 /* Initialize all data structures used for dissection. */
293 /* We're about to start reading the file. */
294 cf->state = FILE_READ_IN_PROGRESS;
299 /* Set the file name because we need it to set the follow stream filter.
300 XXX - is that still true? We need it for other reasons, though,
302 cf->filename = g_strdup(fname);
304 /* Indicate whether it's a permanent or temporary file. */
305 cf->is_tempfile = is_tempfile;
307 /* No user changes yet. */
308 cf->unsaved_changes = FALSE;
312 cf->cd_t = wtap_file_type(cf->wth);
313 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
315 cf->packet_comment_count = 0;
316 cf->displayed_count = 0;
317 cf->marked_count = 0;
318 cf->ignored_count = 0;
319 cf->ref_time_count = 0;
320 cf->drops_known = FALSE;
322 cf->snap = wtap_snapshot_length(cf->wth);
324 /* Snapshot length not known. */
325 cf->has_snap = FALSE;
326 cf->snap = WTAP_MAX_PACKET_SIZE;
330 /* Allocate a frame_data_sequence for the frames in this file */
331 cf->frames = new_frame_data_sequence();
333 nstime_set_zero(&cf->elapsed_time);
334 nstime_set_unset(&first_ts);
335 nstime_set_unset(&prev_dis_ts);
336 nstime_set_unset(&prev_cap_ts);
339 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
340 cf_timestamp_auto_precision(cf);
342 packet_list_queue_draw();
343 fileset_file_opened(fname);
345 if (cf->cd_t == WTAP_FILE_BER) {
346 /* tell the BER dissector the file name */
347 ber_set_filename(cf->filename);
350 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
351 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
356 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
361 * Add an encapsulation type to cf->linktypes.
364 cf_add_encapsulation_type(capture_file *cf, int encap)
368 for (i = 0; i < cf->linktypes->len; i++) {
369 if (g_array_index(cf->linktypes, gint, i) == encap)
370 return; /* it's already there */
372 /* It's not already there - add it. */
373 g_array_append_val(cf->linktypes, encap);
377 * Reset the state for the currently closed file, but don't do the
378 * UI callbacks; this is for use in "cf_open()", where we don't
379 * want the UI to go from "file open" to "file closed" back to
380 * "file open", we want it to go from "old file open" to "new file
381 * open and being read".
383 * XXX - currently, cf_open() calls cf_close(), rather than
387 cf_reset_state(capture_file *cf)
389 /* Die if we're in the middle of reading a file. */
390 g_assert(cf->state != FILE_READ_IN_PROGRESS);
396 /* We have no file open... */
397 if (cf->filename != NULL) {
398 /* If it's a temporary file, remove it. */
400 ws_unlink(cf->filename);
401 g_free(cf->filename);
404 /* ...which means we have no changes to that file to save. */
405 cf->unsaved_changes = FALSE;
407 dfilter_free(cf->rfcode);
409 if (cf->frames != NULL) {
410 free_frame_data_sequence(cf->frames);
413 #ifdef WANT_PACKET_EDITOR
414 if (cf->edited_frames) {
415 g_tree_destroy(cf->edited_frames);
416 cf->edited_frames = NULL;
419 cf_unselect_packet(cf); /* nothing to select */
420 cf->first_displayed = 0;
421 cf->last_displayed = 0;
423 /* No frames, no frame selected, no field in that frame selected. */
425 cf->current_frame = 0;
427 cf->finfo_selected = NULL;
429 /* No frame link-layer types, either. */
430 g_array_free(cf->linktypes, TRUE);
431 cf->linktypes = NULL;
433 /* Clear the packet list. */
434 packet_list_freeze();
439 nstime_set_zero(&cf->elapsed_time);
441 reset_tap_listeners();
443 /* We have no file open. */
444 cf->state = FILE_CLOSED;
446 fileset_file_closed();
449 /* Reset everything to a pristine state */
451 cf_close(capture_file *cf)
453 if (cf->state != FILE_CLOSED) {
454 cf_callback_invoke(cf_cb_file_closing, cf);
456 /* close things, if not already closed before */
457 color_filters_cleanup();
459 cleanup_dissection();
461 cf_callback_invoke(cf_cb_file_closed, cf);
466 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
470 progbar_val = (gfloat) file_pos / (gfloat) size;
471 if (progbar_val > 1.0) {
473 /* The file probably grew while we were reading it.
474 * Update file size, and try again.
476 size = wtap_file_size(cf->wth, NULL);
479 progbar_val = (gfloat) file_pos / (gfloat) size;
481 /* If it's still > 1, either "wtap_file_size()" failed (in which
482 * case there's not much we can do about it), or the file
483 * *shrank* (in which case there's not much we can do about
484 * it); just clip the progress value at 1.0.
486 if (progbar_val > 1.0f)
490 g_snprintf(status_str, status_size,
491 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
492 file_pos / 1024, size / 1024);
498 cf_read(capture_file *cf, gboolean reloading)
505 progdlg_t *volatile progbar = NULL;
507 volatile gint64 size;
508 volatile float progbar_val;
510 gchar status_str[100];
511 volatile gint64 progbar_nextstep;
512 volatile gint64 progbar_quantum;
514 gboolean filtering_tap_listeners;
516 volatile int count = 0;
518 volatile int displayed_once = 0;
522 /* Compile the current display filter.
523 * We assume this will not fail since cf->dfilter is only set in
524 * cf_filter IFF the filter was valid.
526 compiled = dfilter_compile(cf->dfilter, &dfcode);
527 g_assert(!cf->dfilter || (compiled && dfcode));
529 /* Do we have any tap listeners with filters? */
530 filtering_tap_listeners = have_filtering_tap_listeners();
532 /* Get the union of the flags for all tap listeners. */
533 tap_flags = union_of_tap_listener_flags();
535 reset_tap_listeners();
537 name_ptr = g_filename_display_basename(cf->filename);
540 cf_callback_invoke(cf_cb_file_reload_started, cf);
542 cf_callback_invoke(cf_cb_file_read_started, cf);
544 /* Record whether the file is compressed.
545 XXX - do we know this at open time? */
546 cf->iscompressed = wtap_iscompressed(cf->wth);
548 /* Find the size of the file. */
549 size = wtap_file_size(cf->wth, NULL);
551 /* Update the progress bar when it gets to this value. */
552 progbar_nextstep = 0;
553 /* When we reach the value that triggers a progress bar update,
554 bump that value by this amount. */
556 progbar_quantum = size/N_PROGBAR_UPDATES;
557 if (progbar_quantum < MIN_QUANTUM)
558 progbar_quantum = MIN_QUANTUM;
561 /* Progress so far. */
564 /* The packet list window will be empty until the file is completly loaded */
565 packet_list_freeze();
568 g_get_current_time(&start_time);
570 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
573 file_pos = wtap_read_so_far(cf->wth);
575 /* Create the progress bar if necessary.
576 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
578 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
579 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
581 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
582 TRUE, &stop_flag, &start_time, progbar_val);
584 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
585 TRUE, &stop_flag, &start_time, progbar_val);
588 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
589 when we update it, we have to run the GTK+ main loop to get it
590 to repaint what's pending, and doing so may involve an "ioctl()"
591 to see if there's any pending input from an X server, and doing
592 that for every packet can be costly, especially on a big file. */
593 if (file_pos >= progbar_nextstep) {
594 if (progbar != NULL) {
595 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
596 /* update the packet bar content on the first run or frequently on very large files */
598 if (progbar_quantum > 500000 || displayed_once == 0) {
599 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
601 packets_bar_update();
604 #endif /* HAVE_LIBPCAP */
605 update_progress_dlg(progbar, progbar_val, status_str);
607 progbar_nextstep += progbar_quantum;
612 /* Well, the user decided to abort the read. He/She will be warned and
613 it might be enough for him/her to work with the already loaded
615 This is especially true for very large capture files, where you don't
616 want to wait loading the whole file (which may last minutes or even
617 hours even on fast machines) just to see that it was the wrong file. */
621 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
623 CATCH(OutOfMemoryError) {
624 simple_message_box(ESD_TYPE_ERROR, NULL,
625 "Some infos / workarounds can be found at:\n"
626 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
627 "Sorry, but Wireshark has run out of memory and has to terminate now!");
629 /* Could we close the current capture and free up memory from that? */
632 /* we have to terminate, as we cannot recover from the memory error */
639 /* Free the display name */
642 /* Cleanup and release all dfilter resources */
643 if (dfcode != NULL) {
644 dfilter_free(dfcode);
647 /* We're done reading the file; destroy the progress bar if it was created. */
649 destroy_progress_dlg(progbar);
651 /* We're done reading sequentially through the file. */
652 cf->state = FILE_READ_DONE;
654 /* Close the sequential I/O side, to free up memory it requires. */
655 wtap_sequential_close(cf->wth);
657 /* Allow the protocol dissectors to free up memory that they
658 * don't need after the sequential run-through of the packets. */
659 postseq_cleanup_all_protocols();
661 /* compute the time it took to load the file */
662 compute_elapsed(&start_time);
664 /* Set the file encapsulation type now; we don't know what it is until
665 we've looked at all the packets, as we don't know until then whether
666 there's more than one type (and thus whether it's
667 WTAP_ENCAP_PER_PACKET). */
668 cf->lnk_t = wtap_file_encap(cf->wth);
670 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
675 cf_callback_invoke(cf_cb_file_reload_finished, cf);
677 cf_callback_invoke(cf_cb_file_read_finished, cf);
679 /* If we have any displayed packets to select, select the first of those
680 packets by making the first row the selected row. */
681 if (cf->first_displayed != 0) {
682 packet_list_select_first_row();
686 simple_message_box(ESD_TYPE_WARN, NULL,
687 "The remaining packets in the file were discarded.\n"
689 "As a lot of packets from the original file will be missing,\n"
690 "remember to be careful when saving the current content to a file.\n",
691 "File loading was cancelled!");
692 return CF_READ_ERROR;
696 /* Put up a message box noting that the read failed somewhere along
697 the line. Don't throw out the stuff we managed to read, though,
701 case WTAP_ERR_UNSUPPORTED:
702 simple_error_message_box(
703 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
708 case WTAP_ERR_UNSUPPORTED_ENCAP:
709 simple_error_message_box(
710 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
715 case WTAP_ERR_CANT_READ:
716 simple_error_message_box(
717 "An attempt to read from the capture file failed for"
718 " some unknown reason.");
721 case WTAP_ERR_SHORT_READ:
722 simple_error_message_box(
723 "The capture file appears to have been cut short"
724 " in the middle of a packet.");
727 case WTAP_ERR_BAD_FILE:
728 simple_error_message_box(
729 "The capture file appears to be damaged or corrupt.\n(%s)",
734 case WTAP_ERR_DECOMPRESS:
735 simple_error_message_box(
736 "The compressed capture file appears to be damaged or corrupt.\n"
742 simple_error_message_box(
743 "An error occurred while reading the"
744 " capture file: %s.", wtap_strerror(err));
747 return CF_READ_ERROR;
754 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
756 cf_status_t cf_status;
758 cf_status = cf_open(cf, fname, is_tempfile, err);
763 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
765 gint64 data_offset = 0;
767 volatile int newly_displayed_packets = 0;
769 gboolean filtering_tap_listeners;
773 /* Compile the current display filter.
774 * We assume this will not fail since cf->dfilter is only set in
775 * cf_filter IFF the filter was valid.
777 compiled = dfilter_compile(cf->dfilter, &dfcode);
778 g_assert(!cf->dfilter || (compiled && dfcode));
780 /* Do we have any tap listeners with filters? */
781 filtering_tap_listeners = have_filtering_tap_listeners();
783 /* Get the union of the flags for all tap listeners. */
784 tap_flags = union_of_tap_listener_flags();
788 packet_list_check_end();
789 /* Don't freeze/thaw the list when doing live capture */
790 /*packet_list_freeze();*/
792 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
794 while (to_read != 0) {
795 wtap_cleareof(cf->wth);
796 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
799 if (cf->state == FILE_READ_ABORTED) {
800 /* Well, the user decided to exit Wireshark. Break out of the
801 loop, and let the code below (which is called even if there
802 aren't any packets left to read) exit. */
806 if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
807 data_offset) != -1) {
808 newly_displayed_packets++;
811 CATCH(OutOfMemoryError) {
812 simple_message_box(ESD_TYPE_ERROR, NULL,
813 "Some infos / workarounds can be found at:\n"
814 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
815 "Sorry, but Wireshark has run out of memory and has to terminate now!");
817 /* Could we close the current capture and free up memory from that? */
818 return CF_READ_ABORTED;
820 /* we have to terminate, as we cannot recover from the memory error */
828 /* Update the file encapsulation; it might have changed based on the
829 packets we've read. */
830 cf->lnk_t = wtap_file_encap(cf->wth);
832 /* Cleanup and release all dfilter resources */
833 if (dfcode != NULL) {
834 dfilter_free(dfcode);
837 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
838 cf->count, cf->state, *err);*/
840 /* Don't freeze/thaw the list when doing live capture */
841 /*packet_list_thaw();*/
842 /* With the new packet list the first packet
843 * isn't automatically selected.
845 if (!cf->current_frame)
846 packet_list_select_first_row();
848 /* moving to the end of the packet list - if the user requested so and
849 we have some new packets. */
850 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
851 packet_list_moveto_end();
853 if (cf->state == FILE_READ_ABORTED) {
854 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
855 so that our caller can kill off the capture child process;
856 this will cause an EOF on the pipe from the child, so
857 "cf_finish_tail()" will be called, and it will clean up
859 return CF_READ_ABORTED;
860 } else if (*err != 0) {
861 /* We got an error reading the capture file.
862 XXX - pop up a dialog box instead? */
863 g_warning("Error \"%s\" while reading: \"%s\"\n",
864 wtap_strerror(*err), cf->filename);
866 return CF_READ_ERROR;
872 cf_fake_continue_tail(capture_file *cf) {
873 cf->state = FILE_READ_DONE;
877 cf_finish_tail(capture_file *cf, int *err)
882 gboolean filtering_tap_listeners;
886 /* Compile the current display filter.
887 * We assume this will not fail since cf->dfilter is only set in
888 * cf_filter IFF the filter was valid.
890 compiled = dfilter_compile(cf->dfilter, &dfcode);
891 g_assert(!cf->dfilter || (compiled && dfcode));
893 /* Do we have any tap listeners with filters? */
894 filtering_tap_listeners = have_filtering_tap_listeners();
896 /* Get the union of the flags for all tap listeners. */
897 tap_flags = union_of_tap_listener_flags();
899 if (cf->wth == NULL) {
901 return CF_READ_ERROR;
904 packet_list_check_end();
905 /* Don't freeze/thaw the list when doing live capture */
906 /*packet_list_freeze();*/
908 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
909 if (cf->state == FILE_READ_ABORTED) {
910 /* Well, the user decided to abort the read. Break out of the
911 loop, and let the code below (which is called even if there
912 aren't any packets left to read) exit. */
915 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
918 /* Cleanup and release all dfilter resources */
919 if (dfcode != NULL) {
920 dfilter_free(dfcode);
923 /* Don't freeze/thaw the list when doing live capture */
924 /*packet_list_thaw();*/
926 if (cf->state == FILE_READ_ABORTED) {
927 /* Well, the user decided to abort the read. We're only called
928 when the child capture process closes the pipe to us (meaning
929 it's probably exited), so we can just close the capture
930 file; we return CF_READ_ABORTED so our caller can do whatever
931 is appropriate when that happens. */
933 return CF_READ_ABORTED;
936 if (auto_scroll_live && cf->count != 0)
937 packet_list_moveto_end();
939 /* We're done reading sequentially through the file. */
940 cf->state = FILE_READ_DONE;
942 /* We're done reading sequentially through the file; close the
943 sequential I/O side, to free up memory it requires. */
944 wtap_sequential_close(cf->wth);
946 /* Allow the protocol dissectors to free up memory that they
947 * don't need after the sequential run-through of the packets. */
948 postseq_cleanup_all_protocols();
950 /* Update the file encapsulation; it might have changed based on the
951 packets we've read. */
952 cf->lnk_t = wtap_file_encap(cf->wth);
954 /* Update the details in the file-set dialog, as the capture file
955 * has likely grown since we first stat-ed it */
956 fileset_update_file(cf->filename);
959 /* We got an error reading the capture file.
960 XXX - pop up a dialog box? */
961 return CF_READ_ERROR;
966 #endif /* HAVE_LIBPCAP */
969 cf_get_display_name(capture_file *cf)
973 /* Return a name to use in displays */
974 if (!cf->is_tempfile) {
975 /* Get the last component of the file name, and use that. */
977 displayname = g_filename_display_basename(cf->filename);
979 displayname=g_strdup("(No file)");
982 /* The file we read is a temporary file from a live capture or
983 a merge operation; we don't mention its name, but, if it's
984 from a capture, give the source of the capture. */
986 displayname = g_strdup(cf->source);
988 displayname = g_strdup("(Untitled)");
994 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1000 cf->source = g_strdup(source);
1002 cf->source = g_strdup("");
1006 const gchar *cf_get_tempfile_source(capture_file *cf) {
1014 /* XXX - use a macro instead? */
1016 cf_get_packet_count(capture_file *cf)
1021 /* XXX - use a macro instead? */
1023 cf_set_packet_count(capture_file *cf, int packet_count)
1025 cf->count = packet_count;
1028 /* XXX - use a macro instead? */
1030 cf_is_tempfile(capture_file *cf)
1032 return cf->is_tempfile;
1035 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1037 cf->is_tempfile = is_tempfile;
1041 /* XXX - use a macro instead? */
1042 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1044 cf->drops_known = drops_known;
1047 /* XXX - use a macro instead? */
1048 void cf_set_drops(capture_file *cf, guint32 drops)
1053 /* XXX - use a macro instead? */
1054 gboolean cf_get_drops_known(capture_file *cf)
1056 return cf->drops_known;
1059 /* XXX - use a macro instead? */
1060 guint32 cf_get_drops(capture_file *cf)
1065 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1067 cf->rfcode = rfcode;
1071 find_and_mark_frame_depended_upon(gpointer data, gpointer user_data)
1073 frame_data *dependent_fd;
1074 guint32 dependent_frame = GPOINTER_TO_UINT(data);
1075 capture_file *cf = (capture_file *)user_data;
1077 dependent_fd = frame_data_sequence_find(cf->frames, dependent_frame);
1078 dependent_fd->flags.dependent_of_displayed = 1;
1082 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1083 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1085 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1087 gboolean add_to_packet_list)
1089 gboolean create_proto_tree = FALSE;
1094 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1096 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1097 &first_ts, &prev_dis_ts, &prev_cap_ts);
1100 + we have a display filter and are re-applying it;
1101 + we have tap listeners with filters;
1102 + we have tap listeners that require a protocol tree;
1104 allocate a protocol tree root node, so that we'll construct
1105 a protocol tree against which a filter expression can be
1107 if ((dfcode != NULL && refilter) ||
1108 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1109 create_proto_tree = TRUE;
1111 /* Dissect the frame. */
1112 epan_dissect_init(&edt, create_proto_tree, FALSE);
1114 if (dfcode != NULL && refilter) {
1115 epan_dissect_prime_dfilter(&edt, dfcode);
1118 tap_queue_init(&edt);
1119 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1120 tap_push_tapped_queue(&edt);
1122 /* If we have a display filter, apply it if we're refiltering, otherwise
1123 leave the "passed_dfilter" flag alone.
1125 If we don't have a display filter, set "passed_dfilter" to 1. */
1126 if (dfcode != NULL) {
1128 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1130 if (fdata->flags.passed_dfilter) {
1131 /* This frame passed the display filter but it may depend on other
1132 * (potentially not displayed) frames. Find those frames and mark them
1135 g_slist_foreach(edt.pi.dependent_frames, find_and_mark_frame_depended_upon, cf);
1139 fdata->flags.passed_dfilter = 1;
1141 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1142 cf->displayed_count++;
1144 if (add_to_packet_list) {
1145 /* We fill the needed columns from new_packet_list */
1146 row = packet_list_append(cinfo, fdata, &edt.pi);
1149 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1151 frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1153 /* If we haven't yet seen the first frame, this is it.
1155 XXX - we must do this before we add the row to the display,
1156 as, if the display's GtkCList's selection mode is
1157 GTK_SELECTION_BROWSE, when the first entry is added to it,
1158 "cf_select_packet()" will be called, and it will fetch the row
1159 data for the 0th row, and will get a null pointer rather than
1160 "fdata", as "gtk_clist_append()" won't yet have returned and
1161 thus "gtk_clist_set_row_data()" won't yet have been called.
1163 We thus need to leave behind bread crumbs so that
1164 "cf_select_packet()" can find this frame. See the comment
1165 in "cf_select_packet()". */
1166 if (cf->first_displayed == 0)
1167 cf->first_displayed = fdata->num;
1169 /* This is the last frame we've seen so far. */
1170 cf->last_displayed = fdata->num;
1173 epan_dissect_cleanup(&edt);
1177 /* read in a new packet */
1178 /* returns the row of the new packet in the packet list or -1 if not displayed */
1180 read_packet(capture_file *cf, dfilter_t *dfcode,
1181 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1183 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1184 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1185 const guchar *buf = wtap_buf_ptr(cf->wth);
1192 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1193 it's not already there.
1194 XXX - yes, this is O(N), so if every packet had a different
1195 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1196 there are probably going to be a small number of encapsulation types
1198 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1200 /* The frame number of this packet is one more than the count of
1201 frames in the file so far. */
1202 framenum = cf->count + 1;
1204 frame_data_init(&fdlocal, framenum, phdr, offset, cum_bytes);
1209 epan_dissect_init(&edt, TRUE, FALSE);
1210 epan_dissect_prime_dfilter(&edt, cf->rfcode);
1211 epan_dissect_run(&edt, pseudo_header, buf, &fdlocal, NULL);
1212 passed = dfilter_apply_edt(cf->rfcode, &edt);
1213 epan_dissect_cleanup(&edt);
1217 /* This does a shallow copy of fdlocal, which is good enough. */
1218 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1221 if (fdlocal.opt_comment != NULL)
1222 cf->packet_comment_count++;
1223 cf->f_datalen = offset + fdlocal.cap_len;
1225 if (!cf->redissecting) {
1226 row = add_packet_to_packet_list(fdata, cf, dfcode,
1227 filtering_tap_listeners, tap_flags,
1228 pseudo_header, buf, TRUE, TRUE);
1236 cf_merge_files(char **out_filenamep, int in_file_count,
1237 char *const *in_filenames, int file_type, gboolean do_append)
1239 merge_in_file_t *in_files, *in_file;
1244 int open_err, read_err, write_err, close_err;
1248 gboolean got_read_error = FALSE, got_write_error = FALSE;
1250 progdlg_t *progbar = NULL;
1252 gint64 f_len, file_pos;
1254 GTimeVal start_time;
1255 gchar status_str[100];
1256 gint64 progbar_nextstep;
1257 gint64 progbar_quantum;
1258 gchar *display_basename;
1259 int selected_frame_type;
1260 gboolean fake_interface_ids = FALSE;
1262 /* open the input files */
1263 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1264 &open_err, &err_info, &err_fileno)) {
1266 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1271 if (*out_filenamep != NULL) {
1272 out_filename = *out_filenamep;
1273 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1277 out_fd = create_tempfile(&tmpname, "wireshark");
1280 out_filename = g_strdup(tmpname);
1281 *out_filenamep = out_filename;
1285 merge_close_in_files(in_file_count, in_files);
1287 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1291 selected_frame_type = merge_select_frame_type(in_file_count, in_files);
1293 /* If we are trying to merge a number of libpcap files with different encapsulation types
1294 * change the output file type to pcapng and create SHB and IDB:s for the new file use the
1295 * interface index stored in in_files per file to change the phdr before writing the datablock.
1296 * XXX should it be an option to convert to pcapng?
1298 * We need something similar when merging pcapng files possibly with an option to say
1299 * the same interface(s) used in all in files. SHBs comments should be merged together.
1301 if ((selected_frame_type == WTAP_ENCAP_PER_PACKET)&&(file_type == WTAP_FILE_PCAP)) {
1302 /* Write output in pcapng format */
1303 wtapng_section_t *shb_hdr;
1304 wtapng_iface_descriptions_t *idb_inf, *idb_inf_merge_file;
1305 wtapng_if_descr_t int_data, *file_int_data;
1306 GString *comment_gstr;
1309 fake_interface_ids = TRUE;
1310 /* Create SHB info */
1311 shb_hdr = wtap_file_get_shb_info(in_files[0].wth);
1312 comment_gstr = g_string_new("");
1313 g_string_append_printf(comment_gstr, "%s \n",shb_hdr->opt_comment);
1314 g_string_append_printf(comment_gstr, "File created by merging: \n");
1315 file_type = WTAP_FILE_PCAPNG;
1317 for (i = 0; i < in_file_count; i++) {
1318 g_string_append_printf(comment_gstr, "File%d: %s \n",i+1,in_files[i].filename);
1320 shb_hdr->section_length = -1;
1322 shb_hdr->opt_comment = g_string_free(comment_gstr, FALSE); /* NULL if not available */
1323 shb_hdr->shb_hardware = NULL; /* NULL if not available, UTF-8 string containing the */
1324 /* description of the hardware used to create this section. */
1325 shb_hdr->shb_os = NULL; /* NULL if not available, UTF-8 string containing the name */
1326 /* of the operating system used to create this section. */
1327 shb_hdr->shb_user_appl = "Wireshark"; /* NULL if not available, UTF-8 string containing the name */
1328 /* of the application used to create this section. */
1330 /* create fake IDB info */
1331 idb_inf = g_new(wtapng_iface_descriptions_t,1);
1332 idb_inf->number_of_interfaces = in_file_count; /* TODO make this the number of DIFFERENT encapsulation types
1333 * check that snaplength is the same too?
1335 idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1337 for (i = 0; i < in_file_count; i++) {
1338 idb_inf_merge_file = wtap_file_get_idb_info(in_files[i].wth);
1339 /* read the interface data from the in file to our combined interfca data */
1340 file_int_data = &g_array_index (idb_inf_merge_file->interface_data, wtapng_if_descr_t, 0);
1341 int_data.wtap_encap = file_int_data->wtap_encap;
1342 int_data.time_units_per_second = file_int_data->time_units_per_second;
1343 int_data.link_type = file_int_data->link_type;
1344 int_data.snap_len = file_int_data->snap_len;
1345 int_data.if_name = g_strdup(file_int_data->if_name);
1346 int_data.opt_comment = NULL;
1347 int_data.if_description = NULL;
1348 int_data.if_speed = 0;
1349 int_data.if_tsresol = 6;
1350 int_data.if_filter_str = NULL;
1351 int_data.bpf_filter_len = 0;
1352 int_data.if_filter_bpf_bytes = NULL;
1353 int_data.if_os = NULL;
1354 int_data.if_fcslen = -1;
1355 int_data.num_stat_entries = 0; /* Number of ISB:s */
1356 int_data.interface_statistics = NULL;
1358 g_array_append_val(idb_inf->interface_data, int_data);
1359 g_free(idb_inf_merge_file);
1361 /* Set fake interface Id in per file data */
1362 in_files[i].interface_id = i;
1365 pdh = wtap_dump_fdopen_ng(out_fd, file_type,
1366 selected_frame_type,
1367 merge_max_snapshot_length(in_file_count, in_files),
1368 FALSE /* compressed */, shb_hdr, idb_inf /* wtapng_iface_descriptions_t *idb_inf */, &open_err);
1372 merge_close_in_files(in_file_count, in_files);
1374 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1381 pdh = wtap_dump_fdopen(out_fd, file_type,
1382 selected_frame_type,
1383 merge_max_snapshot_length(in_file_count, in_files),
1384 FALSE /* compressed */, &open_err);
1387 merge_close_in_files(in_file_count, in_files);
1389 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1395 /* Get the sum of the sizes of all the files. */
1397 for (i = 0; i < in_file_count; i++)
1398 f_len += in_files[i].size;
1400 /* Update the progress bar when it gets to this value. */
1401 progbar_nextstep = 0;
1402 /* When we reach the value that triggers a progress bar update,
1403 bump that value by this amount. */
1404 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1405 /* Progress so far. */
1409 g_get_current_time(&start_time);
1411 /* do the merge (or append) */
1414 in_file = merge_append_read_packet(in_file_count, in_files, &read_err,
1417 in_file = merge_read_packet(in_file_count, in_files, &read_err,
1419 if (in_file == NULL) {
1424 if (read_err != 0) {
1425 /* I/O error reading from in_file */
1426 got_read_error = TRUE;
1430 /* Get the sum of the data offsets in all of the files. */
1432 for (i = 0; i < in_file_count; i++)
1433 data_offset += in_files[i].data_offset;
1435 /* Create the progress bar if necessary.
1436 We check on every iteration of the loop, so that it takes no
1437 longer than the standard time to create it (otherwise, for a
1438 large file, we might take considerably longer than that standard
1439 time in order to get to the next progress bar step). */
1440 if (progbar == NULL) {
1441 progbar = delayed_create_progress_dlg(NULL, "Merging", "files",
1442 FALSE, &stop_flag, &start_time, progbar_val);
1445 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1446 when we update it, we have to run the GTK+ main loop to get it
1447 to repaint what's pending, and doing so may involve an "ioctl()"
1448 to see if there's any pending input from an X server, and doing
1449 that for every packet can be costly, especially on a big file. */
1450 if (data_offset >= progbar_nextstep) {
1451 /* Get the sum of the seek positions in all of the files. */
1453 for (i = 0; i < in_file_count; i++)
1454 file_pos += wtap_read_so_far(in_files[i].wth);
1455 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1456 if (progbar_val > 1.0f) {
1457 /* Some file probably grew while we were reading it.
1458 That "shouldn't happen", so we'll just clip the progress
1462 if (progbar != NULL) {
1463 g_snprintf(status_str, sizeof(status_str),
1464 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1465 file_pos / 1024, f_len / 1024);
1466 update_progress_dlg(progbar, progbar_val, status_str);
1468 progbar_nextstep += progbar_quantum;
1472 /* Well, the user decided to abort the merge. */
1476 /* If we have WTAP_ENCAP_PER_PACKETend the infiles are of type WTAP_FILE_PCAP
1477 * we need to set the interface id in the paket header = the interface index we used
1478 * in the IDBs interface description for this file(encapsulation type).
1480 if (fake_interface_ids) {
1481 struct wtap_pkthdr *phdr;
1483 phdr = wtap_phdr(in_file->wth);
1484 phdr->interface_id = in_file->interface_id;
1485 phdr->presence_flags = phdr->presence_flags | WTAP_HAS_INTERFACE_ID;
1487 if (!wtap_dump(pdh, wtap_phdr(in_file->wth), wtap_pseudoheader(in_file->wth),
1488 wtap_buf_ptr(in_file->wth), &write_err)) {
1489 got_write_error = TRUE;
1494 /* We're done merging the files; destroy the progress bar if it was created. */
1495 if (progbar != NULL)
1496 destroy_progress_dlg(progbar);
1498 merge_close_in_files(in_file_count, in_files);
1499 if (!got_read_error && !got_write_error) {
1500 if (!wtap_dump_close(pdh, &write_err))
1501 got_write_error = TRUE;
1503 wtap_dump_close(pdh, &close_err);
1505 if (got_read_error) {
1507 * Find the file on which we got the error, and report the error.
1509 for (i = 0; i < in_file_count; i++) {
1510 if (in_files[i].state == GOT_ERROR) {
1511 /* Put up a message box noting that a read failed somewhere along
1513 display_basename = g_filename_display_basename(in_files[i].filename);
1516 case WTAP_ERR_UNSUPPORTED_ENCAP:
1517 simple_error_message_box(
1518 "The capture file %s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1519 display_basename, err_info);
1523 case WTAP_ERR_CANT_READ:
1524 simple_error_message_box(
1525 "An attempt to read from the capture file %s failed for"
1526 " some unknown reason.", display_basename);
1529 case WTAP_ERR_SHORT_READ:
1530 simple_error_message_box(
1531 "The capture file %s appears to have been cut short"
1532 " in the middle of a packet.", display_basename);
1535 case WTAP_ERR_BAD_FILE:
1536 simple_error_message_box(
1537 "The capture file %s appears to be damaged or corrupt.\n(%s)",
1538 display_basename, err_info);
1542 case WTAP_ERR_DECOMPRESS:
1543 simple_error_message_box(
1544 "The compressed capture file %s appears to be damaged or corrupt.\n"
1545 "(%s)", display_basename, err_info);
1550 simple_error_message_box(
1551 "An error occurred while reading the"
1552 " capture file %s: %s.",
1553 display_basename, wtap_strerror(read_err));
1556 g_free(display_basename);
1561 if (got_write_error) {
1562 /* Put up an alert box for the write error. */
1563 if (write_err < 0) {
1564 /* Wiretap error. */
1565 switch (write_err) {
1567 case WTAP_ERR_UNSUPPORTED_ENCAP:
1569 * This is a problem with the particular frame we're writing;
1570 * note that, and give the frame number.
1572 display_basename = g_filename_display_basename(in_file->filename);
1573 simple_error_message_box(
1574 "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.",
1575 in_file->packet_num, display_basename,
1576 wtap_file_type_string(file_type));
1577 g_free(display_basename);
1581 display_basename = g_filename_display_basename(out_filename);
1582 simple_error_message_box(
1583 "An error occurred while writing to the file \"%s\": %s.",
1584 out_filename, wtap_strerror(write_err));
1585 g_free(display_basename);
1590 write_failure_alert_box(out_filename, write_err);
1594 if (got_read_error || got_write_error || stop_flag) {
1595 /* Callers aren't expected to treat an error or an explicit abort
1596 differently - we put up error dialogs ourselves, so they don't
1604 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1606 const char *filter_new = dftext ? dftext : "";
1607 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1609 GTimeVal start_time;
1611 /* if new filter equals old one, do nothing unless told to do so */
1612 if (!force && strcmp(filter_new, filter_old) == 0) {
1618 if (dftext == NULL) {
1619 /* The new filter is an empty filter (i.e., display all packets).
1620 * so leave dfcode==NULL
1624 * We have a filter; make a copy of it (as we'll be saving it),
1625 * and try to compile it.
1627 dftext = g_strdup(dftext);
1628 if (!dfilter_compile(dftext, &dfcode)) {
1629 /* The attempt failed; report an error. */
1630 simple_message_box(ESD_TYPE_ERROR, NULL,
1631 "See the help for a description of the display filter syntax.",
1632 "\"%s\" isn't a valid display filter: %s",
1633 dftext, dfilter_error_msg);
1639 if (dfcode == NULL) {
1640 /* Yes - free the filter text, and set it to null. */
1646 /* We have a valid filter. Replace the current filter. */
1647 g_free(cf->dfilter);
1648 cf->dfilter = dftext;
1649 g_get_current_time(&start_time);
1652 /* Now rescan the packet list, applying the new filter, but not
1653 throwing away information constructed on a previous pass. */
1654 if (dftext == NULL) {
1655 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1657 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1660 /* Cleanup and release all dfilter resources */
1661 dfilter_free(dfcode);
1667 cf_reftime_packets(capture_file *cf)
1669 ref_time_packets(cf);
1673 cf_redissect_packets(capture_file *cf)
1675 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1679 cf_read_frame_r(capture_file *cf, frame_data *fdata,
1680 union wtap_pseudo_header *pseudo_header, guint8 *pd)
1684 gchar *display_basename;
1686 #ifdef WANT_PACKET_EDITOR
1687 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1688 if (G_UNLIKELY(fdata->file_off == -1)) {
1689 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1692 simple_error_message_box("fdata->file_off == -1, but can't find modified frame!");
1696 *pseudo_header = frame->ph;
1697 memcpy(pd, frame->pd, fdata->cap_len);
1702 if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
1703 fdata->cap_len, &err, &err_info)) {
1704 display_basename = g_filename_display_basename(cf->filename);
1707 case WTAP_ERR_UNSUPPORTED_ENCAP:
1708 simple_error_message_box("The file \"%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1709 display_basename, err_info);
1713 case WTAP_ERR_BAD_FILE:
1714 simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)",
1715 display_basename, wtap_strerror(err), err_info);
1720 simple_error_message_box(
1721 "An error occurred while reading from the file \"%s\": %s.",
1722 display_basename, wtap_strerror(err));
1725 g_free(display_basename);
1732 cf_read_frame(capture_file *cf, frame_data *fdata)
1734 return cf_read_frame_r(cf, fdata, &cf->pseudo_header, cf->pd);
1737 /* Rescan the list of packets, reconstructing the CList.
1739 "action" describes why we're doing this; it's used in the progress
1742 "action_item" describes what we're doing; it's used in the progress
1745 "refilter" is TRUE if we need to re-evaluate the filter expression.
1747 "redissect" is TRUE if we need to make the dissectors reconstruct
1748 any state information they have (because a preference that affects
1749 some dissector has changed, meaning some dissector might construct
1750 its state differently from the way it was constructed the last time). */
1752 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1753 gboolean refilter, gboolean redissect)
1755 /* Rescan packets new packet list */
1758 progdlg_t *progbar = NULL;
1761 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1762 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1763 gboolean selected_frame_seen;
1765 GTimeVal start_time;
1766 gchar status_str[100];
1767 int progbar_nextstep;
1768 int progbar_quantum;
1770 gboolean filtering_tap_listeners;
1772 gboolean add_to_packet_list = FALSE;
1775 /* Compile the current display filter.
1776 * We assume this will not fail since cf->dfilter is only set in
1777 * cf_filter IFF the filter was valid.
1779 compiled = dfilter_compile(cf->dfilter, &dfcode);
1780 g_assert(!cf->dfilter || (compiled && dfcode));
1782 /* Do we have any tap listeners with filters? */
1783 filtering_tap_listeners = have_filtering_tap_listeners();
1785 /* Get the union of the flags for all tap listeners. */
1786 tap_flags = union_of_tap_listener_flags();
1788 reset_tap_listeners();
1789 /* Which frame, if any, is the currently selected frame?
1790 XXX - should the selected frame or the focus frame be the "current"
1791 frame, that frame being the one from which "Find Frame" searches
1793 selected_frame = cf->current_frame;
1795 /* Mark frame num as not found */
1796 selected_frame_num = -1;
1798 /* Freeze the packet list while we redo it, so we don't get any
1799 screen updates while it happens. */
1800 packet_list_freeze();
1803 /* We need to re-initialize all the state information that protocols
1804 keep, because some preference that controls a dissector has changed,
1805 which might cause the state information to be constructed differently
1806 by that dissector. */
1808 /* We might receive new packets while redissecting, and we don't
1809 want to dissect those before their time. */
1810 cf->redissecting = TRUE;
1812 /* Cleanup all data structures used for dissection. */
1813 cleanup_dissection();
1814 /* Initialize all data structures used for dissection. */
1817 /* We need to redissect the packets so we have to discard our old
1818 * packet list store. */
1819 packet_list_clear();
1820 add_to_packet_list = TRUE;
1823 /* We don't yet know which will be the first and last frames displayed. */
1824 cf->first_displayed = 0;
1825 cf->last_displayed = 0;
1827 /* We currently don't display any packets */
1828 cf->displayed_count = 0;
1830 /* Iterate through the list of frames. Call a routine for each frame
1831 to check whether it should be displayed and, if so, add it to
1832 the display list. */
1833 nstime_set_unset(&first_ts);
1834 nstime_set_unset(&prev_dis_ts);
1835 nstime_set_unset(&prev_cap_ts);
1838 /* Update the progress bar when it gets to this value. */
1839 progbar_nextstep = 0;
1840 /* When we reach the value that triggers a progress bar update,
1841 bump that value by this amount. */
1842 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1843 /* Count of packets at which we've looked. */
1845 /* Progress so far. */
1849 g_get_current_time(&start_time);
1851 /* no previous row yet */
1852 prev_frame_num = -1;
1855 preceding_frame_num = -1;
1856 preceding_frame = NULL;
1857 following_frame_num = -1;
1858 following_frame = NULL;
1860 selected_frame_seen = FALSE;
1862 for (framenum = 1; framenum <= cf->count; framenum++) {
1863 fdata = frame_data_sequence_find(cf->frames, framenum);
1865 /* Create the progress bar if necessary.
1866 We check on every iteration of the loop, so that it takes no
1867 longer than the standard time to create it (otherwise, for a
1868 large file, we might take considerably longer than that standard
1869 time in order to get to the next progress bar step). */
1870 if (progbar == NULL)
1871 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1872 &stop_flag, &start_time,
1875 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1876 when we update it, we have to run the GTK+ main loop to get it
1877 to repaint what's pending, and doing so may involve an "ioctl()"
1878 to see if there's any pending input from an X server, and doing
1879 that for every packet can be costly, especially on a big file. */
1880 if (count >= progbar_nextstep) {
1881 /* let's not divide by zero. I should never be started
1882 * with count == 0, so let's assert that
1884 g_assert(cf->count > 0);
1885 progbar_val = (gfloat) count / cf->count;
1887 if (progbar != NULL) {
1888 g_snprintf(status_str, sizeof(status_str),
1889 "%4u of %u frames", count, cf->count);
1890 update_progress_dlg(progbar, progbar_val, status_str);
1893 progbar_nextstep += progbar_quantum;
1897 /* Well, the user decided to abort the filtering. Just stop.
1899 XXX - go back to the previous filter? Users probably just
1900 want not to wait for a filtering operation to finish;
1901 unless we cancel by having no filter, reverting to the
1902 previous filter will probably be even more expensive than
1903 continuing the filtering, as it involves going back to the
1904 beginning and filtering, and even with no filter we currently
1905 have to re-generate the entire clist, which is also expensive.
1907 I'm not sure what Network Monitor does, but it doesn't appear
1908 to give you an unfiltered display if you cancel. */
1915 /* Since all state for the frame was destroyed, mark the frame
1916 * as not visited, free the GSList referring to the state
1917 * data (the per-frame data itself was freed by
1918 * "init_dissection()"), and null out the GSList pointer. */
1919 fdata->flags.visited = 0;
1920 frame_data_cleanup(fdata);
1923 if (redissect || refilter) {
1924 /* If we're redissecting or refiltering then any frame dependencies
1925 * from the previous dissection/filtering are no longer valid.
1927 fdata->flags.dependent_of_displayed = 0;
1930 if (!cf_read_frame(cf, fdata))
1931 break; /* error reading the frame */
1933 /* If the previous frame is displayed, and we haven't yet seen the
1934 selected frame, remember that frame - it's the closest one we've
1935 yet seen before the selected frame. */
1936 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1937 preceding_frame_num = prev_frame_num;
1938 preceding_frame = prev_frame;
1940 add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1941 tap_flags, &cf->pseudo_header, cf->pd,
1943 add_to_packet_list);
1945 /* If this frame is displayed, and this is the first frame we've
1946 seen displayed after the selected frame, remember this frame -
1947 it's the closest one we've yet seen at or after the selected
1949 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1950 following_frame_num = fdata->num;
1951 following_frame = fdata;
1953 if (fdata == selected_frame) {
1954 selected_frame_seen = TRUE;
1955 if (fdata->flags.passed_dfilter)
1956 selected_frame_num = fdata->num;
1959 /* Remember this frame - it'll be the previous frame
1960 on the next pass through the loop. */
1961 prev_frame_num = fdata->num;
1965 /* We are done redissecting the packet list. */
1966 cf->redissecting = FALSE;
1969 /* Clear out what remains of the visited flags and per-frame data
1972 XXX - that may cause various forms of bogosity when dissecting
1973 these frames, as they won't have been seen by this sequential
1974 pass, but the only alternative I see is to keep scanning them
1975 even though the user requested that the scan stop, and that
1976 would leave the user stuck with an Wireshark grinding on
1977 until it finishes. Should we just stick them with that? */
1978 for (; framenum <= cf->count; framenum++) {
1979 fdata = frame_data_sequence_find(cf->frames, framenum);
1980 fdata->flags.visited = 0;
1981 frame_data_cleanup(fdata);
1985 /* We're done filtering the packets; destroy the progress bar if it
1987 if (progbar != NULL)
1988 destroy_progress_dlg(progbar);
1990 /* Unfreeze the packet list. */
1991 if (!add_to_packet_list)
1992 packet_list_recreate_visible_rows();
1994 /* Compute the time it took to filter the file */
1995 compute_elapsed(&start_time);
1999 if (selected_frame_num == -1) {
2000 /* The selected frame didn't pass the filter. */
2001 if (selected_frame == NULL) {
2002 /* That's because there *was* no selected frame. Make the first
2003 displayed frame the current frame. */
2004 selected_frame_num = 0;
2006 /* Find the nearest displayed frame to the selected frame (whether
2007 it's before or after that frame) and make that the current frame.
2008 If the next and previous displayed frames are equidistant from the
2009 selected frame, choose the next one. */
2010 g_assert(following_frame == NULL ||
2011 following_frame->num >= selected_frame->num);
2012 g_assert(preceding_frame == NULL ||
2013 preceding_frame->num <= selected_frame->num);
2014 if (following_frame == NULL) {
2015 /* No frame after the selected frame passed the filter, so we
2016 have to select the last displayed frame before the selected
2018 selected_frame_num = preceding_frame_num;
2019 selected_frame = preceding_frame;
2020 } else if (preceding_frame == NULL) {
2021 /* No frame before the selected frame passed the filter, so we
2022 have to select the first displayed frame after the selected
2024 selected_frame_num = following_frame_num;
2025 selected_frame = following_frame;
2027 /* Frames before and after the selected frame passed the filter, so
2028 we'll select the previous frame */
2029 selected_frame_num = preceding_frame_num;
2030 selected_frame = preceding_frame;
2035 if (selected_frame_num == -1) {
2036 /* There are no frames displayed at all. */
2037 cf_unselect_packet(cf);
2039 /* Either the frame that was selected passed the filter, or we've
2040 found the nearest displayed frame to that frame. Select it, make
2041 it the focus row, and make it visible. */
2042 /* Set to invalid to force update of packet list and packet details */
2043 cf->current_row = -1;
2044 if (selected_frame_num == 0) {
2045 packet_list_select_first_row();
2047 if (!packet_list_select_row_from_data(selected_frame)) {
2048 /* We didn't find a row corresponding to this frame.
2049 This means that the frame isn't being displayed currently,
2050 so we can't select it. */
2051 simple_message_box(ESD_TYPE_INFO, NULL,
2052 "The capture file is probably not fully dissected.",
2053 "End of capture exceeded!");
2058 /* Cleanup and release all dfilter resources */
2059 dfilter_free(dfcode);
2064 * Scan trough all frame data and recalculate the ref time
2065 * without rereading the file.
2066 * XXX - do we need a progres bar or is this fast enough?
2069 ref_time_packets(capture_file *cf)
2074 nstime_set_unset(&first_ts);
2075 nstime_set_unset(&prev_dis_ts);
2078 for (framenum = 1; framenum <= cf->count; framenum++) {
2079 fdata = frame_data_sequence_find(cf->frames, framenum);
2081 /* just add some value here until we know if it is being displayed or not */
2082 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
2088 /* If we don't have the time stamp of the first packet in the
2089 capture, it's because this is the first packet. Save the time
2090 stamp of this packet as the time stamp of the first packet. */
2091 if (nstime_is_unset(&first_ts)) {
2092 first_ts = fdata->abs_ts;
2094 /* if this frames is marked as a reference time frame, reset
2095 firstsec and firstusec to this frame */
2096 if (fdata->flags.ref_time) {
2097 first_ts = fdata->abs_ts;
2100 /* If we don't have the time stamp of the previous displayed packet,
2101 it's because this is the first displayed packet. Save the time
2102 stamp of this packet as the time stamp of the previous displayed
2104 if (nstime_is_unset(&prev_dis_ts)) {
2105 prev_dis_ts = fdata->abs_ts;
2108 /* Get the time elapsed between the first packet and this packet. */
2109 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
2111 /* If it's greater than the current elapsed time, set the elapsed time
2112 to it (we check for "greater than" so as not to be confused by
2113 time moving backwards). */
2114 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
2115 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
2116 cf->elapsed_time = fdata->rel_ts;
2119 /* If this frame is displayed, get the time elapsed between the
2120 previous displayed packet and this packet. */
2121 if ( fdata->flags.passed_dfilter ) {
2122 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
2123 prev_dis_ts = fdata->abs_ts;
2129 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
2130 /* This frame either passed the display filter list or is marked as
2131 a time reference frame. All time reference frames are displayed
2132 even if they dont pass the display filter */
2133 if (fdata->flags.ref_time) {
2134 /* if this was a TIME REF frame we should reset the cum_bytes field */
2135 cum_bytes = fdata->pkt_len;
2136 fdata->cum_bytes = cum_bytes;
2138 /* increase cum_bytes with this packets length */
2139 cum_bytes += fdata->pkt_len;
2152 process_specified_packets(capture_file *cf, packet_range_t *range,
2153 const char *string1, const char *string2, gboolean terminate_is_stop,
2154 gboolean (*callback)(capture_file *, frame_data *,
2155 union wtap_pseudo_header *, const guint8 *, void *),
2156 void *callback_args)
2158 union wtap_pseudo_header pseudo_header;
2162 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
2163 psp_return_t ret = PSP_FINISHED;
2165 progdlg_t *progbar = NULL;
2168 gboolean progbar_stop_flag;
2169 GTimeVal progbar_start_time;
2170 gchar progbar_status_str[100];
2171 int progbar_nextstep;
2172 int progbar_quantum;
2173 range_process_e process_this;
2175 /* Update the progress bar when it gets to this value. */
2176 progbar_nextstep = 0;
2177 /* When we reach the value that triggers a progress bar update,
2178 bump that value by this amount. */
2179 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2180 /* Count of packets at which we've looked. */
2182 /* Progress so far. */
2185 progbar_stop_flag = FALSE;
2186 g_get_current_time(&progbar_start_time);
2189 packet_range_process_init(range);
2191 /* Iterate through all the packets, printing the packets that
2192 were selected by the current display filter. */
2193 for (framenum = 1; framenum <= cf->count; framenum++) {
2194 fdata = frame_data_sequence_find(cf->frames, framenum);
2196 /* Create the progress bar if necessary.
2197 We check on every iteration of the loop, so that it takes no
2198 longer than the standard time to create it (otherwise, for a
2199 large file, we might take considerably longer than that standard
2200 time in order to get to the next progress bar step). */
2201 if (progbar == NULL)
2202 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2205 &progbar_start_time,
2208 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2209 when we update it, we have to run the GTK+ main loop to get it
2210 to repaint what's pending, and doing so may involve an "ioctl()"
2211 to see if there's any pending input from an X server, and doing
2212 that for every packet can be costly, especially on a big file. */
2213 if (progbar_count >= progbar_nextstep) {
2214 /* let's not divide by zero. I should never be started
2215 * with count == 0, so let's assert that
2217 g_assert(cf->count > 0);
2218 progbar_val = (gfloat) progbar_count / cf->count;
2220 if (progbar != NULL) {
2221 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2222 "%4u of %u packets", progbar_count, cf->count);
2223 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2226 progbar_nextstep += progbar_quantum;
2229 if (progbar_stop_flag) {
2230 /* Well, the user decided to abort the operation. Just stop,
2231 and arrange to return PSP_STOPPED to our caller, so they know
2232 it was stopped explicitly. */
2239 if (range != NULL) {
2240 /* do we have to process this packet? */
2241 process_this = packet_range_process_packet(range, fdata);
2242 if (process_this == range_process_next) {
2243 /* this packet uninteresting, continue with next one */
2245 } else if (process_this == range_processing_finished) {
2246 /* all interesting packets processed, stop the loop */
2251 /* Get the packet */
2252 if (!cf_read_frame_r(cf, fdata, &pseudo_header, pd)) {
2253 /* Attempt to get the packet failed. */
2257 /* Process the packet */
2258 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
2259 /* Callback failed. We assume it reported the error appropriately. */
2265 /* We're done printing the packets; destroy the progress bar if
2267 if (progbar != NULL)
2268 destroy_progress_dlg(progbar);
2274 gboolean construct_protocol_tree;
2276 } retap_callback_args_t;
2279 retap_packet(capture_file *cf _U_, frame_data *fdata,
2280 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2283 retap_callback_args_t *args = argsp;
2286 epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
2287 tap_queue_init(&edt);
2288 epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
2289 tap_push_tapped_queue(&edt);
2290 epan_dissect_cleanup(&edt);
2296 cf_retap_packets(capture_file *cf)
2298 packet_range_t range;
2299 retap_callback_args_t callback_args;
2300 gboolean filtering_tap_listeners;
2303 /* Do we have any tap listeners with filters? */
2304 filtering_tap_listeners = have_filtering_tap_listeners();
2306 tap_flags = union_of_tap_listener_flags();
2308 /* If any tap listeners have filters, or require the protocol tree,
2309 construct the protocol tree. */
2310 callback_args.construct_protocol_tree = filtering_tap_listeners ||
2311 (tap_flags & TL_REQUIRES_PROTO_TREE);
2313 /* If any tap listeners require the columns, construct them. */
2314 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2316 /* Reset the tap listeners. */
2317 reset_tap_listeners();
2319 /* Iterate through the list of packets, dissecting all packets and
2320 re-running the taps. */
2321 packet_range_init(&range);
2322 packet_range_process_init(&range);
2323 switch (process_specified_packets(cf, &range, "Recalculating statistics on",
2324 "all packets", TRUE, retap_packet,
2327 /* Completed successfully. */
2331 /* Well, the user decided to abort the refiltering.
2332 Return CF_READ_ABORTED so our caller knows they did that. */
2333 return CF_READ_ABORTED;
2336 /* Error while retapping. */
2337 return CF_READ_ERROR;
2340 g_assert_not_reached();
2345 print_args_t *print_args;
2346 gboolean print_header_line;
2347 char *header_line_buf;
2348 int header_line_buf_len;
2349 gboolean print_formfeed;
2350 gboolean print_separator;
2354 int num_visible_cols;
2356 } print_callback_args_t;
2359 print_packet(capture_file *cf, frame_data *fdata,
2360 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2363 print_callback_args_t *args = argsp;
2370 gboolean proto_tree_needed;
2371 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2372 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2374 /* Create the protocol tree, and make it visible, if we're printing
2375 the dissection or the hex data.
2376 XXX - do we need it if we're just printing the hex data? */
2378 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2379 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2381 /* Fill in the column information if we're printing the summary
2383 if (args->print_args->print_summary) {
2384 col_custom_prime_edt(&edt, &cf->cinfo);
2385 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2386 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2388 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2390 if (args->print_formfeed) {
2391 if (!new_page(args->print_args->stream))
2394 if (args->print_separator) {
2395 if (!print_line(args->print_args->stream, 0, ""))
2401 * We generate bookmarks, if the output format supports them.
2402 * The name is "__frameN__".
2404 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2406 if (args->print_args->print_summary) {
2407 if (args->print_header_line) {
2408 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2410 args->print_header_line = FALSE; /* we might not need to print any more */
2412 cp = &args->line_buf[0];
2414 for (i = 0; i < args->num_visible_cols; i++) {
2415 /* Find the length of the string for this column. */
2416 column_len = (int) strlen(cf->cinfo.col_data[args->visible_cols[i]]);
2417 if (args->col_widths[i] > column_len)
2418 column_len = args->col_widths[i];
2420 /* Make sure there's room in the line buffer for the column; if not,
2421 double its length. */
2422 line_len += column_len + 1; /* "+1" for space */
2423 if (line_len > args->line_buf_len) {
2424 cp_off = (int) (cp - args->line_buf);
2425 args->line_buf_len = 2 * line_len;
2426 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2427 cp = args->line_buf + cp_off;
2430 /* Right-justify the packet number column. */
2431 if (cf->cinfo.col_fmt[args->visible_cols[i]] == COL_NUMBER)
2432 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
2434 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
2436 if (i != args->num_visible_cols - 1)
2442 * Generate a bookmark, using the summary line as the title.
2444 if (!print_bookmark(args->print_args->stream, bookmark_name,
2448 if (!print_line(args->print_args->stream, 0, args->line_buf))
2452 * Generate a bookmark, using "Frame N" as the title, as we're not
2453 * printing the summary line.
2455 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2456 if (!print_bookmark(args->print_args->stream, bookmark_name,
2459 } /* if (print_summary) */
2461 if (args->print_args->print_dissections != print_dissections_none) {
2462 if (args->print_args->print_summary) {
2463 /* Separate the summary line from the tree with a blank line. */
2464 if (!print_line(args->print_args->stream, 0, ""))
2468 /* Print the information in that tree. */
2469 if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
2472 /* Print a blank line if we print anything after this (aka more than one packet). */
2473 args->print_separator = TRUE;
2475 /* Print a header line if we print any more packet summaries */
2476 args->print_header_line = TRUE;
2479 if (args->print_args->print_hex) {
2480 /* Print the full packet data as hex. */
2481 if (!print_hex_data(args->print_args->stream, &edt))
2484 /* Print a blank line if we print anything after this (aka more than one packet). */
2485 args->print_separator = TRUE;
2487 /* Print a header line if we print any more packet summaries */
2488 args->print_header_line = TRUE;
2489 } /* if (args->print_args->print_dissections != print_dissections_none) */
2491 epan_dissect_cleanup(&edt);
2493 /* do we want to have a formfeed between each packet from now on? */
2494 if (args->print_args->print_formfeed) {
2495 args->print_formfeed = TRUE;
2501 epan_dissect_cleanup(&edt);
2506 cf_print_packets(capture_file *cf, print_args_t *print_args)
2508 print_callback_args_t callback_args;
2511 int i, cp_off, column_len, line_len;
2512 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2517 callback_args.print_args = print_args;
2518 callback_args.print_header_line = TRUE;
2519 callback_args.header_line_buf = NULL;
2520 callback_args.header_line_buf_len = 256;
2521 callback_args.print_formfeed = FALSE;
2522 callback_args.print_separator = FALSE;
2523 callback_args.line_buf = NULL;
2524 callback_args.line_buf_len = 256;
2525 callback_args.col_widths = NULL;
2526 callback_args.num_visible_cols = 0;
2527 callback_args.visible_cols = NULL;
2529 if (!print_preamble(print_args->stream, cf->filename)) {
2530 destroy_print_stream(print_args->stream);
2531 return CF_PRINT_WRITE_ERROR;
2534 if (print_args->print_summary) {
2535 /* We're printing packet summaries. Allocate the header line buffer
2536 and get the column widths. */
2537 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2539 /* Find the number of visible columns and the last visible column */
2540 for (i = 0; i < prefs.num_cols; i++) {
2542 clp = g_list_nth(prefs.col_list, i);
2543 if (clp == NULL) /* Sanity check, Invalid column requested */
2546 cfmt = (fmt_data *) clp->data;
2547 if (cfmt->visible) {
2549 last_visible_col = i;
2553 /* Find the widths for each of the columns - maximum of the
2554 width of the title and the width of the data - and construct
2555 a buffer with a line containing the column titles. */
2556 callback_args.num_visible_cols = num_visible_col;
2557 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2558 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2559 cp = &callback_args.header_line_buf[0];
2561 visible_col_count = 0;
2562 for (i = 0; i < cf->cinfo.num_cols; i++) {
2564 clp = g_list_nth(prefs.col_list, i);
2565 if (clp == NULL) /* Sanity check, Invalid column requested */
2568 cfmt = (fmt_data *) clp->data;
2569 if (cfmt->visible == FALSE)
2572 /* Save the order of visible columns */
2573 callback_args.visible_cols[visible_col_count] = i;
2575 /* Don't pad the last column. */
2576 if (i == last_visible_col)
2577 callback_args.col_widths[visible_col_count] = 0;
2579 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.col_title[i]);
2580 data_width = get_column_char_width(get_column_format(i));
2581 if (data_width > callback_args.col_widths[visible_col_count])
2582 callback_args.col_widths[visible_col_count] = data_width;
2585 /* Find the length of the string for this column. */
2586 column_len = (int) strlen(cf->cinfo.col_title[i]);
2587 if (callback_args.col_widths[i] > column_len)
2588 column_len = callback_args.col_widths[visible_col_count];
2590 /* Make sure there's room in the line buffer for the column; if not,
2591 double its length. */
2592 line_len += column_len + 1; /* "+1" for space */
2593 if (line_len > callback_args.header_line_buf_len) {
2594 cp_off = (int) (cp - callback_args.header_line_buf);
2595 callback_args.header_line_buf_len = 2 * line_len;
2596 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2597 callback_args.header_line_buf_len + 1);
2598 cp = callback_args.header_line_buf + cp_off;
2601 /* Right-justify the packet number column. */
2602 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2603 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
2605 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
2607 if (i != cf->cinfo.num_cols - 1)
2610 visible_col_count++;
2614 /* Now start out the main line buffer with the same length as the
2615 header line buffer. */
2616 callback_args.line_buf_len = callback_args.header_line_buf_len;
2617 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2618 } /* if (print_summary) */
2620 /* Iterate through the list of packets, printing the packets we were
2622 ret = process_specified_packets(cf, &print_args->range, "Printing",
2623 "selected packets", TRUE, print_packet,
2626 g_free(callback_args.header_line_buf);
2627 g_free(callback_args.line_buf);
2628 g_free(callback_args.col_widths);
2629 g_free(callback_args.visible_cols);
2634 /* Completed successfully. */
2638 /* Well, the user decided to abort the printing.
2640 XXX - note that what got generated before they did that
2641 will get printed if we're piping to a print program; we'd
2642 have to write to a file and then hand that to the print
2643 program to make it actually not print anything. */
2647 /* Error while printing.
2649 XXX - note that what got generated before they did that
2650 will get printed if we're piping to a print program; we'd
2651 have to write to a file and then hand that to the print
2652 program to make it actually not print anything. */
2653 destroy_print_stream(print_args->stream);
2654 return CF_PRINT_WRITE_ERROR;
2657 if (!print_finale(print_args->stream)) {
2658 destroy_print_stream(print_args->stream);
2659 return CF_PRINT_WRITE_ERROR;
2662 if (!destroy_print_stream(print_args->stream))
2663 return CF_PRINT_WRITE_ERROR;
2669 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2670 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2676 /* Create the protocol tree, but don't fill in the column information. */
2677 epan_dissect_init(&edt, TRUE, TRUE);
2678 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2680 /* Write out the information in that tree. */
2681 proto_tree_write_pdml(&edt, fh);
2683 epan_dissect_cleanup(&edt);
2689 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2694 fh = ws_fopen(print_args->file, "w");
2696 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2698 write_pdml_preamble(fh, cf->filename);
2701 return CF_PRINT_WRITE_ERROR;
2704 /* Iterate through the list of packets, printing the packets we were
2706 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2707 "selected packets", TRUE,
2708 write_pdml_packet, fh);
2713 /* Completed successfully. */
2717 /* Well, the user decided to abort the printing. */
2721 /* Error while printing. */
2723 return CF_PRINT_WRITE_ERROR;
2726 write_pdml_finale(fh);
2729 return CF_PRINT_WRITE_ERROR;
2732 /* XXX - check for an error */
2739 write_psml_packet(capture_file *cf, frame_data *fdata,
2740 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2745 gboolean proto_tree_needed;
2747 /* Fill in the column information, only create the protocol tree
2748 if having custom columns. */
2749 proto_tree_needed = have_custom_cols(&cf->cinfo);
2750 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2751 col_custom_prime_edt(&edt, &cf->cinfo);
2752 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2753 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2755 /* Write out the information in that tree. */
2756 proto_tree_write_psml(&edt, fh);
2758 epan_dissect_cleanup(&edt);
2764 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2769 fh = ws_fopen(print_args->file, "w");
2771 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2773 write_psml_preamble(fh);
2776 return CF_PRINT_WRITE_ERROR;
2779 /* Iterate through the list of packets, printing the packets we were
2781 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2782 "selected packets", TRUE,
2783 write_psml_packet, fh);
2788 /* Completed successfully. */
2792 /* Well, the user decided to abort the printing. */
2796 /* Error while printing. */
2798 return CF_PRINT_WRITE_ERROR;
2801 write_psml_finale(fh);
2804 return CF_PRINT_WRITE_ERROR;
2807 /* XXX - check for an error */
2814 write_csv_packet(capture_file *cf, frame_data *fdata,
2815 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2820 gboolean proto_tree_needed;
2822 /* Fill in the column information, only create the protocol tree
2823 if having custom columns. */
2824 proto_tree_needed = have_custom_cols(&cf->cinfo);
2825 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2826 col_custom_prime_edt(&edt, &cf->cinfo);
2827 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2828 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2830 /* Write out the information in that tree. */
2831 proto_tree_write_csv(&edt, fh);
2833 epan_dissect_cleanup(&edt);
2839 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2844 fh = ws_fopen(print_args->file, "w");
2846 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2848 write_csv_preamble(fh);
2851 return CF_PRINT_WRITE_ERROR;
2854 /* Iterate through the list of packets, printing the packets we were
2856 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2857 "selected packets", TRUE,
2858 write_csv_packet, fh);
2863 /* Completed successfully. */
2867 /* Well, the user decided to abort the printing. */
2871 /* Error while printing. */
2873 return CF_PRINT_WRITE_ERROR;
2876 write_csv_finale(fh);
2879 return CF_PRINT_WRITE_ERROR;
2882 /* XXX - check for an error */
2889 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
2890 union wtap_pseudo_header *pseudo_header,
2891 const guint8 *pd, void *argsp)
2896 epan_dissect_init(&edt, TRUE, TRUE);
2897 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2898 proto_tree_write_carrays(fdata->num, fh, &edt);
2899 epan_dissect_cleanup(&edt);
2905 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2910 fh = ws_fopen(print_args->file, "w");
2913 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2915 write_carrays_preamble(fh);
2919 return CF_PRINT_WRITE_ERROR;
2922 /* Iterate through the list of packets, printing the packets we were
2924 ret = process_specified_packets(cf, &print_args->range,
2926 "selected packets", TRUE,
2927 write_carrays_packet, fh);
2930 /* Completed successfully. */
2933 /* Well, the user decided to abort the printing. */
2936 /* Error while printing. */
2938 return CF_PRINT_WRITE_ERROR;
2941 write_carrays_finale(fh);
2945 return CF_PRINT_WRITE_ERROR;
2953 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2954 search_direction dir)
2958 mdata.string = string;
2959 mdata.string_len = strlen(string);
2960 return find_packet(cf, match_protocol_tree, &mdata, dir);
2964 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2966 mdata->frame_matched = FALSE;
2967 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2968 mdata->string_len = strlen(mdata->string);
2970 /* Iterate through all the nodes looking for matching text */
2971 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2972 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2976 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2978 match_data *mdata = criterion;
2981 /* Load the frame's data. */
2982 if (!cf_read_frame(cf, fdata)) {
2983 /* Attempt to get the packet failed. */
2987 /* Construct the protocol tree, including the displayed text */
2988 epan_dissect_init(&edt, TRUE, TRUE);
2989 /* We don't need the column information */
2990 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2992 /* Iterate through all the nodes, seeing if they have text that matches. */
2994 mdata->frame_matched = FALSE;
2995 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2996 epan_dissect_cleanup(&edt);
2997 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3001 match_subtree_text(proto_node *node, gpointer data)
3003 match_data *mdata = (match_data *) data;
3004 const gchar *string = mdata->string;
3005 size_t string_len = mdata->string_len;
3006 capture_file *cf = mdata->cf;
3007 field_info *fi = PNODE_FINFO(node);
3008 gchar label_str[ITEM_LABEL_LENGTH];
3015 /* dissection with an invisible proto tree? */
3018 if (mdata->frame_matched) {
3019 /* We already had a match; don't bother doing any more work. */
3023 /* Don't match invisible entries. */
3024 if (PROTO_ITEM_IS_HIDDEN(node))
3027 /* was a free format label produced? */
3029 label_ptr = fi->rep->representation;
3031 /* no, make a generic label */
3032 label_ptr = label_str;
3033 proto_item_fill_label(fi, label_str);
3036 /* Does that label match? */
3037 label_len = strlen(label_ptr);
3038 for (i = 0; i < label_len; i++) {
3039 c_char = label_ptr[i];
3041 c_char = toupper(c_char);
3042 if (c_char == string[c_match]) {
3044 if (c_match == string_len) {
3045 /* No need to look further; we have a match */
3046 mdata->frame_matched = TRUE;
3054 /* Recurse into the subtree, if it exists */
3055 if (node->first_child != NULL)
3056 proto_tree_children_foreach(node, match_subtree_text, mdata);
3060 cf_find_packet_summary_line(capture_file *cf, const char *string,
3061 search_direction dir)
3065 mdata.string = string;
3066 mdata.string_len = strlen(string);
3067 return find_packet(cf, match_summary_line, &mdata, dir);
3071 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3073 match_data *mdata = criterion;
3074 const gchar *string = mdata->string;
3075 size_t string_len = mdata->string_len;
3077 const char *info_column;
3078 size_t info_column_len;
3079 match_result result = MR_NOTMATCHED;
3085 /* Load the frame's data. */
3086 if (!cf_read_frame(cf, fdata)) {
3087 /* Attempt to get the packet failed. */
3091 /* Don't bother constructing the protocol tree */
3092 epan_dissect_init(&edt, FALSE, FALSE);
3093 /* Get the column information */
3094 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
3096 /* Find the Info column */
3097 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3098 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
3099 /* Found it. See if we match. */
3100 info_column = edt.pi.cinfo->col_data[colx];
3101 info_column_len = strlen(info_column);
3102 for (i = 0; i < info_column_len; i++) {
3103 c_char = info_column[i];
3105 c_char = toupper(c_char);
3106 if (c_char == string[c_match]) {
3108 if (c_match == string_len) {
3109 result = MR_MATCHED;
3118 epan_dissect_cleanup(&edt);
3125 } cbs_t; /* "Counted byte string" */
3128 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3129 search_direction dir)
3134 info.data_len = string_size;
3136 /* String or hex search? */
3138 /* String search - what type of string? */
3139 switch (cf->scs_type) {
3141 case SCS_ASCII_AND_UNICODE:
3142 return find_packet(cf, match_ascii_and_unicode, &info, dir);
3145 return find_packet(cf, match_ascii, &info, dir);
3148 return find_packet(cf, match_unicode, &info, dir);
3151 g_assert_not_reached();
3155 return find_packet(cf, match_binary, &info, dir);
3159 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3161 cbs_t *info = criterion;
3162 const guint8 *ascii_text = info->data;
3163 size_t textlen = info->data_len;
3164 match_result result;
3170 /* Load the frame's data. */
3171 if (!cf_read_frame(cf, fdata)) {
3172 /* Attempt to get the packet failed. */
3176 result = MR_NOTMATCHED;
3177 buf_len = fdata->pkt_len;
3179 while (i < buf_len) {
3182 c_char = toupper(c_char);
3183 if (c_char != '\0') {
3184 if (c_char == ascii_text[c_match]) {
3186 if (c_match == textlen) {
3187 result = MR_MATCHED;
3188 cf->search_pos = i; /* Save the position of the last character
3189 for highlighting the field. */
3194 g_assert(i>=c_match);
3195 i -= (guint32)c_match;
3205 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
3207 cbs_t *info = criterion;
3208 const guint8 *ascii_text = info->data;
3209 size_t textlen = info->data_len;
3210 match_result result;
3216 /* Load the frame's data. */
3217 if (!cf_read_frame(cf, fdata)) {
3218 /* Attempt to get the packet failed. */
3222 result = MR_NOTMATCHED;
3223 buf_len = fdata->pkt_len;
3225 while (i < buf_len) {
3228 c_char = toupper(c_char);
3229 if (c_char == ascii_text[c_match]) {
3231 if (c_match == textlen) {
3232 result = MR_MATCHED;
3233 cf->search_pos = i; /* Save the position of the last character
3234 for highlighting the field. */
3239 g_assert(i>=c_match);
3240 i -= (guint32)c_match;
3250 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3252 cbs_t *info = criterion;
3253 const guint8 *ascii_text = info->data;
3254 size_t textlen = info->data_len;
3255 match_result result;
3261 /* Load the frame's data. */
3262 if (!cf_read_frame(cf, fdata)) {
3263 /* Attempt to get the packet failed. */
3267 result = MR_NOTMATCHED;
3268 buf_len = fdata->pkt_len;
3270 while (i < buf_len) {
3273 c_char = toupper(c_char);
3274 if (c_char == ascii_text[c_match]) {
3276 if (c_match == textlen) {
3277 result = MR_MATCHED;
3278 cf->search_pos = i; /* Save the position of the last character
3279 for highlighting the field. */
3285 g_assert(i>=(c_match*2));
3286 i -= (guint32)c_match*2;
3295 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3297 cbs_t *info = criterion;
3298 const guint8 *binary_data = info->data;
3299 size_t datalen = info->data_len;
3300 match_result result;
3305 /* Load the frame's data. */
3306 if (!cf_read_frame(cf, fdata)) {
3307 /* Attempt to get the packet failed. */
3311 result = MR_NOTMATCHED;
3312 buf_len = fdata->pkt_len;
3314 while (i < buf_len) {
3315 if (cf->pd[i] == binary_data[c_match]) {
3317 if (c_match == datalen) {
3318 result = MR_MATCHED;
3319 cf->search_pos = i; /* Save the position of the last character
3320 for highlighting the field. */
3325 g_assert(i>=c_match);
3326 i -= (guint32)c_match;
3335 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3336 search_direction dir)
3338 return find_packet(cf, match_dfilter, sfcode, dir);
3342 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3343 search_direction dir)
3348 if (!dfilter_compile(filter, &sfcode)) {
3350 * XXX - this shouldn't happen, as the filter string is machine
3355 if (sfcode == NULL) {
3357 * XXX - this shouldn't happen, as the filter string is machine
3362 result = find_packet(cf, match_dfilter, sfcode, dir);
3363 dfilter_free(sfcode);
3368 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3370 dfilter_t *sfcode = criterion;
3372 match_result result;
3374 /* Load the frame's data. */
3375 if (!cf_read_frame(cf, fdata)) {
3376 /* Attempt to get the packet failed. */
3380 epan_dissect_init(&edt, TRUE, FALSE);
3381 epan_dissect_prime_dfilter(&edt, sfcode);
3382 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3383 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3384 epan_dissect_cleanup(&edt);
3389 cf_find_packet_marked(capture_file *cf, search_direction dir)
3391 return find_packet(cf, match_marked, NULL, dir);
3395 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3397 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3401 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3403 return find_packet(cf, match_time_reference, NULL, dir);
3407 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3409 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3413 find_packet(capture_file *cf,
3414 match_result (*match_function)(capture_file *, frame_data *, void *),
3415 void *criterion, search_direction dir)
3417 frame_data *start_fd;
3420 frame_data *new_fd = NULL;
3421 progdlg_t *progbar = NULL;
3426 GTimeVal start_time;
3427 gchar status_str[100];
3428 int progbar_nextstep;
3429 int progbar_quantum;
3431 match_result result;
3433 start_fd = cf->current_frame;
3434 if (start_fd != NULL) {
3435 /* Iterate through the list of packets, starting at the packet we've
3436 picked, calling a routine to run the filter on the packet, see if
3437 it matches, and stop if so. */
3439 framenum = start_fd->num;
3441 /* Update the progress bar when it gets to this value. */
3442 progbar_nextstep = 0;
3443 /* When we reach the value that triggers a progress bar update,
3444 bump that value by this amount. */
3445 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3446 /* Progress so far. */
3450 g_get_current_time(&start_time);
3452 title = cf->sfilter?cf->sfilter:"";
3454 /* Create the progress bar if necessary.
3455 We check on every iteration of the loop, so that it takes no
3456 longer than the standard time to create it (otherwise, for a
3457 large file, we might take considerably longer than that standard
3458 time in order to get to the next progress bar step). */
3459 if (progbar == NULL)
3460 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3461 FALSE, &stop_flag, &start_time, progbar_val);
3463 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3464 when we update it, we have to run the GTK+ main loop to get it
3465 to repaint what's pending, and doing so may involve an "ioctl()"
3466 to see if there's any pending input from an X server, and doing
3467 that for every packet can be costly, especially on a big file. */
3468 if (count >= progbar_nextstep) {
3469 /* let's not divide by zero. I should never be started
3470 * with count == 0, so let's assert that
3472 g_assert(cf->count > 0);
3474 progbar_val = (gfloat) count / cf->count;
3476 if (progbar != NULL) {
3477 g_snprintf(status_str, sizeof(status_str),
3478 "%4u of %u packets", count, cf->count);
3479 update_progress_dlg(progbar, progbar_val, status_str);
3482 progbar_nextstep += progbar_quantum;
3486 /* Well, the user decided to abort the search. Go back to the
3487 frame where we started. */
3492 /* Go past the current frame. */
3493 if (dir == SD_BACKWARD) {
3494 /* Go on to the previous frame. */
3495 if (framenum == 1) {
3497 * XXX - other apps have a bit more of a detailed message
3498 * for this, and instead of offering "OK" and "Cancel",
3499 * they offer things such as "Continue" and "Cancel";
3500 * we need an API for popping up alert boxes with
3501 * {Verb} and "Cancel".
3504 if (prefs.gui_find_wrap)
3506 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3507 framenum = cf->count; /* wrap around */
3511 statusbar_push_temporary_msg("Search reached the beginning.");
3512 framenum = start_fd->num; /* stay on previous packet */
3517 /* Go on to the next frame. */
3518 if (framenum == cf->count) {
3519 if (prefs.gui_find_wrap)
3521 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3522 framenum = 1; /* wrap around */
3526 statusbar_push_temporary_msg("Search reached the end.");
3527 framenum = start_fd->num; /* stay on previous packet */
3532 fdata = frame_data_sequence_find(cf->frames, framenum);
3536 /* Is this packet in the display? */
3537 if (fdata->flags.passed_dfilter) {
3538 /* Yes. Does it match the search criterion? */
3539 result = (*match_function)(cf, fdata, criterion);
3540 if (result == MR_ERROR) {
3541 /* Error; our caller has reported the error. Go back to the frame
3542 where we started. */
3545 } else if (result == MR_MATCHED) {
3546 /* Yes. Go to the new frame. */
3552 if (fdata == start_fd) {
3553 /* We're back to the frame we were on originally, and that frame
3554 doesn't match the search filter. The search failed. */
3559 /* We're done scanning the packets; destroy the progress bar if it
3561 if (progbar != NULL)
3562 destroy_progress_dlg(progbar);
3565 if (new_fd != NULL) {
3566 /* Find and select */
3567 cf->search_in_progress = TRUE;
3568 found = packet_list_select_row_from_data(new_fd);
3569 cf->search_in_progress = FALSE;
3570 cf->search_pos = 0; /* Reset the position */
3572 /* We didn't find a row corresponding to this frame.
3573 This means that the frame isn't being displayed currently,
3574 so we can't select it. */
3575 simple_message_box(ESD_TYPE_INFO, NULL,
3576 "The capture file is probably not fully dissected.",
3577 "End of capture exceeded!");
3580 return TRUE; /* success */
3582 return FALSE; /* failure */
3586 cf_goto_frame(capture_file *cf, guint fnumber)
3590 fdata = frame_data_sequence_find(cf->frames, fnumber);
3592 if (fdata == NULL) {
3593 /* we didn't find a packet with that packet number */
3594 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3595 return FALSE; /* we failed to go to that packet */
3597 if (!fdata->flags.passed_dfilter) {
3598 /* that packet currently isn't displayed */
3599 /* XXX - add it to the set of displayed packets? */
3600 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3601 return FALSE; /* we failed to go to that packet */
3604 if (!packet_list_select_row_from_data(fdata)) {
3605 /* We didn't find a row corresponding to this frame.
3606 This means that the frame isn't being displayed currently,
3607 so we can't select it. */
3608 simple_message_box(ESD_TYPE_INFO, NULL,
3609 "The capture file is probably not fully dissected.",
3610 "End of capture exceeded!");
3613 return TRUE; /* we got to that packet */
3617 cf_goto_top_frame(void)
3619 /* Find and select */
3620 packet_list_select_first_row();
3621 return TRUE; /* we got to that packet */
3625 cf_goto_bottom_frame(void)
3627 /* Find and select */
3628 packet_list_select_last_row();
3629 return TRUE; /* we got to that packet */
3633 * Go to frame specified by currently selected protocol tree item.
3636 cf_goto_framenum(capture_file *cf)
3638 header_field_info *hfinfo;
3641 if (cf->finfo_selected) {
3642 hfinfo = cf->finfo_selected->hfinfo;
3644 if (hfinfo->type == FT_FRAMENUM) {
3645 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3647 return cf_goto_frame(cf, framenum);
3654 /* Select the packet on a given row. */
3656 cf_select_packet(capture_file *cf, int row)
3658 epan_dissect_t *old_edt;
3661 /* Get the frame data struct pointer for this frame */
3662 fdata = packet_list_get_row_data(row);
3664 if (fdata == NULL) {
3665 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3666 the first entry is added to it by "real_insert_row()", that row
3667 is selected (see "real_insert_row()", in "ui/gtk/gtkclist.c", in both
3668 our version and the vanilla GTK+ version).
3670 This means that a "select-row" signal is emitted; this causes
3671 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3674 "cf_select_packet()" fetches, above, the data associated with the
3675 row that was selected; however, as "gtk_clist_append()", which
3676 called "real_insert_row()", hasn't yet returned, we haven't yet
3677 associated any data with that row, so we get back a null pointer.
3679 We can't assume that there's only one frame in the frame list,
3680 either, as we may be filtering the display.
3682 We therefore assume that, if "row" is 0, i.e. the first row
3683 is being selected, and "cf->first_displayed" equals
3684 "cf->last_displayed", i.e. there's only one frame being
3685 displayed, that frame is the frame we want.
3687 This means we have to set "cf->first_displayed" and
3688 "cf->last_displayed" before adding the row to the
3689 GtkCList; see the comment in "add_packet_to_packet_list()". */
3691 if (row == 0 && cf->first_displayed == cf->last_displayed)
3692 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3695 /* If fdata _still_ isn't set simply give up. */
3696 if (fdata == NULL) {
3700 /* Get the data in that frame. */
3701 if (!cf_read_frame (cf, fdata)) {
3705 /* Record that this frame is the current frame. */
3706 cf->current_frame = fdata;
3707 cf->current_row = row;
3710 /* Create the logical protocol tree. */
3711 /* We don't need the columns here. */
3712 cf->edt = epan_dissect_new(TRUE, TRUE);
3714 tap_build_interesting(cf->edt);
3715 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3718 dfilter_macro_build_ftv_cache(cf->edt->tree);
3720 cf_callback_invoke(cf_cb_packet_selected, cf);
3722 if (old_edt != NULL)
3723 epan_dissect_free(old_edt);
3727 /* Unselect the selected packet, if any. */
3729 cf_unselect_packet(capture_file *cf)
3731 epan_dissect_t *old_edt = cf->edt;
3735 /* No packet is selected. */
3736 cf->current_frame = NULL;
3737 cf->current_row = 0;
3739 cf_callback_invoke(cf_cb_packet_unselected, cf);
3741 /* No protocol tree means no selected field. */
3742 cf_unselect_field(cf);
3744 /* Destroy the epan_dissect_t for the unselected packet. */
3745 if (old_edt != NULL)
3746 epan_dissect_free(old_edt);
3749 /* Unset the selected protocol tree field, if any. */
3751 cf_unselect_field(capture_file *cf)
3753 cf->finfo_selected = NULL;
3755 cf_callback_invoke(cf_cb_field_unselected, cf);
3759 * Mark a particular frame.
3762 cf_mark_frame(capture_file *cf, frame_data *frame)
3764 if (! frame->flags.marked) {
3765 frame->flags.marked = TRUE;
3766 if (cf->count > cf->marked_count)
3772 * Unmark a particular frame.
3775 cf_unmark_frame(capture_file *cf, frame_data *frame)
3777 if (frame->flags.marked) {
3778 frame->flags.marked = FALSE;
3779 if (cf->marked_count > 0)
3785 * Ignore a particular frame.
3788 cf_ignore_frame(capture_file *cf, frame_data *frame)
3790 if (! frame->flags.ignored) {
3791 frame->flags.ignored = TRUE;
3792 if (cf->count > cf->ignored_count)
3793 cf->ignored_count++;
3798 * Un-ignore a particular frame.
3801 cf_unignore_frame(capture_file *cf, frame_data *frame)
3803 if (frame->flags.ignored) {
3804 frame->flags.ignored = FALSE;
3805 if (cf->ignored_count > 0)
3806 cf->ignored_count--;
3811 * Read the comment in SHB block
3815 cf_read_shb_comment(capture_file *cf)
3817 wtapng_section_t *shb_inf;
3818 const gchar *temp_str;
3820 /* Get info from SHB */
3821 shb_inf = wtap_file_get_shb_info(cf->wth);
3822 if (shb_inf == NULL)
3824 temp_str = shb_inf->opt_comment;
3832 cf_update_capture_comment(capture_file *cf, gchar *comment)
3834 wtapng_section_t *shb_inf;
3836 /* Get info from SHB */
3837 shb_inf = wtap_file_get_shb_info(cf->wth);
3839 /* See if the comment has changed or not */
3840 if (shb_inf && shb_inf->opt_comment) {
3841 if (strcmp(shb_inf->opt_comment, comment) == 0) {
3850 /* The comment has changed, let's update it */
3851 wtap_write_shb_comment(cf->wth, comment);
3852 /* Mark the file as having unsaved changes */
3853 cf->unsaved_changes = TRUE;
3857 cf_update_packet_comment(capture_file *cf, frame_data *fdata, gchar *comment)
3859 if (fdata->opt_comment != NULL) {
3860 /* OK, remove the old comment. */
3861 g_free(fdata->opt_comment);
3862 fdata->opt_comment = NULL;
3863 cf->packet_comment_count--;
3865 if (comment != NULL) {
3866 /* Add the new comment. */
3867 fdata->opt_comment = comment;
3868 cf->packet_comment_count++;
3871 /* OK, we have unsaved changes. */
3872 cf->unsaved_changes = TRUE;
3876 * Does this capture file have any comments?
3879 cf_has_comments(capture_file *cf)
3881 return (cf_read_shb_comment(cf) != NULL || cf->packet_comment_count != 0);
3888 } save_callback_args_t;
3891 * Save a capture to a file, in a particular format, saving either
3892 * all packets, all currently-displayed packets, or all marked packets.
3894 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3895 * up a message box for the failure.
3898 save_packet(capture_file *cf _U_, frame_data *fdata,
3899 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3902 save_callback_args_t *args = argsp;
3903 struct wtap_pkthdr hdr;
3905 gchar *display_basename;
3907 /* init the wtap header for saving */
3908 /* XXX - these are the only flags that correspond to data that we have
3909 in the frame_data structure and that matter on a per-packet basis.
3911 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
3912 and "on the wire" lengths, or it doesn't.
3914 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
3917 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
3918 from the packet flags. */
3919 hdr.presence_flags = 0;
3920 if (fdata->flags.has_ts)
3921 hdr.presence_flags |= WTAP_HAS_TS;
3922 if (fdata->flags.has_ts)
3923 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
3924 hdr.ts.secs = fdata->abs_ts.secs;
3925 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3926 hdr.caplen = fdata->cap_len;
3927 hdr.len = fdata->pkt_len;
3928 hdr.pkt_encap = fdata->lnk_t;
3930 hdr.interface_id = fdata->interface_id; /* identifier of the interface. */
3932 hdr.opt_comment = fdata->opt_comment; /* NULL if not available */
3935 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
3937 /* and save the packet */
3938 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3940 /* Wiretap error. */
3943 case WTAP_ERR_UNSUPPORTED_ENCAP:
3945 * This is a problem with the particular frame we're writing;
3946 * note that, and give the frame number.
3948 simple_error_message_box(
3949 "Frame %u has a network type that can't be saved in a \"%s\" file.",
3950 fdata->num, wtap_file_type_string(args->file_type));
3954 display_basename = g_filename_display_basename(args->fname);
3955 simple_error_message_box(
3956 "An error occurred while writing to the file \"%s\": %s.",
3957 display_basename, wtap_strerror(err));
3958 g_free(display_basename);
3963 write_failure_alert_box(args->fname, err);
3971 * Can this capture file be written out in any format using Wiretap
3972 * rather than by copying the raw data?
3975 cf_can_write_with_wiretap(capture_file *cf)
3979 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
3980 /* To save a file with Wiretap, Wiretap has to handle that format,
3981 and its code to handle that format must be able to write a file
3982 with this file's encapsulation types. */
3983 if (wtap_dump_can_write_encaps(ft, cf->linktypes)) {
3984 /* OK, we can write it out in this type. */
3989 /* No, we couldn't save it in any format. */
3994 * Quick scan to find packet offsets.
3996 static cf_read_status_t
3997 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
3999 const struct wtap_pkthdr *phdr;
4004 progdlg_t *volatile progbar = NULL;
4006 volatile gint64 size;
4007 volatile float progbar_val;
4008 GTimeVal start_time;
4009 gchar status_str[100];
4010 volatile gint64 progbar_nextstep;
4011 volatile gint64 progbar_quantum;
4014 volatile int count = 0;
4016 volatile int displayed_once = 0;
4019 /* Close the old handle. */
4020 wtap_close(cf->wth);
4022 /* Open the new file. */
4023 cf->wth = wtap_open_offline(fname, err, &err_info, TRUE);
4024 if (cf->wth == NULL) {
4025 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
4026 return CF_READ_ERROR;
4029 /* We're scanning a file whose contents should be the same as what
4030 we had before, so we don't discard dissection state etc.. */
4033 /* Set the file name because we need it to set the follow stream filter.
4034 XXX - is that still true? We need it for other reasons, though,
4036 cf->filename = g_strdup(fname);
4038 /* Indicate whether it's a permanent or temporary file. */
4039 cf->is_tempfile = is_tempfile;
4041 /* No user changes yet. */
4042 cf->unsaved_changes = FALSE;
4044 cf->cd_t = wtap_file_type(cf->wth);
4045 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4047 cf->snap = wtap_snapshot_length(cf->wth);
4048 if (cf->snap == 0) {
4049 /* Snapshot length not known. */
4050 cf->has_snap = FALSE;
4051 cf->snap = WTAP_MAX_PACKET_SIZE;
4053 cf->has_snap = TRUE;
4055 name_ptr = g_filename_display_basename(cf->filename);
4057 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4059 /* Record whether the file is compressed.
4060 XXX - do we know this at open time? */
4061 cf->iscompressed = wtap_iscompressed(cf->wth);
4063 /* Find the size of the file. */
4064 size = wtap_file_size(cf->wth, NULL);
4066 /* Update the progress bar when it gets to this value. */
4067 progbar_nextstep = 0;
4068 /* When we reach the value that triggers a progress bar update,
4069 bump that value by this amount. */
4071 progbar_quantum = size/N_PROGBAR_UPDATES;
4072 if (progbar_quantum < MIN_QUANTUM)
4073 progbar_quantum = MIN_QUANTUM;
4075 progbar_quantum = 0;
4076 /* Progress so far. */
4080 g_get_current_time(&start_time);
4083 phdr = wtap_phdr(cf->wth);
4084 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
4086 fdata = frame_data_sequence_find(cf->frames, framenum);
4087 fdata->file_off = data_offset;
4090 file_pos = wtap_read_so_far(cf->wth);
4092 /* Create the progress bar if necessary.
4093 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
4095 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
4096 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
4097 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4098 TRUE, &stop_flag, &start_time, progbar_val);
4101 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
4102 when we update it, we have to run the GTK+ main loop to get it
4103 to repaint what's pending, and doing so may involve an "ioctl()"
4104 to see if there's any pending input from an X server, and doing
4105 that for every packet can be costly, especially on a big file. */
4106 if (file_pos >= progbar_nextstep) {
4107 if (progbar != NULL) {
4108 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
4109 /* update the packet bar content on the first run or frequently on very large files */
4111 if (progbar_quantum > 500000 || displayed_once == 0) {
4112 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
4114 packets_bar_update();
4117 #endif /* HAVE_LIBPCAP */
4118 update_progress_dlg(progbar, progbar_val, status_str);
4120 progbar_nextstep += progbar_quantum;
4125 /* Well, the user decided to abort the rescan. Sadly, as this
4126 isn't a reread, recovering is difficult, so we'll just
4127 close the current capture. */
4131 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4132 it's not already there.
4133 XXX - yes, this is O(N), so if every packet had a different
4134 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4135 there are probably going to be a small number of encapsulation types
4137 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4140 /* Free the display name */
4143 /* We're done reading the file; destroy the progress bar if it was created. */
4144 if (progbar != NULL)
4145 destroy_progress_dlg(progbar);
4147 /* We're done reading sequentially through the file. */
4148 cf->state = FILE_READ_DONE;
4150 /* Close the sequential I/O side, to free up memory it requires. */
4151 wtap_sequential_close(cf->wth);
4153 /* compute the time it took to load the file */
4154 compute_elapsed(&start_time);
4156 /* Set the file encapsulation type now; we don't know what it is until
4157 we've looked at all the packets, as we don't know until then whether
4158 there's more than one type (and thus whether it's
4159 WTAP_ENCAP_PER_PACKET). */
4160 cf->lnk_t = wtap_file_encap(cf->wth);
4162 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4165 /* Our caller will give up at this point. */
4166 return CF_READ_ABORTED;
4170 /* Put up a message box noting that the read failed somewhere along
4171 the line. Don't throw out the stuff we managed to read, though,
4175 case WTAP_ERR_UNSUPPORTED:
4176 simple_error_message_box(
4177 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
4182 case WTAP_ERR_UNSUPPORTED_ENCAP:
4183 simple_error_message_box(
4184 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
4189 case WTAP_ERR_CANT_READ:
4190 simple_error_message_box(
4191 "An attempt to read from the capture file failed for"
4192 " some unknown reason.");
4195 case WTAP_ERR_SHORT_READ:
4196 simple_error_message_box(
4197 "The capture file appears to have been cut short"
4198 " in the middle of a packet.");
4201 case WTAP_ERR_BAD_FILE:
4202 simple_error_message_box(
4203 "The capture file appears to be damaged or corrupt.\n(%s)",
4208 case WTAP_ERR_DECOMPRESS:
4209 simple_error_message_box(
4210 "The compressed capture file appears to be damaged or corrupt.\n"
4216 simple_error_message_box(
4217 "An error occurred while reading the"
4218 " capture file: %s.", wtap_strerror(*err));
4221 return CF_READ_ERROR;
4227 cf_save_packets(capture_file *cf, const char *fname, guint save_format,
4228 gboolean compressed, gboolean discard_comments,
4229 gboolean dont_reopen)
4231 gchar *fname_new = NULL;
4240 save_callback_args_t callback_args;
4242 gchar *display_basename;
4247 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4249 if (save_format == cf->cd_t && compressed == cf->iscompressed
4250 && !discard_comments && !cf->unsaved_changes) {
4251 /* We're saving in the format it's already in, and we're
4252 not discarding comments, and there are no changes we have
4253 in memory that aren't saved to the file, so we can just move
4254 or copy the raw data. */
4256 if (cf->is_tempfile) {
4257 /* The file being saved is a temporary file from a live
4258 capture, so it doesn't need to stay around under that name;
4259 first, try renaming the capture buffer file to the new name.
4260 This acts as a "safe save", in that, if the file already
4261 exists, the existing file will be removed only if the rename
4264 Sadly, on Windows, as we have the current capture file
4265 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4266 (to cause the rename to remove an existing target), as
4267 done by ws_stdio_rename() (ws_rename() is #defined to
4268 be ws_stdio_rename() on Windows) will fail.
4270 According to the MSDN documentation for CreateFile(), if,
4271 when we open a capture file, we were to directly do a CreateFile(),
4272 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4273 convert it to a file descriptor with _open_osfhandle(),
4274 that would allow the file to be renamed out from under us.
4276 However, that doesn't work in practice. Perhaps the problem
4277 is that the process doing the rename is the process that
4278 has the file open. */
4280 if (ws_rename(cf->filename, fname) == 0) {
4281 /* That succeeded - there's no need to copy the source file. */
4282 how_to_save = SAVE_WITH_MOVE;
4284 if (errno == EXDEV) {
4285 /* They're on different file systems, so we have to copy the
4287 how_to_save = SAVE_WITH_COPY;
4289 /* The rename failed, but not because they're on different
4290 file systems - put up an error message. (Or should we
4291 just punt and try to copy? The only reason why I'd
4292 expect the rename to fail and the copy to succeed would
4293 be if we didn't have permission to remove the file from
4294 the temporary directory, and that might be fixable - but
4295 is it worth requiring the user to go off and fix it?) */
4296 cf_rename_failure_alert_box(fname, errno);
4301 how_to_save = SAVE_WITH_COPY;
4304 /* It's a permanent file, so we should copy it, and not remove the
4306 how_to_save = SAVE_WITH_COPY;
4309 if (how_to_save == SAVE_WITH_COPY) {
4310 /* Copy the file, if we haven't moved it. If we're overwriting
4311 an existing file, we do it with a "safe save", by writing
4312 to a new file and, if the write succeeds, renaming the
4313 new file on top of the old file. */
4314 if (file_exists(fname)) {
4315 fname_new = g_strdup_printf("%s~", fname);
4316 if (!copy_file_binary_mode(cf->filename, fname_new))
4319 if (!copy_file_binary_mode(cf->filename, fname))
4324 /* Either we're saving in a different format or we're saving changes,
4325 such as added, modified, or removed comments, that haven't yet
4326 been written to the underlying file; we can't do that by copying
4327 or moving the capture file, we have to do it by writing the packets
4330 wtapng_section_t *shb_hdr = NULL;
4331 wtapng_iface_descriptions_t *idb_inf = NULL;
4334 shb_hdr = wtap_file_get_shb_info(cf->wth);
4335 idb_inf = wtap_file_get_idb_info(cf->wth);
4337 /* Determine what file encapsulation type we should use. */
4338 encap = wtap_dump_file_encap_type(cf->linktypes);
4340 if (file_exists(fname)) {
4341 /* We're overwriting an existing file; write out to a new file,
4342 and, if that succeeds, rename the new file on top of the
4343 old file. That makes this a "safe save", so that we don't
4344 lose the old file if we have a problem writing out the new
4345 file. (If the existing file is the current capture file,
4346 we *HAVE* to do that, otherwise we're overwriting the file
4347 from which we're reading the packets that we're writing!) */
4348 fname_new = g_strdup_printf("%s~", fname);
4349 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4350 compressed, shb_hdr, idb_inf, &err);
4352 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4353 compressed, shb_hdr, idb_inf, &err);
4359 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4363 /* Add address resolution */
4364 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4366 /* Iterate through the list of packets, processing all the packets. */
4367 callback_args.pdh = pdh;
4368 callback_args.fname = fname;
4369 callback_args.file_type = save_format;
4370 switch (process_specified_packets(cf, NULL, "Saving", "packets",
4371 TRUE, save_packet, &callback_args)) {
4374 /* Completed successfully. */
4378 /* The user decided to abort the saving.
4379 If we're writing to a temporary file, remove it.
4380 XXX - should we do so even if we're not writing to a
4382 wtap_dump_close(pdh, &err);
4383 if (fname_new != NULL)
4384 ws_unlink(fname_new);
4385 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4386 return CF_WRITE_ABORTED;
4389 /* Error while saving.
4390 If we're writing to a temporary file, remove it. */
4391 if (fname_new != NULL)
4392 ws_unlink(fname_new);
4393 wtap_dump_close(pdh, &err);
4397 if (!wtap_dump_close(pdh, &err)) {
4398 cf_close_failure_alert_box(fname, err);
4402 how_to_save = SAVE_WITH_WTAP;
4405 if (fname_new != NULL) {
4406 /* We wrote out to fname_new, and should rename it on top of
4407 fname. fname_new is now closed, so that should be possible even
4408 on Windows. However, on Windows, we first need to close whatever
4409 file descriptors we have open for fname. */
4411 wtap_fdclose(cf->wth);
4413 /* Now do the rename. */
4414 if (ws_rename(fname_new, fname) == -1) {
4415 /* Well, the rename failed. */
4416 cf_rename_failure_alert_box(fname, errno);
4418 /* Attempt to reopen the random file descriptor using the
4419 current file's filename. (At this point, the sequential
4420 file descriptor is closed.) */
4421 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4422 /* Oh, well, we're screwed. */
4423 display_basename = g_filename_display_basename(cf->filename);
4424 simple_error_message_box(
4425 file_open_error_message(err, FALSE), display_basename);
4426 g_free(display_basename);
4433 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4434 cf->unsaved_changes = FALSE;
4437 switch (how_to_save) {
4439 case SAVE_WITH_MOVE:
4440 /* We just moved the file, so the wtap structure refers to the
4441 new file, and all the information other than the filename
4442 and the "is temporary" status applies to the new file; just
4444 g_free(cf->filename);
4445 cf->filename = g_strdup(fname);
4446 cf->is_tempfile = FALSE;
4447 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4450 case SAVE_WITH_COPY:
4451 /* We just copied the file, s all the information other than
4452 the wtap structure, the filename, and the "is temporary"
4453 status applies to the new file; just update that. */
4454 wtap_close(cf->wth);
4455 cf->wth = wtap_open_offline(fname, &err, &err_info, TRUE);
4456 if (cf->wth == NULL) {
4457 cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
4460 g_free(cf->filename);
4461 cf->filename = g_strdup(fname);
4462 cf->is_tempfile = FALSE;
4464 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4467 case SAVE_WITH_WTAP:
4468 /* Open and read the file we saved to.
4470 XXX - this is somewhat of a waste; we already have the
4471 packets, all this gets us is updated file type information
4472 (which we could just stuff into "cf"), and having the new
4473 file be the one we have opened and from which we're reading
4474 the data, and it means we have to spend time opening and
4475 reading the file, which could be a significant amount of
4476 time if the file is large.
4478 If the capture-file-writing code were to return the
4479 seek offset of each packet it writes, we could save that
4480 in the frame_data structure for the frame, and just open
4481 the file without reading it again...
4483 ...as long as, for gzipped files, the process of writing
4484 out the file *also* generates the information needed to
4485 support fast random access to the compressed file. */
4486 if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) {
4487 /* The rescan failed; just close the file. Either
4488 a dialog was popped up for the failure, so the
4489 user knows what happened, or they stopped the
4490 rescan, in which case they know what happened. */
4496 /* If we were told to discard the comments, do so. */
4497 if (discard_comments) {
4498 /* Remove SHB comment, if any. */
4499 wtap_write_shb_comment(cf->wth, NULL);
4501 /* Remove packet comments. */
4502 for (framenum = 1; framenum <= cf->count; framenum++) {
4503 fdata = frame_data_sequence_find(cf->frames, framenum);
4504 if (fdata->opt_comment) {
4505 g_free(fdata->opt_comment);
4506 fdata->opt_comment = NULL;
4507 cf->packet_comment_count--;
4515 if (fname_new != NULL) {
4516 /* We were trying to write to a temporary file; get rid of it if it
4517 exists. (We don't care whether this fails, as, if it fails,
4518 there's not much we can do about it. I guess if it failed for
4519 a reason other than "it doesn't exist", we could report an
4520 error, so the user knows there's a junk file that they might
4521 want to clean up.) */
4522 ws_unlink(fname_new);
4525 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4526 return CF_WRITE_ERROR;
4530 cf_export_specified_packets(capture_file *cf, const char *fname,
4531 packet_range_t *range, guint save_format,
4532 gboolean compressed)
4534 gchar *fname_new = NULL;
4537 save_callback_args_t callback_args;
4538 wtapng_section_t *shb_hdr;
4539 wtapng_iface_descriptions_t *idb_inf;
4542 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4544 packet_range_process_init(range);
4546 /* We're writing out specified packets from the specified capture
4547 file to another file. Even if all captured packets are to be
4548 written, don't special-case the operation - read each packet
4549 and then write it out if it's one of the specified ones. */
4551 shb_hdr = wtap_file_get_shb_info(cf->wth);
4552 idb_inf = wtap_file_get_idb_info(cf->wth);
4554 /* Determine what file encapsulation type we should use. */
4555 encap = wtap_dump_file_encap_type(cf->linktypes);
4557 if (file_exists(fname)) {
4558 /* We're overwriting an existing file; write out to a new file,
4559 and, if that succeeds, rename the new file on top of the
4560 old file. That makes this a "safe save", so that we don't
4561 lose the old file if we have a problem writing out the new
4562 file. (If the existing file is the current capture file,
4563 we *HAVE* to do that, otherwise we're overwriting the file
4564 from which we're reading the packets that we're writing!) */
4565 fname_new = g_strdup_printf("%s~", fname);
4566 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4567 compressed, shb_hdr, idb_inf, &err);
4569 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4570 compressed, shb_hdr, idb_inf, &err);
4576 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4580 /* Add address resolution */
4581 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4583 /* Iterate through the list of packets, processing the packets we were
4586 XXX - we've already called "packet_range_process_init(range)", but
4587 "process_specified_packets()" will do it again. Fortunately,
4588 that's harmless in this case, as we haven't done anything to
4589 "range" since we initialized it. */
4590 callback_args.pdh = pdh;
4591 callback_args.fname = fname;
4592 callback_args.file_type = save_format;
4593 switch (process_specified_packets(cf, range, "Writing", "specified packets",
4594 TRUE, save_packet, &callback_args)) {
4597 /* Completed successfully. */
4601 /* The user decided to abort the saving.
4602 If we're writing to a temporary file, remove it.
4603 XXX - should we do so even if we're not writing to a
4605 wtap_dump_close(pdh, &err);
4606 if (fname_new != NULL)
4607 ws_unlink(fname_new);
4608 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4609 return CF_WRITE_ABORTED;
4613 /* Error while saving.
4614 If we're writing to a temporary file, remove it. */
4615 if (fname_new != NULL)
4616 ws_unlink(fname_new);
4617 wtap_dump_close(pdh, &err);
4621 if (!wtap_dump_close(pdh, &err)) {
4622 cf_close_failure_alert_box(fname, err);
4626 if (fname_new != NULL) {
4627 /* We wrote out to fname_new, and should rename it on top of
4628 fname; fname is now closed, so that should be possible even
4629 on Windows. Do the rename. */
4630 if (ws_rename(fname_new, fname) == -1) {
4631 /* Well, the rename failed. */
4632 cf_rename_failure_alert_box(fname, errno);
4637 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4641 if (fname_new != NULL) {
4642 /* We were trying to write to a temporary file; get rid of it if it
4643 exists. (We don't care whether this fails, as, if it fails,
4644 there's not much we can do about it. I guess if it failed for
4645 a reason other than "it doesn't exist", we could report an
4646 error, so the user knows there's a junk file that they might
4647 want to clean up.) */
4648 ws_unlink(fname_new);
4651 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4652 return CF_WRITE_ERROR;
4656 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
4657 gboolean for_writing, int file_type)
4659 gchar *display_basename;
4662 /* Wiretap error. */
4663 display_basename = g_filename_display_basename(filename);
4666 case WTAP_ERR_NOT_REGULAR_FILE:
4667 simple_error_message_box(
4668 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4672 case WTAP_ERR_RANDOM_OPEN_PIPE:
4673 /* Seen only when opening a capture file for reading. */
4674 simple_error_message_box(
4675 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.\n"
4676 "To capture from a pipe or FIFO use wireshark -i -",
4680 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
4681 /* Seen only when opening a capture file for reading. */
4682 simple_error_message_box(
4683 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
4687 case WTAP_ERR_UNSUPPORTED:
4688 /* Seen only when opening a capture file for reading. */
4689 simple_error_message_box(
4690 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
4692 display_basename, err_info);
4696 case WTAP_ERR_CANT_WRITE_TO_PIPE:
4697 /* Seen only when opening a capture file for writing. */
4698 simple_error_message_box(
4699 "The file \"%s\" is a pipe, and %s capture files can't be "
4700 "written to a pipe.",
4701 display_basename, wtap_file_type_string(file_type));
4704 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
4705 /* Seen only when opening a capture file for writing. */
4706 simple_error_message_box(
4707 "Wireshark doesn't support writing capture files in that format.");
4710 case WTAP_ERR_UNSUPPORTED_ENCAP:
4712 simple_error_message_box("Wireshark can't save this capture in that format.");
4714 simple_error_message_box(
4715 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
4717 display_basename, err_info);
4722 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
4724 simple_error_message_box(
4725 "Wireshark can't save this capture in that format.");
4727 simple_error_message_box(
4728 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
4733 case WTAP_ERR_BAD_FILE:
4734 /* Seen only when opening a capture file for reading. */
4735 simple_error_message_box(
4736 "The file \"%s\" appears to be damaged or corrupt.\n"
4738 display_basename, err_info);
4742 case WTAP_ERR_CANT_OPEN:
4744 simple_error_message_box(
4745 "The file \"%s\" could not be created for some unknown reason.",
4748 simple_error_message_box(
4749 "The file \"%s\" could not be opened for some unknown reason.",
4754 case WTAP_ERR_SHORT_READ:
4755 simple_error_message_box(
4756 "The file \"%s\" appears to have been cut short"
4757 " in the middle of a packet or other data.",
4761 case WTAP_ERR_SHORT_WRITE:
4762 simple_error_message_box(
4763 "A full header couldn't be written to the file \"%s\".",
4767 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4768 simple_error_message_box(
4769 "This file type cannot be written as a compressed file.");
4772 case WTAP_ERR_DECOMPRESS:
4773 simple_error_message_box(
4774 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
4775 "(%s)", display_basename, err_info);
4780 simple_error_message_box(
4781 "The file \"%s\" could not be %s: %s.",
4783 for_writing ? "created" : "opened",
4784 wtap_strerror(err));
4787 g_free(display_basename);
4790 open_failure_alert_box(filename, err, for_writing);
4795 * XXX - whether we mention the source pathname, the target pathname,
4796 * or both depends on the error and on what we find if we look for
4797 * one or both of them.
4800 cf_rename_failure_alert_box(const char *filename, int err)
4802 gchar *display_basename;
4804 display_basename = g_filename_display_basename(filename);
4808 /* XXX - should check whether the source exists and, if not,
4809 report it as the problem and, if so, report the destination
4811 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4816 /* XXX - if we're doing a rename after a safe save, we should
4817 probably say something else. */
4818 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4823 /* XXX - this should probably mention both the source and destination
4825 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4826 display_basename, wtap_strerror(err));
4829 g_free(display_basename);
4832 /* Check for write errors - if the file is being written to an NFS server,
4833 a write error may not show up until the file is closed, as NFS clients
4834 might not send writes to the server until the "write()" call finishes,
4835 so that the write may fail on the server but the "write()" may succeed. */
4837 cf_close_failure_alert_box(const char *filename, int err)
4839 gchar *display_basename;
4842 /* Wiretap error. */
4843 display_basename = g_filename_display_basename(filename);
4846 case WTAP_ERR_CANT_CLOSE:
4847 simple_error_message_box(
4848 "The file \"%s\" couldn't be closed for some unknown reason.",
4852 case WTAP_ERR_SHORT_WRITE:
4853 simple_error_message_box(
4854 "Not all the packets could be written to the file \"%s\".",
4859 simple_error_message_box(
4860 "An error occurred while closing the file \"%s\": %s.",
4861 display_basename, wtap_strerror(err));
4864 g_free(display_basename);
4867 We assume that a close error from the OS is really a write error. */
4868 write_failure_alert_box(filename, err);
4872 /* Reload the current capture file. */
4874 cf_reload(capture_file *cf) {
4876 gboolean is_tempfile;
4879 /* If the file could be opened, "cf_open()" calls "cf_close()"
4880 to get rid of state for the old capture file before filling in state
4881 for the new capture file. "cf_close()" will remove the file if
4882 it's a temporary file; we don't want that to happen (for one thing,
4883 it'd prevent subsequent reopens from working). Remember whether it's
4884 a temporary file, mark it as not being a temporary file, and then
4885 reopen it as the type of file it was.
4887 Also, "cf_close()" will free "cf->filename", so we must make
4888 a copy of it first. */
4889 filename = g_strdup(cf->filename);
4890 is_tempfile = cf->is_tempfile;
4891 cf->is_tempfile = FALSE;
4892 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4893 switch (cf_read(cf, TRUE)) {
4897 /* Just because we got an error, that doesn't mean we were unable
4898 to read any of the file; we handle what we could get from the
4902 case CF_READ_ABORTED:
4903 /* The user bailed out of re-reading the capture file; the
4904 capture file has been closed - just free the capture file name
4905 string and return (without changing the last containing
4911 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4912 Instead, the file was left open, so we should restore "cf->is_tempfile"
4915 XXX - change the menu? Presumably "cf_open()" will do that;
4916 make sure it does! */
4917 cf->is_tempfile = is_tempfile;
4919 /* "cf_open()" made a copy of the file name we handed it, so
4920 we should free up our copy. */
4930 * indent-tabs-mode: nil
4933 * ex: set shiftwidth=2 tabstop=8 expandtab:
4934 * :indentSize=2:tabSize=8:noTabs=true: