6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #include <epan/epan.h>
47 #include <epan/filesystem.h>
50 #include "color_filters.h"
52 #include <epan/column.h>
53 #include <epan/packet.h>
54 #include <epan/column-utils.h>
55 #include "packet-range.h"
61 #include "alert_box.h"
62 #include "simple_dialog.h"
63 #include "progress_dlg.h"
65 #include <epan/prefs.h>
66 #include <epan/dfilter/dfilter.h>
67 #include <epan/epan_dissect.h>
69 #include <epan/dissectors/packet-data.h>
70 #include <epan/dissectors/packet-ber.h>
71 #include <epan/timestamp.h>
72 #include <epan/dfilter/dfilter-macro.h>
73 #include <wsutil/file_util.h>
74 #include <epan/strutil.h>
77 gboolean auto_scroll_live;
80 static guint32 cum_bytes;
81 static nstime_t first_ts;
82 static nstime_t prev_dis_ts;
83 static nstime_t prev_cap_ts;
85 static gulong computed_elapsed;
87 static void cf_reset_state(capture_file *cf);
89 static int read_packet(capture_file *cf, dfilter_t *dfcode,
90 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset);
92 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
93 gboolean refilter, gboolean redissect);
100 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
102 static void match_subtree_text(proto_node *node, gpointer data);
103 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
105 static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
107 static match_result match_ascii(capture_file *cf, frame_data *fdata,
109 static match_result match_unicode(capture_file *cf, frame_data *fdata,
111 static match_result match_binary(capture_file *cf, frame_data *fdata,
113 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
115 static match_result match_marked(capture_file *cf, frame_data *fdata,
117 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
119 static gboolean find_packet(capture_file *cf,
120 match_result (*match_function)(capture_file *, frame_data *, void *),
121 void *criterion, search_direction dir);
123 static void cf_open_failure_alert_box(const char *filename, int err,
124 gchar *err_info, gboolean for_writing,
126 static const char *file_rename_error_message(int err);
127 static void cf_write_failure_alert_box(const char *filename, int err);
128 static void cf_close_failure_alert_box(const char *filename, int err);
129 #ifdef NEW_PACKET_LIST
130 static void ref_time_packets(capture_file *cf);
132 /* Update the progress bar this many times when reading a file. */
133 #define N_PROGBAR_UPDATES 100
134 /* We read around 200k/100ms don't update the progress bar more often than that */
135 #define MIN_QUANTUM 200000
136 #define MIN_NUMBER_OF_PACKET 1500
138 /* Number of "frame_data" structures per memory chunk.
139 XXX - is this the right number? */
140 #define FRAME_DATA_CHUNK_SIZE 1024
143 /* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
145 cf_callback_t cb_fct;
147 } cf_callback_data_t;
149 static GList *cf_callbacks = NULL;
152 cf_callback_invoke(int event, gpointer data)
154 cf_callback_data_t *cb;
155 GList *cb_item = cf_callbacks;
157 /* there should be at least one interested */
158 g_assert(cb_item != NULL);
160 while(cb_item != NULL) {
162 cb->cb_fct(event, data, cb->user_data);
163 cb_item = g_list_next(cb_item);
169 cf_callback_add(cf_callback_t func, gpointer user_data)
171 cf_callback_data_t *cb;
173 cb = g_malloc(sizeof(cf_callback_data_t));
175 cb->user_data = user_data;
177 cf_callbacks = g_list_append(cf_callbacks, cb);
181 cf_callback_remove(cf_callback_t func)
183 cf_callback_data_t *cb;
184 GList *cb_item = cf_callbacks;
186 while(cb_item != NULL) {
188 if(cb->cb_fct == func) {
189 cf_callbacks = g_list_remove(cf_callbacks, cb);
193 cb_item = g_list_next(cb_item);
196 g_assert_not_reached();
200 cf_timestamp_auto_precision(capture_file *cf)
202 #ifdef NEW_PACKET_LIST
205 int prec = timestamp_get_precision();
208 /* don't try to get the file's precision if none is opened */
209 if(cf->state == FILE_CLOSED) {
213 /* if we are in auto mode, set precision of current file */
214 if(prec == TS_PREC_AUTO ||
215 prec == TS_PREC_AUTO_SEC ||
216 prec == TS_PREC_AUTO_DSEC ||
217 prec == TS_PREC_AUTO_CSEC ||
218 prec == TS_PREC_AUTO_MSEC ||
219 prec == TS_PREC_AUTO_USEC ||
220 prec == TS_PREC_AUTO_NSEC)
222 switch(wtap_file_tsprecision(cf->wth)) {
223 case(WTAP_FILE_TSPREC_SEC):
224 timestamp_set_precision(TS_PREC_AUTO_SEC);
226 case(WTAP_FILE_TSPREC_DSEC):
227 timestamp_set_precision(TS_PREC_AUTO_DSEC);
229 case(WTAP_FILE_TSPREC_CSEC):
230 timestamp_set_precision(TS_PREC_AUTO_CSEC);
232 case(WTAP_FILE_TSPREC_MSEC):
233 timestamp_set_precision(TS_PREC_AUTO_MSEC);
235 case(WTAP_FILE_TSPREC_USEC):
236 timestamp_set_precision(TS_PREC_AUTO_USEC);
238 case(WTAP_FILE_TSPREC_NSEC):
239 timestamp_set_precision(TS_PREC_AUTO_NSEC);
242 g_assert_not_reached();
245 #ifdef NEW_PACKET_LIST
246 /* Set the column widths of those columns that show the time in
247 "command-line-specified" format. */
248 for (i = 0; i < cf->cinfo.num_cols; i++) {
249 if (col_has_time_fmt(&cf->cinfo, i)) {
250 new_packet_list_resize_column(i);
257 cf_get_computed_elapsed(void)
259 return computed_elapsed;
262 static void reset_elapsed(void)
264 computed_elapsed = 0;
267 static void compute_elapsed(GTimeVal *start_time)
272 g_get_current_time(&time_now);
274 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
275 time_now.tv_usec - start_time->tv_usec;
277 computed_elapsed = (gulong) (delta_time / 1000); /* ms*/
281 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
286 wth = wtap_open_offline(fname, err, &err_info, TRUE);
290 /* The open succeeded. Close whatever capture file we had open,
291 and fill in the information for this file. */
294 /* Cleanup all data structures used for dissection. */
295 cleanup_dissection();
296 /* Initialize all data structures used for dissection. */
299 /* We're about to start reading the file. */
300 cf->state = FILE_READ_IN_PROGRESS;
305 /* Set the file name because we need it to set the follow stream filter.
306 XXX - is that still true? We need it for other reasons, though,
308 cf->filename = g_strdup(fname);
310 /* Indicate whether it's a permanent or temporary file. */
311 cf->is_tempfile = is_tempfile;
313 /* If it's a temporary capture buffer file, mark it as not saved. */
314 cf->user_saved = !is_tempfile;
318 cf->cd_t = wtap_file_type(cf->wth);
320 cf->displayed_count = 0;
321 cf->marked_count = 0;
322 cf->ignored_count = 0;
323 cf->ref_time_count = 0;
324 cf->drops_known = FALSE;
326 cf->snap = wtap_snapshot_length(cf->wth);
328 /* Snapshot length not known. */
329 cf->has_snap = FALSE;
330 cf->snap = WTAP_MAX_PACKET_SIZE;
334 nstime_set_zero(&cf->elapsed_time);
335 nstime_set_unset(&first_ts);
336 nstime_set_unset(&prev_dis_ts);
337 nstime_set_unset(&prev_cap_ts);
340 #if GLIB_CHECK_VERSION(2,10,0)
342 /* memory chunks have been deprecated in favor of the slice allocator,
343 * which has been added in 2.10
345 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
347 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
349 g_assert(cf->plist_chunk);
352 #ifdef NEW_PACKET_LIST
353 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
354 cf_timestamp_auto_precision(cf);
356 new_packet_list_queue_draw();
358 /* change the time formats now, as we might have a new precision */
359 cf_change_time_formats(cf);
361 fileset_file_opened(fname);
363 if(cf->cd_t == WTAP_FILE_BER) {
364 /* tell the BER dissector the file name */
365 ber_set_filename(cf->filename);
371 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
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".
384 cf_reset_state(capture_file *cf)
386 /* Die if we're in the middle of reading a file. */
387 g_assert(cf->state != FILE_READ_IN_PROGRESS);
393 /* We have no file open... */
394 if (cf->filename != NULL) {
395 /* If it's a temporary file, remove it. */
397 ws_unlink(cf->filename);
398 g_free(cf->filename);
401 /* ...which means we have nothing to save. */
402 cf->user_saved = FALSE;
404 #if GLIB_CHECK_VERSION(2,10,0)
405 if (cf->plist_start != NULL)
406 g_slice_free_chain(frame_data, cf->plist_start, next);
408 /* memory chunks have been deprecated in favor of the slice allocator,
409 * which has been added in 2.10
411 if (cf->plist_chunk != NULL) {
412 g_mem_chunk_destroy(cf->plist_chunk);
413 cf->plist_chunk = NULL;
416 dfilter_free(cf->rfcode);
418 cf->plist_start = NULL;
419 cf->plist_end = NULL;
420 cf_unselect_packet(cf); /* nothing to select */
421 cf->first_displayed = NULL;
422 cf->last_displayed = NULL;
424 /* No frame selected, no field in that frame selected. */
425 cf->current_frame = NULL;
427 cf->finfo_selected = NULL;
429 /* Clear the packet list. */
430 #ifdef NEW_PACKET_LIST
431 new_packet_list_freeze();
432 new_packet_list_clear();
433 new_packet_list_thaw();
435 packet_list_freeze();
442 nstime_set_zero(&cf->elapsed_time);
444 reset_tap_listeners();
446 /* We have no file open. */
447 cf->state = FILE_CLOSED;
449 fileset_file_closed();
452 /* Reset everything to a pristine state */
454 cf_close(capture_file *cf)
456 /* do GUI things even if file is already closed,
457 * e.g. to cleanup things if a capture couldn't be started */
458 cf_callback_invoke(cf_cb_file_closing, cf);
460 /* close things, if not already closed before */
461 if(cf->state != FILE_CLOSED) {
462 color_filters_cleanup();
464 cleanup_dissection();
467 cf_callback_invoke(cf_cb_file_closed, cf);
470 /* an out of memory exception occured, wait for a user button press to exit */
471 static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
476 static float calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos){
480 progbar_val = (gfloat) file_pos / (gfloat) size;
481 if (progbar_val > 1.0) {
482 /* The file probably grew while we were reading it.
483 Update file size, and try again. */
484 size = wtap_file_size(cf->wth, NULL);
486 progbar_val = (gfloat) file_pos / (gfloat) size;
487 /* If it's still > 1, either "wtap_file_size()" failed (in which
488 case there's not much we can do about it), or the file
489 *shrank* (in which case there's not much we can do about
490 it); just clip the progress value at 1.0. */
491 if (progbar_val > 1.0f)
498 cf_read(capture_file *cf, gboolean from_save)
502 const gchar *name_ptr;
504 char errmsg_errno[1024+1];
506 progdlg_t *volatile progbar = NULL;
508 volatile gint64 size;
509 volatile float progbar_val;
511 gchar status_str[100];
512 volatile gint64 progbar_nextstep;
513 volatile gint64 progbar_quantum;
515 gboolean filtering_tap_listeners;
517 volatile int count = 0;
519 volatile int displayed_once = 0;
523 /* Compile the current display filter.
524 * We assume this will not fail since cf->dfilter is only set in
525 * cf_filter IFF the filter was valid.
527 compiled = dfilter_compile(cf->dfilter, &dfcode);
528 g_assert(!cf->dfilter || (compiled && dfcode));
530 /* Do we have any tap listeners with filters? */
531 filtering_tap_listeners = have_filtering_tap_listeners();
533 /* Get the union of the flags for all tap listeners. */
534 tap_flags = union_of_tap_listener_flags();
536 reset_tap_listeners();
538 name_ptr = get_basename(cf->filename);
540 if (from_save == FALSE)
541 cf_callback_invoke(cf_cb_file_read_started, cf);
543 cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr);
545 /* Find the size of the file. */
546 size = wtap_file_size(cf->wth, NULL);
548 /* Update the progress bar when it gets to this value. */
549 progbar_nextstep = 0;
550 /* When we reach the value that triggers a progress bar update,
551 bump that value by this amount. */
553 progbar_quantum = size/N_PROGBAR_UPDATES;
554 if (progbar_quantum < MIN_QUANTUM)
555 progbar_quantum = MIN_QUANTUM;
558 /* Progress so far. */
561 #ifdef NEW_PACKET_LIST
562 new_packet_list_freeze();
564 packet_list_freeze();
568 g_get_current_time(&start_time);
570 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
573 /* Create the progress bar if necessary.
574 * Check wether it should be created or not every MIN_NUMBER_OF_PACKET
576 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
577 progbar_val = calc_progbar_val( cf, size, data_offset);
578 if (from_save == FALSE)
579 progbar = delayed_create_progress_dlg("Loading", name_ptr,
580 TRUE, &stop_flag, &start_time, progbar_val);
582 progbar = delayed_create_progress_dlg("Saving", name_ptr,
583 TRUE, &stop_flag, &start_time, progbar_val);
586 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
587 when we update it, we have to run the GTK+ main loop to get it
588 to repaint what's pending, and doing so may involve an "ioctl()"
589 to see if there's any pending input from an X server, and doing
590 that for every packet can be costly, especially on a big file. */
591 if (data_offset >= progbar_nextstep) {
592 if (progbar != NULL) {
593 progbar_val = calc_progbar_val( cf, size, data_offset);
594 /* update the packet lists content on the first run or frequently on very large files */
595 /* (on smaller files the display update takes longer than reading the file) */
597 if (progbar_quantum > 500000 || displayed_once == 0) {
598 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
600 #ifdef NEW_PACKET_LIST
601 new_packet_list_thaw();
602 if (auto_scroll_live)
603 new_packet_list_moveto_end();
604 new_packet_list_freeze();
607 if (auto_scroll_live)
608 packet_list_moveto_end();
609 packet_list_freeze();
610 #endif /* NEW_PACKET_LIST */
613 #endif /* HAVE_LIBPCAP */
614 g_snprintf(status_str, sizeof(status_str),
615 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
616 data_offset / 1024, size / 1024);
617 update_progress_dlg(progbar, progbar_val, status_str);
619 progbar_nextstep += progbar_quantum;
624 /* Well, the user decided to abort the read. He/She will be warned and
625 it might be enough for him/her to work with the already loaded
627 This is especially true for very large capture files, where you don't
628 want to wait loading the whole file (which may last minutes or even
629 hours even on fast machines) just to see that it was the wrong file. */
633 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
635 CATCH(OutOfMemoryError) {
638 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
639 "%sOut Of Memory!%s\n"
641 "Sorry, but Wireshark has to terminate now!\n"
643 "Some infos / workarounds can be found at:\n"
644 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
645 simple_dialog_primary_start(), simple_dialog_primary_end());
646 /* we have to terminate, as we cannot recover from the memory error */
647 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
649 main_window_update();
650 /* XXX - how to avoid a busy wait? */
658 /* Cleanup and release all dfilter resources */
660 dfilter_free(dfcode);
663 /* We're done reading the file; destroy the progress bar if it was created. */
665 destroy_progress_dlg(progbar);
667 /* We're done reading sequentially through the file. */
668 cf->state = FILE_READ_DONE;
670 /* Close the sequential I/O side, to free up memory it requires. */
671 wtap_sequential_close(cf->wth);
673 /* Allow the protocol dissectors to free up memory that they
674 * don't need after the sequential run-through of the packets. */
675 postseq_cleanup_all_protocols();
677 /* compute the time it took to load the file */
678 compute_elapsed(&start_time);
680 /* Set the file encapsulation type now; we don't know what it is until
681 we've looked at all the packets, as we don't know until then whether
682 there's more than one type (and thus whether it's
683 WTAP_ENCAP_PER_PACKET). */
684 cf->lnk_t = wtap_file_encap(cf->wth);
686 cf->current_frame = cf->first_displayed;
689 #ifdef NEW_PACKET_LIST
690 new_packet_list_thaw();
694 if (from_save == FALSE)
695 cf_callback_invoke(cf_cb_file_read_finished, cf);
697 cf_callback_invoke(cf_cb_file_save_finished, cf);
699 /* If we have any displayed packets to select, select the first of those
700 packets by making the first row the selected row. */
701 if (cf->first_displayed != NULL){
702 #ifdef NEW_PACKET_LIST
703 new_packet_list_select_first_row();
705 packet_list_select_row(0);
706 #endif /* NEW_PACKET_LIST */
710 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
711 "%sFile loading was cancelled!%s\n"
713 "The remaining packets in the file were discarded.\n"
715 "As a lot of packets from the original file will be missing,\n"
716 "remember to be careful when saving the current content to a file.\n",
717 simple_dialog_primary_start(), simple_dialog_primary_end());
718 return CF_READ_ERROR;
722 /* Put up a message box noting that the read failed somewhere along
723 the line. Don't throw out the stuff we managed to read, though,
727 case WTAP_ERR_UNSUPPORTED_ENCAP:
728 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
729 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
732 errmsg = errmsg_errno;
735 case WTAP_ERR_CANT_READ:
736 errmsg = "An attempt to read from the capture file failed for"
737 " some unknown reason.";
740 case WTAP_ERR_SHORT_READ:
741 errmsg = "The capture file appears to have been cut short"
742 " in the middle of a packet.";
745 case WTAP_ERR_BAD_RECORD:
746 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
747 "The capture file appears to be damaged or corrupt.\n(%s)",
750 errmsg = errmsg_errno;
754 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
755 "An error occurred while reading the"
756 " capture file: %s.", wtap_strerror(err));
757 errmsg = errmsg_errno;
760 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
761 return CF_READ_ERROR;
768 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
770 cf_status_t cf_status;
772 cf_status = cf_open(cf, fname, is_tempfile, err);
777 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
779 gint64 data_offset = 0;
781 volatile int newly_displayed_packets = 0;
783 gboolean filtering_tap_listeners;
787 /* Compile the current display filter.
788 * We assume this will not fail since cf->dfilter is only set in
789 * cf_filter IFF the filter was valid.
791 compiled = dfilter_compile(cf->dfilter, &dfcode);
792 g_assert(!cf->dfilter || (compiled && dfcode));
794 /* Do we have any tap listeners with filters? */
795 filtering_tap_listeners = have_filtering_tap_listeners();
797 /* Get the union of the flags for all tap listeners. */
798 tap_flags = union_of_tap_listener_flags();
802 #ifdef NEW_PACKET_LIST
803 new_packet_list_check_end();
804 /* Don't freeze/thaw the list when doing live capture */
805 /*new_packet_list_freeze();*/
807 packet_list_check_end();
808 packet_list_freeze();
811 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
813 while (to_read != 0) {
814 wtap_cleareof(cf->wth);
815 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
818 if (cf->state == FILE_READ_ABORTED) {
819 /* Well, the user decided to exit Wireshark. Break out of the
820 loop, and let the code below (which is called even if there
821 aren't any packets left to read) exit. */
825 if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
826 data_offset) != -1) {
827 newly_displayed_packets++;
830 CATCH(OutOfMemoryError) {
833 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
834 "%sOut Of Memory!%s\n"
836 "Sorry, but Wireshark has to terminate now!\n"
838 "The capture file is not lost, it can be found at:\n"
841 "Some infos / workarounds can be found at:\n"
842 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
843 simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
844 /* we have to terminate, as we cannot recover from the memory error */
845 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
847 main_window_update();
848 /* XXX - how to avoid a busy wait? */
851 #ifdef NEW_PACKET_LIST
852 /* Don't freeze/thaw the list when doing live capture */
853 /*new_packet_list_thaw();*/
857 return CF_READ_ABORTED;
863 /* Cleanup and release all dfilter resources */
865 dfilter_free(dfcode);
868 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
869 cf->count, cf->state, *err);*/
871 #ifdef NEW_PACKET_LIST
872 /* Don't freeze/thaw the list when doing live capture */
873 /*new_packet_list_thaw();*/
874 /* With the new packet list the first packet
875 * isn't automatically selected.
877 if(!cf->current_frame)
878 new_packet_list_select_first_row();
880 /* XXX - this causes "flickering" of the list */
884 /* moving to the end of the packet list - if the user requested so and
885 we have some new packets. */
886 if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL)
887 #ifdef NEW_PACKET_LIST
888 new_packet_list_moveto_end();
890 /* this doesn't seem to work well with a frozen GTK_Clist, so do this after
891 packet_list_thaw() is done, see bugzilla 1188 */
892 /* XXX - this cheats and looks inside the packet list to find the final
894 packet_list_moveto_end();
895 #endif /* NEW_PACKET_LIST */
897 if (cf->state == FILE_READ_ABORTED) {
898 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
899 so that our caller can kill off the capture child process;
900 this will cause an EOF on the pipe from the child, so
901 "cf_finish_tail()" will be called, and it will clean up
903 return CF_READ_ABORTED;
904 } else if (*err != 0) {
905 /* We got an error reading the capture file.
906 XXX - pop up a dialog box instead? */
907 g_warning("Error \"%s\" while reading: \"%s\"\n",
908 wtap_strerror(*err), cf->filename);
910 return CF_READ_ERROR;
916 cf_fake_continue_tail(capture_file *cf) {
917 cf->state = FILE_READ_DONE;
921 cf_finish_tail(capture_file *cf, int *err)
926 gboolean filtering_tap_listeners;
930 /* Compile the current display filter.
931 * We assume this will not fail since cf->dfilter is only set in
932 * cf_filter IFF the filter was valid.
934 compiled = dfilter_compile(cf->dfilter, &dfcode);
935 g_assert(!cf->dfilter || (compiled && dfcode));
937 /* Do we have any tap listeners with filters? */
938 filtering_tap_listeners = have_filtering_tap_listeners();
940 /* Get the union of the flags for all tap listeners. */
941 tap_flags = union_of_tap_listener_flags();
943 if(cf->wth == NULL) {
945 return CF_READ_ERROR;
948 #ifdef NEW_PACKET_LIST
949 new_packet_list_check_end();
950 /* Don't freeze/thaw the list when doing live capture */
951 /*new_packet_list_freeze();*/
953 packet_list_check_end();
954 packet_list_freeze();
957 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
958 if (cf->state == FILE_READ_ABORTED) {
959 /* Well, the user decided to abort the read. Break out of the
960 loop, and let the code below (which is called even if there
961 aren't any packets left to read) exit. */
964 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
967 /* Cleanup and release all dfilter resources */
969 dfilter_free(dfcode);
972 #ifdef NEW_PACKET_LIST
973 /* Don't freeze/thaw the list when doing live capture */
974 /*new_packet_list_thaw();*/
979 if (cf->state == FILE_READ_ABORTED) {
980 /* Well, the user decided to abort the read. We're only called
981 when the child capture process closes the pipe to us (meaning
982 it's probably exited), so we can just close the capture
983 file; we return CF_READ_ABORTED so our caller can do whatever
984 is appropriate when that happens. */
986 return CF_READ_ABORTED;
989 if (auto_scroll_live && cf->plist_end != NULL)
990 #ifdef NEW_PACKET_LIST
991 new_packet_list_moveto_end();
993 /* XXX - this cheats and looks inside the packet list to find the final
995 packet_list_moveto_end();
998 /* We're done reading sequentially through the file. */
999 cf->state = FILE_READ_DONE;
1001 /* We're done reading sequentially through the file; close the
1002 sequential I/O side, to free up memory it requires. */
1003 wtap_sequential_close(cf->wth);
1005 /* Allow the protocol dissectors to free up memory that they
1006 * don't need after the sequential run-through of the packets. */
1007 postseq_cleanup_all_protocols();
1009 /* Set the file encapsulation type now; we don't know what it is until
1010 we've looked at all the packets, as we don't know until then whether
1011 there's more than one type (and thus whether it's
1012 WTAP_ENCAP_PER_PACKET). */
1013 cf->lnk_t = wtap_file_encap(cf->wth);
1016 /* We got an error reading the capture file.
1017 XXX - pop up a dialog box? */
1018 return CF_READ_ERROR;
1023 #endif /* HAVE_LIBPCAP */
1026 cf_get_display_name(capture_file *cf)
1028 const gchar *displayname;
1030 /* Return a name to use in displays */
1031 if (!cf->is_tempfile) {
1032 /* Get the last component of the file name, and use that. */
1034 displayname = get_basename(cf->filename);
1036 displayname="(No file)";
1039 /* The file we read is a temporary file from a live capture;
1040 we don't mention its name. */
1042 displayname = cf->source;
1044 displayname = "(Untitled)";
1050 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1056 cf->source = g_strdup(source);
1058 cf->source = g_strdup("");
1062 const gchar *cf_get_tempfile_source(capture_file *cf) {
1070 /* XXX - use a macro instead? */
1072 cf_get_packet_count(capture_file *cf)
1077 /* XXX - use a macro instead? */
1079 cf_set_packet_count(capture_file *cf, int packet_count)
1081 cf->count = packet_count;
1084 /* XXX - use a macro instead? */
1086 cf_is_tempfile(capture_file *cf)
1088 return cf->is_tempfile;
1091 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1093 cf->is_tempfile = is_tempfile;
1097 /* XXX - use a macro instead? */
1098 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1100 cf->drops_known = drops_known;
1103 /* XXX - use a macro instead? */
1104 void cf_set_drops(capture_file *cf, guint32 drops)
1109 /* XXX - use a macro instead? */
1110 gboolean cf_get_drops_known(capture_file *cf)
1112 return cf->drops_known;
1115 /* XXX - use a macro instead? */
1116 guint32 cf_get_drops(capture_file *cf)
1121 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1123 cf->rfcode = rfcode;
1126 #ifdef NEW_PACKET_LIST
1128 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1129 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1131 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1133 gboolean add_to_packet_list)
1135 gboolean create_proto_tree = FALSE;
1140 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1142 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1143 &first_ts, &prev_dis_ts, &prev_cap_ts);
1146 + we have a display filter and are re-applying it;
1147 + we have tap listeners with filters;
1148 + we have tap listeners that require a protocol tree;
1150 allocate a protocol tree root node, so that we'll construct
1151 a protocol tree against which a filter expression can be
1153 if ((dfcode != NULL && refilter) ||
1154 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1155 create_proto_tree = TRUE;
1157 /* Dissect the frame. */
1158 epan_dissect_init(&edt, create_proto_tree, FALSE);
1160 if (dfcode != NULL && refilter) {
1161 epan_dissect_prime_dfilter(&edt, dfcode);
1164 tap_queue_init(&edt);
1165 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1166 tap_push_tapped_queue(&edt);
1168 /* If we have a display filter, apply it if we're refiltering, otherwise
1169 leave the "passed_dfilter" flag alone.
1171 If we don't have a display filter, set "passed_dfilter" to 1. */
1172 if (dfcode != NULL) {
1174 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1177 fdata->flags.passed_dfilter = 1;
1179 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1180 cf->displayed_count++;
1182 if (add_to_packet_list) {
1183 /* We fill the needed columns from new_packet_list */
1184 row = new_packet_list_append(cinfo, fdata, &edt.pi);
1187 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1189 frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1191 /* If we haven't yet seen the first frame, this is it.
1193 XXX - we must do this before we add the row to the display,
1194 as, if the display's GtkCList's selection mode is
1195 GTK_SELECTION_BROWSE, when the first entry is added to it,
1196 "cf_select_packet()" will be called, and it will fetch the row
1197 data for the 0th row, and will get a null pointer rather than
1198 "fdata", as "gtk_clist_append()" won't yet have returned and
1199 thus "gtk_clist_set_row_data()" won't yet have been called.
1201 We thus need to leave behind bread crumbs so that
1202 "cf_select_packet()" can find this frame. See the comment
1203 in "cf_select_packet()". */
1204 if (cf->first_displayed == NULL)
1205 cf->first_displayed = fdata;
1207 /* This is the last frame we've seen so far. */
1208 cf->last_displayed = fdata;
1211 epan_dissect_cleanup(&edt);
1218 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1219 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1221 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1223 gboolean add_to_packet_list _U_)
1225 gboolean create_proto_tree = FALSE;
1232 /* just add some value here until we know if it is being displayed or not */
1233 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1235 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1236 &first_ts, &prev_dis_ts, &prev_cap_ts);
1240 we have a display filter and are re-applying it;
1242 we have a list of color filters;
1244 we have tap listeners with filters;
1246 we have tap listeners that require a protocol tree;
1248 we have custom columns;
1250 allocate a protocol tree root node, so that we'll construct
1251 a protocol tree against which a filter expression can be
1253 if ((dfcode != NULL && refilter) ||
1254 color_filters_used() ||
1255 have_custom_cols(cinfo) ||
1256 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1257 create_proto_tree = TRUE;
1259 /* Dissect the frame. */
1260 epan_dissect_init(&edt, create_proto_tree, FALSE);
1262 if (dfcode != NULL && refilter) {
1263 epan_dissect_prime_dfilter(&edt, dfcode);
1266 /* prepare color filters */
1267 color_filters_prime_edt(&edt);
1268 col_custom_prime_edt(&edt, cinfo);
1270 tap_queue_init(&edt);
1271 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1272 tap_push_tapped_queue(&edt);
1274 /* If we have a display filter, apply it if we're refiltering, otherwise
1275 leave the "passed_dfilter" flag alone.
1277 If we don't have a display filter, set "passed_dfilter" to 1. */
1278 if (dfcode != NULL) {
1280 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1283 fdata->flags.passed_dfilter = 1;
1285 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) )
1287 frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1289 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
1291 /* If we haven't yet seen the first frame, this is it.
1293 XXX - we must do this before we add the row to the display,
1294 as, if the display's GtkCList's selection mode is
1295 GTK_SELECTION_BROWSE, when the first entry is added to it,
1296 "cf_select_packet()" will be called, and it will fetch the row
1297 data for the 0th row, and will get a null pointer rather than
1298 "fdata", as "gtk_clist_append()" won't yet have returned and
1299 thus "gtk_clist_set_row_data()" won't yet have been called.
1301 We thus need to leave behind bread crumbs so that
1302 "cf_select_packet()" can find this frame. See the comment
1303 in "cf_select_packet()". */
1304 if (cf->first_displayed == NULL)
1305 cf->first_displayed = fdata;
1307 /* This is the last frame we've seen so far. */
1308 cf->last_displayed = fdata;
1310 row = packet_list_append(cinfo->col_data, fdata);
1312 /* colorize packet: first apply color filters
1313 * then if packet is marked, use preferences to overwrite color
1314 * we do both to make sure that when a packet gets un-marked, the
1315 * color will be correctly set (fixes bug 2038)
1317 fdata->color_filter = color_filters_colorize_packet(row, &edt);
1318 if (fdata->flags.marked) {
1319 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
1321 if (fdata->flags.ignored) {
1322 packet_list_set_colors(row, &prefs.gui_ignored_fg, &prefs.gui_ignored_bg);
1325 cf->displayed_count++;
1328 epan_dissect_cleanup(&edt);
1333 /* read in a new packet */
1334 /* returns the row of the new packet in the packet list or -1 if not displayed */
1336 read_packet(capture_file *cf, dfilter_t *dfcode,
1337 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1339 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1340 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1341 const guchar *buf = wtap_buf_ptr(cf->wth);
1348 /* Allocate the next list entry, and add it to the list.
1349 * memory chunks have been deprecated in favor of the slice allocator,
1350 * which has been added in 2.10
1352 #if GLIB_CHECK_VERSION(2,10,0)
1353 fdata = g_slice_new(frame_data);
1355 fdata = g_mem_chunk_alloc(cf->plist_chunk);
1358 frame_data_init(fdata, cf->count, phdr, offset, cum_bytes);
1360 #ifdef NEW_PACKET_LIST
1361 fdata->col_text_len = se_alloc0(sizeof(fdata->col_text_len) * (cf->cinfo.num_cols));
1362 fdata->col_text = se_alloc0(sizeof(fdata->col_text) * (cf->cinfo.num_cols));
1368 epan_dissect_init(&edt, TRUE, FALSE);
1369 epan_dissect_prime_dfilter(&edt, cf->rfcode);
1370 epan_dissect_run(&edt, pseudo_header, buf, fdata, NULL);
1371 passed = dfilter_apply_edt(cf->rfcode, &edt);
1372 epan_dissect_cleanup(&edt);
1376 cap_file_add_fdata(cf, fdata);
1378 cf->f_datalen = offset + fdata->cap_len;
1380 if (!cf->redissecting) {
1381 row = add_packet_to_packet_list(fdata, cf, dfcode,
1382 filtering_tap_listeners, tap_flags,
1383 pseudo_header, buf, TRUE, TRUE);
1386 /* We didn't pass read filter so roll back count */
1389 /* XXX - if we didn't have read filters, or if we could avoid
1390 allocating the "frame_data" structure until we knew whether
1391 the frame passed the read filter, we could use a G_ALLOC_ONLY
1394 ...but, at least in one test I did, where I just made the chunk
1395 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
1396 seem to save a noticeable amount of time or space. */
1397 #if GLIB_CHECK_VERSION(2,10,0)
1398 /* memory chunks have been deprecated in favor of the slice allocator,
1399 * which has been added in 2.10
1401 g_slice_free(frame_data,fdata);
1403 g_mem_chunk_free(cf->plist_chunk, fdata);
1411 cf_merge_files(char **out_filenamep, int in_file_count,
1412 char *const *in_filenames, int file_type, gboolean do_append)
1414 merge_in_file_t *in_files;
1420 int open_err, read_err, write_err, close_err;
1424 char errmsg_errno[1024+1];
1426 gboolean got_read_error = FALSE, got_write_error = FALSE;
1428 progdlg_t *progbar = NULL;
1430 gint64 f_len, file_pos;
1432 GTimeVal start_time;
1433 gchar status_str[100];
1434 gint64 progbar_nextstep;
1435 gint64 progbar_quantum;
1437 /* open the input files */
1438 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1439 &open_err, &err_info, &err_fileno)) {
1441 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1446 if (*out_filenamep != NULL) {
1447 out_filename = *out_filenamep;
1448 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1452 out_fd = create_tempfile(&tmpname, "wireshark");
1455 out_filename = g_strdup(tmpname);
1456 *out_filenamep = out_filename;
1460 merge_close_in_files(in_file_count, in_files);
1462 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1466 pdh = wtap_dump_fdopen(out_fd, file_type,
1467 merge_select_frame_type(in_file_count, in_files),
1468 merge_max_snapshot_length(in_file_count, in_files),
1469 FALSE /* compressed */, &open_err);
1472 merge_close_in_files(in_file_count, in_files);
1474 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1479 /* Get the sum of the sizes of all the files. */
1481 for (i = 0; i < in_file_count; i++)
1482 f_len += in_files[i].size;
1484 /* Update the progress bar when it gets to this value. */
1485 progbar_nextstep = 0;
1486 /* When we reach the value that triggers a progress bar update,
1487 bump that value by this amount. */
1488 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1489 /* Progress so far. */
1493 g_get_current_time(&start_time);
1495 /* do the merge (or append) */
1498 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1501 wth = merge_read_packet(in_file_count, in_files, &read_err,
1505 got_read_error = TRUE;
1509 /* Get the sum of the data offsets in all of the files. */
1511 for (i = 0; i < in_file_count; i++)
1512 data_offset += in_files[i].data_offset;
1514 /* Create the progress bar if necessary.
1515 We check on every iteration of the loop, so that it takes no
1516 longer than the standard time to create it (otherwise, for a
1517 large file, we might take considerably longer than that standard
1518 time in order to get to the next progress bar step). */
1519 if (progbar == NULL) {
1520 progbar = delayed_create_progress_dlg("Merging", "files",
1521 FALSE, &stop_flag, &start_time, progbar_val);
1524 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1525 when we update it, we have to run the GTK+ main loop to get it
1526 to repaint what's pending, and doing so may involve an "ioctl()"
1527 to see if there's any pending input from an X server, and doing
1528 that for every packet can be costly, especially on a big file. */
1529 if (data_offset >= progbar_nextstep) {
1530 /* Get the sum of the seek positions in all of the files. */
1532 for (i = 0; i < in_file_count; i++)
1533 file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1534 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1535 if (progbar_val > 1.0f) {
1536 /* Some file probably grew while we were reading it.
1537 That "shouldn't happen", so we'll just clip the progress
1541 if (progbar != NULL) {
1542 g_snprintf(status_str, sizeof(status_str),
1543 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1544 file_pos / 1024, f_len / 1024);
1545 update_progress_dlg(progbar, progbar_val, status_str);
1547 progbar_nextstep += progbar_quantum;
1551 /* Well, the user decided to abort the merge. */
1555 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1556 wtap_buf_ptr(wth), &write_err)) {
1557 got_write_error = TRUE;
1562 /* We're done merging the files; destroy the progress bar if it was created. */
1563 if (progbar != NULL)
1564 destroy_progress_dlg(progbar);
1566 merge_close_in_files(in_file_count, in_files);
1567 if (!got_read_error && !got_write_error) {
1568 if (!wtap_dump_close(pdh, &write_err))
1569 got_write_error = TRUE;
1571 wtap_dump_close(pdh, &close_err);
1573 if (got_read_error) {
1575 * Find the file on which we got the error, and report the error.
1577 for (i = 0; i < in_file_count; i++) {
1578 if (in_files[i].state == GOT_ERROR) {
1579 /* Put up a message box noting that a read failed somewhere along
1583 case WTAP_ERR_UNSUPPORTED_ENCAP:
1584 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1585 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1588 errmsg = errmsg_errno;
1591 case WTAP_ERR_CANT_READ:
1592 errmsg = "An attempt to read from the capture file %s failed for"
1593 " some unknown reason.";
1596 case WTAP_ERR_SHORT_READ:
1597 errmsg = "The capture file %s appears to have been cut short"
1598 " in the middle of a packet.";
1601 case WTAP_ERR_BAD_RECORD:
1602 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1603 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1606 errmsg = errmsg_errno;
1610 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1611 "An error occurred while reading the"
1612 " capture file %%s: %s.", wtap_strerror(read_err));
1613 errmsg = errmsg_errno;
1616 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
1621 if (got_write_error) {
1622 /* Put up an alert box for the write error. */
1623 cf_write_failure_alert_box(out_filename, write_err);
1626 if (got_read_error || got_write_error || stop_flag) {
1627 /* Callers aren't expected to treat an error or an explicit abort
1628 differently - we put up error dialogs ourselves, so they don't
1636 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1638 const char *filter_new = dftext ? dftext : "";
1639 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1641 GTimeVal start_time;
1643 /* if new filter equals old one, do nothing unless told to do so */
1644 if (!force && strcmp(filter_new, filter_old) == 0) {
1650 if (dftext == NULL) {
1651 /* The new filter is an empty filter (i.e., display all packets).
1652 * so leave dfcode==NULL
1656 * We have a filter; make a copy of it (as we'll be saving it),
1657 * and try to compile it.
1659 dftext = g_strdup(dftext);
1660 if (!dfilter_compile(dftext, &dfcode)) {
1661 /* The attempt failed; report an error. */
1662 gchar *safe_dftext = simple_dialog_format_message(dftext);
1663 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1665 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1668 "The following display filter isn't a valid display filter:\n%s\n"
1669 "See the help for a description of the display filter syntax.",
1670 simple_dialog_primary_start(), safe_dfilter_error_msg,
1671 simple_dialog_primary_end(), safe_dftext);
1672 g_free(safe_dfilter_error_msg);
1673 g_free(safe_dftext);
1679 if (dfcode == NULL) {
1680 /* Yes - free the filter text, and set it to null. */
1686 /* We have a valid filter. Replace the current filter. */
1687 g_free(cf->dfilter);
1688 cf->dfilter = dftext;
1689 g_get_current_time(&start_time);
1692 /* Now rescan the packet list, applying the new filter, but not
1693 throwing away information constructed on a previous pass. */
1694 if (dftext == NULL) {
1695 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1697 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1700 /* Cleanup and release all dfilter resources */
1701 dfilter_free(dfcode);
1707 cf_colorize_packets(capture_file *cf)
1709 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1713 cf_reftime_packets(capture_file *cf)
1716 #ifdef NEW_PACKET_LIST
1717 ref_time_packets(cf);
1719 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1724 cf_redissect_packets(capture_file *cf)
1726 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1730 cf_read_frame_r(capture_file *cf, frame_data *fdata,
1731 union wtap_pseudo_header *pseudo_header, guint8 *pd)
1735 char errmsg_errno[1024+1];
1737 if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
1738 fdata->cap_len, &err, &err_info)) {
1741 case WTAP_ERR_UNSUPPORTED_ENCAP:
1742 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1743 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1748 case WTAP_ERR_BAD_RECORD:
1749 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1750 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
1751 wtap_strerror(err), err_info);
1756 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1757 "An error occurred while reading from the file \"%%s\": %s.",
1758 wtap_strerror(err));
1761 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg_errno, cf->filename);
1768 cf_read_frame(capture_file *cf, frame_data *fdata)
1770 return cf_read_frame_r(cf, fdata, &cf->pseudo_header, cf->pd);
1773 /* Rescan the list of packets, reconstructing the CList.
1775 "action" describes why we're doing this; it's used in the progress
1778 "action_item" describes what we're doing; it's used in the progress
1781 "refilter" is TRUE if we need to re-evaluate the filter expression.
1783 "redissect" is TRUE if we need to make the dissectors reconstruct
1784 any state information they have (because a preference that affects
1785 some dissector has changed, meaning some dissector might construct
1786 its state differently from the way it was constructed the last time). */
1787 #ifdef NEW_PACKET_LIST
1789 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1790 gboolean refilter, gboolean redissect)
1792 /* Rescan packets new packet list */
1794 progdlg_t *progbar = NULL;
1797 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1798 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1799 gboolean selected_frame_seen;
1802 GTimeVal start_time;
1803 gchar status_str[100];
1804 int progbar_nextstep;
1805 int progbar_quantum;
1807 gboolean filtering_tap_listeners;
1809 gboolean add_to_packet_list = FALSE;
1812 /* Compile the current display filter.
1813 * We assume this will not fail since cf->dfilter is only set in
1814 * cf_filter IFF the filter was valid.
1816 compiled = dfilter_compile(cf->dfilter, &dfcode);
1817 g_assert(!cf->dfilter || (compiled && dfcode));
1819 /* Do we have any tap listeners with filters? */
1820 filtering_tap_listeners = have_filtering_tap_listeners();
1822 /* Get the union of the flags for all tap listeners. */
1823 tap_flags = union_of_tap_listener_flags();
1825 reset_tap_listeners();
1826 /* Which frame, if any, is the currently selected frame?
1827 XXX - should the selected frame or the focus frame be the "current"
1828 frame, that frame being the one from which "Find Frame" searches
1830 selected_frame = cf->current_frame;
1832 /* Mark frame num as not found */
1833 selected_frame_num = -1;
1835 /* Freeze the packet list while we redo it, so we don't get any
1836 screen updates while it happens. */
1837 new_packet_list_freeze();
1840 /* We need to re-initialize all the state information that protocols
1841 keep, because some preference that controls a dissector has changed,
1842 which might cause the state information to be constructed differently
1843 by that dissector. */
1845 /* We might receive new packets while redissecting, and we don't
1846 want to dissect those before their time. */
1847 cf->redissecting = TRUE;
1849 /* Cleanup all data structures used for dissection. */
1850 cleanup_dissection();
1851 /* Initialize all data structures used for dissection. */
1854 /* We need to redissect the packets so we have to discard our old
1855 * packet list store. */
1856 new_packet_list_clear();
1857 add_to_packet_list = TRUE;
1860 /* We don't yet know which will be the first and last frames displayed. */
1861 cf->first_displayed = NULL;
1862 cf->last_displayed = NULL;
1864 /* We currently don't display any packets */
1865 cf->displayed_count = 0;
1867 /* Iterate through the list of frames. Call a routine for each frame
1868 to check whether it should be displayed and, if so, add it to
1869 the display list. */
1870 nstime_set_unset(&first_ts);
1871 nstime_set_unset(&prev_dis_ts);
1872 nstime_set_unset(&prev_cap_ts);
1875 /* Update the progress bar when it gets to this value. */
1876 progbar_nextstep = 0;
1877 /* When we reach the value that triggers a progress bar update,
1878 bump that value by this amount. */
1879 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1880 /* Count of packets at which we've looked. */
1882 /* Progress so far. */
1886 g_get_current_time(&start_time);
1888 /* no previous row yet */
1890 prev_frame_num = -1;
1893 preceding_frame_num = -1;
1894 preceding_frame = NULL;
1895 following_frame_num = -1;
1896 following_frame = NULL;
1898 selected_frame_seen = FALSE;
1900 for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
1901 /* Create the progress bar if necessary.
1902 We check on every iteration of the loop, so that it takes no
1903 longer than the standard time to create it (otherwise, for a
1904 large file, we might take considerably longer than that standard
1905 time in order to get to the next progress bar step). */
1906 if (progbar == NULL)
1907 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1908 &stop_flag, &start_time,
1911 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1912 when we update it, we have to run the GTK+ main loop to get it
1913 to repaint what's pending, and doing so may involve an "ioctl()"
1914 to see if there's any pending input from an X server, and doing
1915 that for every packet can be costly, especially on a big file. */
1916 if (count >= progbar_nextstep) {
1917 /* let's not divide by zero. I should never be started
1918 * with count == 0, so let's assert that
1920 g_assert(cf->count > 0);
1921 progbar_val = (gfloat) count / cf->count;
1923 if (progbar != NULL) {
1924 g_snprintf(status_str, sizeof(status_str),
1925 "%4u of %u frames", count, cf->count);
1926 update_progress_dlg(progbar, progbar_val, status_str);
1929 progbar_nextstep += progbar_quantum;
1933 /* Well, the user decided to abort the filtering. Just stop.
1935 XXX - go back to the previous filter? Users probably just
1936 want not to wait for a filtering operation to finish;
1937 unless we cancel by having no filter, reverting to the
1938 previous filter will probably be even more expensive than
1939 continuing the filtering, as it involves going back to the
1940 beginning and filtering, and even with no filter we currently
1941 have to re-generate the entire clist, which is also expensive.
1943 I'm not sure what Network Monitor does, but it doesn't appear
1944 to give you an unfiltered display if you cancel. */
1951 /* Since all state for the frame was destroyed, mark the frame
1952 * as not visited, free the GSList referring to the state
1953 * data (the per-frame data itself was freed by
1954 * "init_dissection()"), and null out the GSList pointer. */
1955 fdata->flags.visited = 0;
1956 frame_data_cleanup(fdata);
1958 /* cleanup_dissection() calls se_free_all();
1959 * And after that fdata->col_text (which is allocated using se_alloc0())
1960 * no longer points to valid memory.
1962 fdata->col_text_len = se_alloc0(sizeof(fdata->col_text_len) * (cf->cinfo.num_cols));
1963 fdata->col_text = se_alloc0(sizeof(fdata->col_text) * (cf->cinfo.num_cols));
1966 if (!cf_read_frame(cf, fdata))
1967 break; /* error reading the frame */
1969 /* If the previous frame is displayed, and we haven't yet seen the
1970 selected frame, remember that frame - it's the closest one we've
1971 yet seen before the selected frame. */
1972 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1973 preceding_frame_num = prev_frame_num;
1974 preceding_frame = prev_frame;
1976 add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1977 tap_flags, &cf->pseudo_header, cf->pd,
1979 add_to_packet_list);
1981 /* If this frame is displayed, and this is the first frame we've
1982 seen displayed after the selected frame, remember this frame -
1983 it's the closest one we've yet seen at or after the selected
1985 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1986 following_frame_num = fdata->num;
1987 following_frame = fdata;
1989 if (fdata == selected_frame) {
1990 selected_frame_seen = TRUE;
1991 if (fdata->flags.passed_dfilter)
1992 selected_frame_num = fdata->num;
1995 /* Remember this frame - it'll be the previous frame
1996 on the next pass through the loop. */
1997 prev_frame_num = fdata->num;
2001 /* We are done redissecting the packet list. */
2002 cf->redissecting = FALSE;
2005 /* Clear out what remains of the visited flags and per-frame data
2008 XXX - that may cause various forms of bogosity when dissecting
2009 these frames, as they won't have been seen by this sequential
2010 pass, but the only alternative I see is to keep scanning them
2011 even though the user requested that the scan stop, and that
2012 would leave the user stuck with an Wireshark grinding on
2013 until it finishes. Should we just stick them with that? */
2014 for (; fdata != NULL; fdata = fdata->next) {
2015 fdata->flags.visited = 0;
2016 frame_data_cleanup(fdata);
2020 /* We're done filtering the packets; destroy the progress bar if it
2022 if (progbar != NULL)
2023 destroy_progress_dlg(progbar);
2025 /* Unfreeze the packet list. */
2026 if (!add_to_packet_list)
2027 new_packet_list_recreate_visible_rows();
2029 /* Compute the time it took to filter the file */
2030 compute_elapsed(&start_time);
2032 new_packet_list_thaw();
2034 if (selected_frame_num == -1) {
2035 /* The selected frame didn't pass the filter. */
2036 if (selected_frame == NULL) {
2037 /* That's because there *was* no selected frame. Make the first
2038 displayed frame the current frame. */
2039 selected_frame_num = 0;
2041 /* Find the nearest displayed frame to the selected frame (whether
2042 it's before or after that frame) and make that the current frame.
2043 If the next and previous displayed frames are equidistant from the
2044 selected frame, choose the next one. */
2045 g_assert(following_frame == NULL ||
2046 following_frame->num >= selected_frame->num);
2047 g_assert(preceding_frame == NULL ||
2048 preceding_frame->num <= selected_frame->num);
2049 if (following_frame == NULL) {
2050 /* No frame after the selected frame passed the filter, so we
2051 have to select the last displayed frame before the selected
2053 selected_frame_num = preceding_frame_num;
2054 selected_frame = preceding_frame;
2055 } else if (preceding_frame == NULL) {
2056 /* No frame before the selected frame passed the filter, so we
2057 have to select the first displayed frame after the selected
2059 selected_frame_num = following_frame_num;
2060 selected_frame = following_frame;
2062 /* Frames before and after the selected frame passed the filter, so
2063 we'll select the previous frame */
2064 selected_frame_num = preceding_frame_num;
2065 selected_frame = preceding_frame;
2070 if (selected_frame_num == -1) {
2071 /* There are no frames displayed at all. */
2072 cf_unselect_packet(cf);
2074 /* Either the frame that was selected passed the filter, or we've
2075 found the nearest displayed frame to that frame. Select it, make
2076 it the focus row, and make it visible. */
2077 /* Set to invalid to force update of packet list and packet details */
2078 cf->current_row = -1;
2079 if (selected_frame_num == 0) {
2080 new_packet_list_select_first_row();
2082 new_packet_list_find_row_from_data(selected_frame, TRUE);
2086 /* Cleanup and release all dfilter resources */
2087 dfilter_free(dfcode);
2093 rescan_packets(capture_file *cf, const char *action, const char *action_item,
2094 gboolean refilter, gboolean redissect)
2097 progdlg_t *progbar = NULL;
2100 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
2101 int selected_row, prev_row, preceding_row, following_row;
2102 gboolean selected_frame_seen;
2105 GTimeVal start_time;
2106 gchar status_str[100];
2107 int progbar_nextstep;
2108 int progbar_quantum;
2110 gboolean filtering_tap_listeners;
2112 gboolean add_to_packet_list = TRUE;
2115 /* Compile the current display filter.
2116 * We assume this will not fail since cf->dfilter is only set in
2117 * cf_filter IFF the filter was valid.
2119 compiled = dfilter_compile(cf->dfilter, &dfcode);
2120 g_assert(!cf->dfilter || (compiled && dfcode));
2122 /* Do we have any tap listeners with filters? */
2123 filtering_tap_listeners = have_filtering_tap_listeners();
2125 /* Get the union of the flags for all tap listeners. */
2126 tap_flags = union_of_tap_listener_flags();
2128 reset_tap_listeners();
2129 /* Which frame, if any, is the currently selected frame?
2130 XXX - should the selected frame or the focus frame be the "current"
2131 frame, that frame being the one from which "Find Frame" searches
2133 selected_frame = cf->current_frame;
2135 /* We don't yet know what row that frame will be on, if any, after we
2136 rebuild the clist, however. */
2139 /* Freeze the packet list while we redo it, so we don't get any
2140 screen updates while it happens. */
2141 packet_list_freeze();
2144 packet_list_clear();
2147 /* We need to re-initialize all the state information that protocols
2148 keep, because some preference that controls a dissector has changed,
2149 which might cause the state information to be constructed differently
2150 by that dissector. */
2152 /* We might receive new packets while redissecting, and we don't
2153 want to dissect those before their time. */
2154 cf->redissecting = TRUE;
2156 /* Cleanup all data structures used for dissection. */
2157 cleanup_dissection();
2158 /* Initialize all data structures used for dissection. */
2163 /* We don't yet know which will be the first and last frames displayed. */
2164 cf->first_displayed = NULL;
2165 cf->last_displayed = NULL;
2169 /* We currently don't display any packets */
2170 cf->displayed_count = 0;
2172 /* Iterate through the list of frames. Call a routine for each frame
2173 to check whether it should be displayed and, if so, add it to
2174 the display list. */
2175 nstime_set_unset(&first_ts);
2176 nstime_set_unset(&prev_dis_ts);
2177 nstime_set_unset(&prev_cap_ts);
2180 /* Update the progress bar when it gets to this value. */
2181 progbar_nextstep = 0;
2182 /* When we reach the value that triggers a progress bar update,
2183 bump that value by this amount. */
2184 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2185 /* Count of packets at which we've looked. */
2187 /* Progress so far. */
2191 g_get_current_time(&start_time);
2193 row = -1; /* no previous row yet */
2198 preceding_frame = NULL;
2200 following_frame = NULL;
2202 selected_frame_seen = FALSE;
2204 for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
2205 /* Create the progress bar if necessary.
2206 We check on every iteration of the loop, so that it takes no
2207 longer than the standard time to create it (otherwise, for a
2208 large file, we might take considerably longer than that standard
2209 time in order to get to the next progress bar step). */
2210 if (progbar == NULL)
2211 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
2212 &stop_flag, &start_time,
2215 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2216 when we update it, we have to run the GTK+ main loop to get it
2217 to repaint what's pending, and doing so may involve an "ioctl()"
2218 to see if there's any pending input from an X server, and doing
2219 that for every packet can be costly, especially on a big file. */
2220 if (count >= progbar_nextstep) {
2221 /* let's not divide by zero. I should never be started
2222 * with count == 0, so let's assert that
2224 g_assert(cf->count > 0);
2225 progbar_val = (gfloat) count / cf->count;
2227 if (progbar != NULL) {
2228 g_snprintf(status_str, sizeof(status_str),
2229 "%4u of %u frames", count, cf->count);
2230 update_progress_dlg(progbar, progbar_val, status_str);
2233 progbar_nextstep += progbar_quantum;
2237 /* Well, the user decided to abort the filtering. Just stop.
2239 XXX - go back to the previous filter? Users probably just
2240 want not to wait for a filtering operation to finish;
2241 unless we cancel by having no filter, reverting to the
2242 previous filter will probably be even more expensive than
2243 continuing the filtering, as it involves going back to the
2244 beginning and filtering, and even with no filter we currently
2245 have to re-generate the entire clist, which is also expensive.
2247 I'm not sure what Network Monitor does, but it doesn't appear
2248 to give you an unfiltered display if you cancel. */
2255 /* Since all state for the frame was destroyed, mark the frame
2256 * as not visited, free the GSList referring to the state
2257 * data (the per-frame data itself was freed by
2258 * "init_dissection()"), and null out the GSList pointer.
2260 fdata->flags.visited = 0;
2261 frame_data_cleanup(fdata);
2264 if (!cf_read_frame(cf, fdata))
2265 break; /* error reading the frame */
2267 /* If the previous frame is displayed, and we haven't yet seen the
2268 selected frame, remember that frame - it's the closest one we've
2269 yet seen before the selected frame. */
2270 if (prev_row != -1 && !selected_frame_seen) {
2271 preceding_row = prev_row;
2272 preceding_frame = prev_frame;
2274 row = add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
2275 tap_flags, &cf->pseudo_header, cf->pd,
2277 add_to_packet_list);
2279 /* If this frame is displayed, and this is the first frame we've
2280 seen displayed after the selected frame, remember this frame -
2281 it's the closest one we've yet seen at or after the selected
2283 if (row != -1 && selected_frame_seen && following_row == -1) {
2284 following_row = row;
2285 following_frame = fdata;
2287 if (fdata == selected_frame) {
2289 selected_frame_seen = TRUE;
2292 /* Remember this row/frame - it'll be the previous row/frame
2293 on the next pass through the loop. */
2298 /* We are done redissecting the packet list. */
2299 cf->redissecting = FALSE;
2302 /* Clear out what remains of the visited flags and per-frame data
2305 XXX - that may cause various forms of bogosity when dissecting
2306 these frames, as they won't have been seen by this sequential
2307 pass, but the only alternative I see is to keep scanning them
2308 even though the user requested that the scan stop, and that
2309 would leave the user stuck with an Wireshark grinding on
2310 until it finishes. Should we just stick them with that? */
2311 for (; fdata != NULL; fdata = fdata->next) {
2312 fdata->flags.visited = 0;
2313 frame_data_cleanup(fdata);
2317 /* We're done filtering the packets; destroy the progress bar if it
2319 if (progbar != NULL)
2320 destroy_progress_dlg(progbar);
2322 /* Unfreeze the packet list. */
2325 if (selected_row == -1) {
2326 /* The selected frame didn't pass the filter. */
2327 if (selected_frame == NULL) {
2328 /* That's because there *was* no selected frame. Make the first
2329 displayed frame the current frame. */
2332 /* Find the nearest displayed frame to the selected frame (whether
2333 it's before or after that frame) and make that the current frame.
2334 If the next and previous displayed frames are equidistant from the
2335 selected frame, choose the next one. */
2336 g_assert(following_frame == NULL ||
2337 following_frame->num >= selected_frame->num);
2338 g_assert(preceding_frame == NULL ||
2339 preceding_frame->num <= selected_frame->num);
2340 if (following_frame == NULL) {
2341 /* No frame after the selected frame passed the filter, so we
2342 have to select the last displayed frame before the selected
2344 selected_row = preceding_row;
2345 } else if (preceding_frame == NULL) {
2346 /* No frame before the selected frame passed the filter, so we
2347 have to select the first displayed frame after the selected
2349 selected_row = following_row;
2351 /* Frames before and after the selected frame passed the filter, so
2352 we'll select the previous frame */
2353 selected_row = preceding_row;
2358 if (selected_row == -1) {
2359 /* There are no frames displayed at all. */
2360 cf_unselect_packet(cf);
2362 /* Either the frame that was selected passed the filter, or we've
2363 found the nearest displayed frame to that frame. Select it, make
2364 it the focus row, and make it visible. */
2365 if (selected_row == 0) {
2366 /* Set to invalid to force update of packet list and packet details */
2367 cf->current_row = -1;
2369 packet_list_set_selected_row(selected_row);
2372 /* Cleanup and release all dfilter resources */
2373 dfilter_free(dfcode);
2375 #endif /* NEW_PACKET_LIST */
2378 * Scan trough all frame data and recalculate the ref time
2379 * without rereading the file.
2380 * XXX - do we need a progres bar or is this fast enough?
2382 #ifdef NEW_PACKET_LIST
2384 ref_time_packets(capture_file *cf)
2388 nstime_set_unset(&first_ts);
2389 nstime_set_unset(&prev_dis_ts);
2392 for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
2393 /* just add some value here until we know if it is being displayed or not */
2394 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
2400 /* If we don't have the time stamp of the first packet in the
2401 capture, it's because this is the first packet. Save the time
2402 stamp of this packet as the time stamp of the first packet. */
2403 if (nstime_is_unset(&first_ts)) {
2404 first_ts = fdata->abs_ts;
2406 /* if this frames is marked as a reference time frame, reset
2407 firstsec and firstusec to this frame */
2408 if(fdata->flags.ref_time){
2409 first_ts = fdata->abs_ts;
2412 /* If we don't have the time stamp of the previous displayed packet,
2413 it's because this is the first displayed packet. Save the time
2414 stamp of this packet as the time stamp of the previous displayed
2416 if (nstime_is_unset(&prev_dis_ts)) {
2417 prev_dis_ts = fdata->abs_ts;
2420 /* Get the time elapsed between the first packet and this packet. */
2421 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
2423 /* If it's greater than the current elapsed time, set the elapsed time
2424 to it (we check for "greater than" so as not to be confused by
2425 time moving backwards). */
2426 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
2427 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
2428 cf->elapsed_time = fdata->rel_ts;
2431 /* Get the time elapsed between the previous displayed packet and
2433 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
2435 prev_dis_ts = fdata->abs_ts;
2440 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
2441 /* This frame either passed the display filter list or is marked as
2442 a time reference frame. All time reference frames are displayed
2443 even if they dont pass the display filter */
2444 if(fdata->flags.ref_time){
2445 /* if this was a TIME REF frame we should reset the cum_bytes field */
2446 cum_bytes = fdata->pkt_len;
2447 fdata->cum_bytes = cum_bytes;
2449 /* increase cum_bytes with this packets length */
2450 cum_bytes += fdata->pkt_len;
2464 process_specified_packets(capture_file *cf, packet_range_t *range,
2465 const char *string1, const char *string2, gboolean terminate_is_stop,
2466 gboolean (*callback)(capture_file *, frame_data *,
2467 union wtap_pseudo_header *, const guint8 *, void *),
2468 void *callback_args)
2471 union wtap_pseudo_header pseudo_header;
2472 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
2473 psp_return_t ret = PSP_FINISHED;
2475 progdlg_t *progbar = NULL;
2478 gboolean progbar_stop_flag;
2479 GTimeVal progbar_start_time;
2480 gchar progbar_status_str[100];
2481 int progbar_nextstep;
2482 int progbar_quantum;
2483 range_process_e process_this;
2485 /* Update the progress bar when it gets to this value. */
2486 progbar_nextstep = 0;
2487 /* When we reach the value that triggers a progress bar update,
2488 bump that value by this amount. */
2489 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2490 /* Count of packets at which we've looked. */
2492 /* Progress so far. */
2495 progbar_stop_flag = FALSE;
2496 g_get_current_time(&progbar_start_time);
2498 packet_range_process_init(range);
2500 /* Iterate through the list of packets, printing the packets that
2501 were selected by the current display filter. */
2502 for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
2503 /* Create the progress bar if necessary.
2504 We check on every iteration of the loop, so that it takes no
2505 longer than the standard time to create it (otherwise, for a
2506 large file, we might take considerably longer than that standard
2507 time in order to get to the next progress bar step). */
2508 if (progbar == NULL)
2509 progbar = delayed_create_progress_dlg(string1, string2,
2512 &progbar_start_time,
2515 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2516 when we update it, we have to run the GTK+ main loop to get it
2517 to repaint what's pending, and doing so may involve an "ioctl()"
2518 to see if there's any pending input from an X server, and doing
2519 that for every packet can be costly, especially on a big file. */
2520 if (progbar_count >= progbar_nextstep) {
2521 /* let's not divide by zero. I should never be started
2522 * with count == 0, so let's assert that
2524 g_assert(cf->count > 0);
2525 progbar_val = (gfloat) progbar_count / cf->count;
2527 if (progbar != NULL) {
2528 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2529 "%4u of %u packets", progbar_count, cf->count);
2530 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2533 progbar_nextstep += progbar_quantum;
2536 if (progbar_stop_flag) {
2537 /* Well, the user decided to abort the operation. Just stop,
2538 and arrange to return PSP_STOPPED to our caller, so they know
2539 it was stopped explicitly. */
2546 /* do we have to process this packet? */
2547 process_this = packet_range_process_packet(range, fdata);
2548 if (process_this == range_process_next) {
2549 /* this packet uninteresting, continue with next one */
2551 } else if (process_this == range_processing_finished) {
2552 /* all interesting packets processed, stop the loop */
2556 /* Get the packet */
2557 if (!cf_read_frame_r(cf, fdata, &pseudo_header, pd)) {
2558 /* Attempt to get the packet failed. */
2562 /* Process the packet */
2563 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
2564 /* Callback failed. We assume it reported the error appropriately. */
2570 /* We're done printing the packets; destroy the progress bar if
2572 if (progbar != NULL)
2573 destroy_progress_dlg(progbar);
2579 gboolean construct_protocol_tree;
2581 } retap_callback_args_t;
2584 retap_packet(capture_file *cf _U_, frame_data *fdata,
2585 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2588 retap_callback_args_t *args = argsp;
2591 epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
2592 tap_queue_init(&edt);
2593 epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
2594 tap_push_tapped_queue(&edt);
2595 epan_dissect_cleanup(&edt);
2601 cf_retap_packets(capture_file *cf)
2603 packet_range_t range;
2604 retap_callback_args_t callback_args;
2605 gboolean filtering_tap_listeners;
2608 /* Do we have any tap listeners with filters? */
2609 filtering_tap_listeners = have_filtering_tap_listeners();
2611 tap_flags = union_of_tap_listener_flags();
2613 /* If any tap listeners have filters, or require the protocol tree,
2614 construct the protocol tree. */
2615 callback_args.construct_protocol_tree = filtering_tap_listeners ||
2616 (tap_flags & TL_REQUIRES_PROTO_TREE);
2618 /* If any tap listeners require the columns, construct them. */
2619 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2621 /* Reset the tap listeners. */
2622 reset_tap_listeners();
2624 /* Iterate through the list of packets, dissecting all packets and
2625 re-running the taps. */
2626 packet_range_init(&range);
2627 packet_range_process_init(&range);
2628 switch (process_specified_packets(cf, &range, "Recalculating statistics on",
2629 "all packets", TRUE, retap_packet,
2632 /* Completed successfully. */
2636 /* Well, the user decided to abort the refiltering.
2637 Return CF_READ_ABORTED so our caller knows they did that. */
2638 return CF_READ_ABORTED;
2641 /* Error while retapping. */
2642 return CF_READ_ERROR;
2645 g_assert_not_reached();
2650 print_args_t *print_args;
2651 gboolean print_header_line;
2652 char *header_line_buf;
2653 int header_line_buf_len;
2654 gboolean print_formfeed;
2655 gboolean print_separator;
2659 } print_callback_args_t;
2662 print_packet(capture_file *cf, frame_data *fdata,
2663 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2666 print_callback_args_t *args = argsp;
2673 gboolean proto_tree_needed;
2674 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2675 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2677 /* Create the protocol tree, and make it visible, if we're printing
2678 the dissection or the hex data.
2679 XXX - do we need it if we're just printing the hex data? */
2681 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2682 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2684 /* Fill in the column information if we're printing the summary
2686 if (args->print_args->print_summary) {
2687 col_custom_prime_edt(&edt, &cf->cinfo);
2688 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2689 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2691 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2693 if (args->print_formfeed) {
2694 if (!new_page(args->print_args->stream))
2697 if (args->print_separator) {
2698 if (!print_line(args->print_args->stream, 0, ""))
2704 * We generate bookmarks, if the output format supports them.
2705 * The name is "__frameN__".
2707 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2709 if (args->print_args->print_summary) {
2710 if (args->print_header_line) {
2711 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2713 args->print_header_line = FALSE; /* we might not need to print any more */
2715 cp = &args->line_buf[0];
2717 for (i = 0; i < cf->cinfo.num_cols; i++) {
2718 /* Find the length of the string for this column. */
2719 column_len = (int) strlen(cf->cinfo.col_data[i]);
2720 if (args->col_widths[i] > column_len)
2721 column_len = args->col_widths[i];
2723 /* Make sure there's room in the line buffer for the column; if not,
2724 double its length. */
2725 line_len += column_len + 1; /* "+1" for space */
2726 if (line_len > args->line_buf_len) {
2727 cp_off = (int) (cp - args->line_buf);
2728 args->line_buf_len = 2 * line_len;
2729 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2730 cp = args->line_buf + cp_off;
2733 /* Right-justify the packet number column. */
2734 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2735 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
2737 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
2739 if (i != cf->cinfo.num_cols - 1)
2745 * Generate a bookmark, using the summary line as the title.
2747 if (!print_bookmark(args->print_args->stream, bookmark_name,
2751 if (!print_line(args->print_args->stream, 0, args->line_buf))
2755 * Generate a bookmark, using "Frame N" as the title, as we're not
2756 * printing the summary line.
2758 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2759 if (!print_bookmark(args->print_args->stream, bookmark_name,
2762 } /* if (print_summary) */
2764 if (args->print_args->print_dissections != print_dissections_none) {
2765 if (args->print_args->print_summary) {
2766 /* Separate the summary line from the tree with a blank line. */
2767 if (!print_line(args->print_args->stream, 0, ""))
2771 /* Print the information in that tree. */
2772 if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
2775 /* Print a blank line if we print anything after this (aka more than one packet). */
2776 args->print_separator = TRUE;
2778 /* Print a header line if we print any more packet summaries */
2779 args->print_header_line = TRUE;
2782 if (args->print_args->print_hex) {
2783 /* Print the full packet data as hex. */
2784 if (!print_hex_data(args->print_args->stream, &edt))
2787 /* Print a blank line if we print anything after this (aka more than one packet). */
2788 args->print_separator = TRUE;
2790 /* Print a header line if we print any more packet summaries */
2791 args->print_header_line = TRUE;
2792 } /* if (args->print_args->print_dissections != print_dissections_none) */
2794 epan_dissect_cleanup(&edt);
2796 /* do we want to have a formfeed between each packet from now on? */
2797 if(args->print_args->print_formfeed) {
2798 args->print_formfeed = TRUE;
2804 epan_dissect_cleanup(&edt);
2809 cf_print_packets(capture_file *cf, print_args_t *print_args)
2812 print_callback_args_t callback_args;
2820 callback_args.print_args = print_args;
2821 callback_args.print_header_line = TRUE;
2822 callback_args.header_line_buf = NULL;
2823 callback_args.header_line_buf_len = 256;
2824 callback_args.print_formfeed = FALSE;
2825 callback_args.print_separator = FALSE;
2826 callback_args.line_buf = NULL;
2827 callback_args.line_buf_len = 256;
2828 callback_args.col_widths = NULL;
2830 if (!print_preamble(print_args->stream, cf->filename)) {
2831 destroy_print_stream(print_args->stream);
2832 return CF_PRINT_WRITE_ERROR;
2835 if (print_args->print_summary) {
2836 /* We're printing packet summaries. Allocate the header line buffer
2837 and get the column widths. */
2838 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2840 /* Find the widths for each of the columns - maximum of the
2841 width of the title and the width of the data - and construct
2842 a buffer with a line containing the column titles. */
2843 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2844 cp = &callback_args.header_line_buf[0];
2846 for (i = 0; i < cf->cinfo.num_cols; i++) {
2847 /* Don't pad the last column. */
2848 if (i == cf->cinfo.num_cols - 1)
2849 callback_args.col_widths[i] = 0;
2851 callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
2852 data_width = get_column_char_width(get_column_format(i));
2853 if (data_width > callback_args.col_widths[i])
2854 callback_args.col_widths[i] = data_width;
2857 /* Find the length of the string for this column. */
2858 column_len = (int) strlen(cf->cinfo.col_title[i]);
2859 if (callback_args.col_widths[i] > column_len)
2860 column_len = callback_args.col_widths[i];
2862 /* Make sure there's room in the line buffer for the column; if not,
2863 double its length. */
2864 line_len += column_len + 1; /* "+1" for space */
2865 if (line_len > callback_args.header_line_buf_len) {
2866 cp_off = (int) (cp - callback_args.header_line_buf);
2867 callback_args.header_line_buf_len = 2 * line_len;
2868 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2869 callback_args.header_line_buf_len + 1);
2870 cp = callback_args.header_line_buf + cp_off;
2873 /* Right-justify the packet number column. */
2874 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2875 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2877 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2879 if (i != cf->cinfo.num_cols - 1)
2884 /* Now start out the main line buffer with the same length as the
2885 header line buffer. */
2886 callback_args.line_buf_len = callback_args.header_line_buf_len;
2887 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2888 } /* if (print_summary) */
2890 /* Iterate through the list of packets, printing the packets we were
2892 ret = process_specified_packets(cf, &print_args->range, "Printing",
2893 "selected packets", TRUE, print_packet,
2896 g_free(callback_args.header_line_buf);
2897 g_free(callback_args.line_buf);
2898 g_free(callback_args.col_widths);
2903 /* Completed successfully. */
2907 /* Well, the user decided to abort the printing.
2909 XXX - note that what got generated before they did that
2910 will get printed if we're piping to a print program; we'd
2911 have to write to a file and then hand that to the print
2912 program to make it actually not print anything. */
2916 /* Error while printing.
2918 XXX - note that what got generated before they did that
2919 will get printed if we're piping to a print program; we'd
2920 have to write to a file and then hand that to the print
2921 program to make it actually not print anything. */
2922 destroy_print_stream(print_args->stream);
2923 return CF_PRINT_WRITE_ERROR;
2926 if (!print_finale(print_args->stream)) {
2927 destroy_print_stream(print_args->stream);
2928 return CF_PRINT_WRITE_ERROR;
2931 if (!destroy_print_stream(print_args->stream))
2932 return CF_PRINT_WRITE_ERROR;
2938 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2939 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2945 /* Create the protocol tree, but don't fill in the column information. */
2946 epan_dissect_init(&edt, TRUE, TRUE);
2947 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2949 /* Write out the information in that tree. */
2950 proto_tree_write_pdml(&edt, fh);
2952 epan_dissect_cleanup(&edt);
2958 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2963 fh = ws_fopen(print_args->file, "w");
2965 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2967 write_pdml_preamble(fh);
2970 return CF_PRINT_WRITE_ERROR;
2973 /* Iterate through the list of packets, printing the packets we were
2975 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2976 "selected packets", TRUE,
2977 write_pdml_packet, fh);
2982 /* Completed successfully. */
2986 /* Well, the user decided to abort the printing. */
2990 /* Error while printing. */
2992 return CF_PRINT_WRITE_ERROR;
2995 write_pdml_finale(fh);
2998 return CF_PRINT_WRITE_ERROR;
3001 /* XXX - check for an error */
3008 write_psml_packet(capture_file *cf, frame_data *fdata,
3009 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3014 gboolean proto_tree_needed;
3016 /* Fill in the column information, only create the protocol tree
3017 if having custom columns. */
3018 proto_tree_needed = have_custom_cols(&cf->cinfo);
3019 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
3020 col_custom_prime_edt(&edt, &cf->cinfo);
3021 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
3022 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
3024 /* Write out the information in that tree. */
3025 proto_tree_write_psml(&edt, fh);
3027 epan_dissect_cleanup(&edt);
3033 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
3038 fh = ws_fopen(print_args->file, "w");
3040 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
3042 write_psml_preamble(fh);
3045 return CF_PRINT_WRITE_ERROR;
3048 /* Iterate through the list of packets, printing the packets we were
3050 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
3051 "selected packets", TRUE,
3052 write_psml_packet, fh);
3057 /* Completed successfully. */
3061 /* Well, the user decided to abort the printing. */
3065 /* Error while printing. */
3067 return CF_PRINT_WRITE_ERROR;
3070 write_psml_finale(fh);
3073 return CF_PRINT_WRITE_ERROR;
3076 /* XXX - check for an error */
3083 write_csv_packet(capture_file *cf, frame_data *fdata,
3084 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3089 gboolean proto_tree_needed;
3091 /* Fill in the column information, only create the protocol tree
3092 if having custom columns. */
3093 proto_tree_needed = have_custom_cols(&cf->cinfo);
3094 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
3095 col_custom_prime_edt(&edt, &cf->cinfo);
3096 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
3097 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
3099 /* Write out the information in that tree. */
3100 proto_tree_write_csv(&edt, fh);
3102 epan_dissect_cleanup(&edt);
3108 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
3113 fh = ws_fopen(print_args->file, "w");
3115 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
3117 write_csv_preamble(fh);
3120 return CF_PRINT_WRITE_ERROR;
3123 /* Iterate through the list of packets, printing the packets we were
3125 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
3126 "selected packets", TRUE,
3127 write_csv_packet, fh);
3132 /* Completed successfully. */
3136 /* Well, the user decided to abort the printing. */
3140 /* Error while printing. */
3142 return CF_PRINT_WRITE_ERROR;
3145 write_csv_finale(fh);
3148 return CF_PRINT_WRITE_ERROR;
3151 /* XXX - check for an error */
3158 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
3159 union wtap_pseudo_header *pseudo_header _U_,
3160 const guint8 *pd, void *argsp)
3164 proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh);
3169 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
3174 fh = ws_fopen(print_args->file, "w");
3177 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
3179 write_carrays_preamble(fh);
3183 return CF_PRINT_WRITE_ERROR;
3186 /* Iterate through the list of packets, printing the packets we were
3188 ret = process_specified_packets(cf, &print_args->range,
3190 "selected packets", TRUE,
3191 write_carrays_packet, fh);
3194 /* Completed successfully. */
3197 /* Well, the user decided to abort the printing. */
3200 /* Error while printing. */
3202 return CF_PRINT_WRITE_ERROR;
3205 write_carrays_finale(fh);
3209 return CF_PRINT_WRITE_ERROR;
3216 #ifndef NEW_PACKET_LIST /* This function is not needed with the new packet list */
3218 /* Scan through the packet list and change all columns that use the
3219 "command-line-specified" time stamp format to use the current
3220 value of that format. */
3222 cf_change_time_formats(capture_file *cf)
3226 progdlg_t *progbar = NULL;
3231 GTimeVal start_time;
3232 gchar status_str[100];
3233 int progbar_nextstep;
3234 int progbar_quantum;
3235 gboolean sorted_by_frame_column;
3237 /* Adjust timestamp precision if auto is selected */
3238 cf_timestamp_auto_precision(cf);
3240 /* Are there any columns with time stamps in the "command-line-specified"
3243 XXX - we have to force the "column is writable" flag on, as it
3244 might be off from the last frame that was dissected. */
3245 col_set_writable(&cf->cinfo, TRUE);
3246 if (!check_col(&cf->cinfo, COL_CLS_TIME) &&
3247 !check_col(&cf->cinfo, COL_ABS_TIME) &&
3248 !check_col(&cf->cinfo, COL_ABS_DATE_TIME) &&
3249 !check_col(&cf->cinfo, COL_REL_TIME) &&
3250 !check_col(&cf->cinfo, COL_DELTA_TIME) &&
3251 !check_col(&cf->cinfo, COL_DELTA_TIME_DIS)) {
3252 /* No, there aren't any columns in that format, so we have no work
3257 /* Freeze the packet list while we redo it, so we don't get any
3258 screen updates while it happens. */
3259 packet_list_freeze();
3261 /* Update the progress bar when it gets to this value. */
3262 progbar_nextstep = 0;
3263 /* When we reach the value that triggers a progress bar update,
3264 bump that value by this amount. */
3265 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3266 /* Count of packets at which we've looked. */
3268 /* Progress so far. */
3271 /* If the rows are currently sorted by the frame column then we know
3272 * the row number of each packet: it's the row number of the previously
3273 * displayed packet + 1.
3275 * Otherwise, if the display is sorted by a different column then we have
3276 * to use the O(N) packet_list_find_row_from_data() (thus making the job
3277 * of changing the time display format O(N**2)).
3279 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
3280 * the row number and walks that many elements down the clist to find
3281 * the appropriate element.)
3283 sorted_by_frame_column = FALSE;
3284 for (i = 0; i < cf->cinfo.num_cols; i++) {
3285 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
3287 sorted_by_frame_column = (i == packet_list_get_sort_column());
3293 g_get_current_time(&start_time);
3295 /* Iterate through the list of packets, checking whether the packet
3296 is in a row of the summary list and, if so, whether there are
3297 any columns that show the time in the "command-line-specified"
3298 format and, if so, update that row. */
3299 for (fdata = cf->plist_start, row = -1; fdata != NULL; fdata = fdata->next) {
3300 /* Create the progress bar if necessary.
3301 We check on every iteration of the loop, so that it takes no
3302 longer than the standard time to create it (otherwise, for a
3303 large file, we might take considerably longer than that standard
3304 time in order to get to the next progress bar step). */
3305 if (progbar == NULL)
3306 progbar = delayed_create_progress_dlg("Changing", "time display",
3307 TRUE, &stop_flag, &start_time, progbar_val);
3309 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3310 when we update it, we have to run the GTK+ main loop to get it
3311 to repaint what's pending, and doing so may involve an "ioctl()"
3312 to see if there's any pending input from an X server, and doing
3313 that for every packet can be costly, especially on a big file. */
3314 if (count >= progbar_nextstep) {
3315 /* let's not divide by zero. I should never be started
3316 * with count == 0, so let's assert that
3318 g_assert(cf->count > 0);
3320 progbar_val = (gfloat) count / cf->count;
3322 if (progbar != NULL) {
3323 g_snprintf(status_str, sizeof(status_str),
3324 "%4u of %u packets", count, cf->count);
3325 update_progress_dlg(progbar, progbar_val, status_str);
3328 progbar_nextstep += progbar_quantum;
3332 /* Well, the user decided to abort the redisplay. Just stop.
3334 XXX - this leaves the time field in the old format in
3335 frames we haven't yet processed. So it goes; should we
3336 simply not offer them the option of stopping? */
3342 /* Find what row this packet is in. */
3343 if (!sorted_by_frame_column) {
3344 /* This function is O(N), so we try to avoid using it... */
3345 row = packet_list_find_row_from_data(fdata);
3347 /* ...which we do by maintaining a count of packets that are
3348 being displayed (i.e., that have passed the display filter),
3349 and using the current value of that count as the row number
3350 (which is why we can only do it when the display is sorted
3351 by the frame number). */
3352 if (fdata->flags.passed_dfilter)
3359 /* This packet is in the summary list, on row "row". */
3361 for (i = 0; i < cf->cinfo.num_cols; i++) {
3362 if (col_has_time_fmt(&cf->cinfo, i)) {
3363 /* This is one of the columns that shows the time in
3364 "command-line-specified" format; update it. */
3365 cf->cinfo.col_buf[i][0] = '\0';
3366 col_set_fmt_time(fdata, &cf->cinfo, cf->cinfo.col_fmt[i], i);
3367 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
3373 /* We're done redisplaying the packets; destroy the progress bar if it
3375 if (progbar != NULL)
3376 destroy_progress_dlg(progbar);
3378 /* Set the column widths of those columns that show the time in
3379 "command-line-specified" format. */
3380 for (i = 0; i < cf->cinfo.num_cols; i++) {
3381 if (col_has_time_fmt(&cf->cinfo, i)) {
3382 packet_list_set_time_width(cf->cinfo.col_fmt[i], i);
3386 /* Unfreeze the packet list. */
3389 #endif /* NEW_PACKET_LIST */
3396 gboolean frame_matched;
3400 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
3401 search_direction dir)
3405 mdata.string = string;
3406 mdata.string_len = strlen(string);
3407 return find_packet(cf, match_protocol_tree, &mdata, dir);
3411 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
3413 match_data *mdata = criterion;
3416 /* Load the frame's data. */
3417 if (!cf_read_frame(cf, fdata)) {
3418 /* Attempt to get the packet failed. */
3422 /* Construct the protocol tree, including the displayed text */
3423 epan_dissect_init(&edt, TRUE, TRUE);
3424 /* We don't need the column information */
3425 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3427 /* Iterate through all the nodes, seeing if they have text that matches. */
3429 mdata->frame_matched = FALSE;
3430 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
3431 epan_dissect_cleanup(&edt);
3432 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3436 match_subtree_text(proto_node *node, gpointer data)
3438 match_data *mdata = (match_data*) data;
3439 const gchar *string = mdata->string;
3440 size_t string_len = mdata->string_len;
3441 capture_file *cf = mdata->cf;
3442 field_info *fi = PNODE_FINFO(node);
3443 gchar label_str[ITEM_LABEL_LENGTH];
3450 g_assert(fi && "dissection with an invisible proto tree?");
3452 if (mdata->frame_matched) {
3453 /* We already had a match; don't bother doing any more work. */
3457 /* Don't match invisible entries. */
3458 if (PROTO_ITEM_IS_HIDDEN(node))
3461 /* was a free format label produced? */
3463 label_ptr = fi->rep->representation;
3465 /* no, make a generic label */
3466 label_ptr = label_str;
3467 proto_item_fill_label(fi, label_str);
3470 /* Does that label match? */
3471 label_len = strlen(label_ptr);
3472 for (i = 0; i < label_len; i++) {
3473 c_char = label_ptr[i];
3475 c_char = toupper(c_char);
3476 if (c_char == string[c_match]) {
3478 if (c_match == string_len) {
3479 /* No need to look further; we have a match */
3480 mdata->frame_matched = TRUE;
3487 /* Recurse into the subtree, if it exists */
3488 if (node->first_child != NULL)
3489 proto_tree_children_foreach(node, match_subtree_text, mdata);
3493 cf_find_packet_summary_line(capture_file *cf, const char *string,
3494 search_direction dir)
3498 mdata.string = string;
3499 mdata.string_len = strlen(string);
3500 return find_packet(cf, match_summary_line, &mdata, dir);
3504 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3506 match_data *mdata = criterion;
3507 const gchar *string = mdata->string;
3508 size_t string_len = mdata->string_len;
3510 const char *info_column;
3511 size_t info_column_len;
3512 match_result result = MR_NOTMATCHED;
3518 /* Load the frame's data. */
3519 if (!cf_read_frame(cf, fdata)) {
3520 /* Attempt to get the packet failed. */
3524 /* Don't bother constructing the protocol tree */
3525 epan_dissect_init(&edt, FALSE, FALSE);
3526 /* Get the column information */
3527 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
3529 /* Find the Info column */
3530 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3531 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
3532 /* Found it. See if we match. */
3533 info_column = edt.pi.cinfo->col_data[colx];
3534 info_column_len = strlen(info_column);
3535 for (i = 0; i < info_column_len; i++) {
3536 c_char = info_column[i];
3538 c_char = toupper(c_char);
3539 if (c_char == string[c_match]) {
3541 if (c_match == string_len) {
3542 result = MR_MATCHED;
3551 epan_dissect_cleanup(&edt);
3558 } cbs_t; /* "Counted byte string" */
3561 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3562 search_direction dir)
3567 info.data_len = string_size;
3569 /* String or hex search? */
3571 /* String search - what type of string? */
3572 switch (cf->scs_type) {
3574 case SCS_ASCII_AND_UNICODE:
3575 return find_packet(cf, match_ascii_and_unicode, &info, dir);
3578 return find_packet(cf, match_ascii, &info, dir);
3581 return find_packet(cf, match_unicode, &info, dir);
3584 g_assert_not_reached();
3588 return find_packet(cf, match_binary, &info, dir);
3592 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3594 cbs_t *info = criterion;
3595 const guint8 *ascii_text = info->data;
3596 size_t textlen = info->data_len;
3597 match_result result;
3603 /* Load the frame's data. */
3604 if (!cf_read_frame(cf, fdata)) {
3605 /* Attempt to get the packet failed. */
3609 result = MR_NOTMATCHED;
3610 buf_len = fdata->pkt_len;
3611 for (i = 0; i < buf_len; i++) {
3614 c_char = toupper(c_char);
3616 if (c_char == ascii_text[c_match]) {
3618 if (c_match == textlen) {
3619 result = MR_MATCHED;
3620 cf->search_pos = i; /* Save the position of the last character
3621 for highlighting the field. */
3632 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
3634 cbs_t *info = criterion;
3635 const guint8 *ascii_text = info->data;
3636 size_t textlen = info->data_len;
3637 match_result result;
3643 /* Load the frame's data. */
3644 if (!cf_read_frame(cf, fdata)) {
3645 /* Attempt to get the packet failed. */
3649 result = MR_NOTMATCHED;
3650 buf_len = fdata->pkt_len;
3651 for (i = 0; i < buf_len; i++) {
3654 c_char = toupper(c_char);
3655 if (c_char == ascii_text[c_match]) {
3657 if (c_match == textlen) {
3658 result = MR_MATCHED;
3659 cf->search_pos = i; /* Save the position of the last character
3660 for highlighting the field. */
3670 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3672 cbs_t *info = criterion;
3673 const guint8 *ascii_text = info->data;
3674 size_t textlen = info->data_len;
3675 match_result result;
3681 /* Load the frame's data. */
3682 if (!cf_read_frame(cf, fdata)) {
3683 /* Attempt to get the packet failed. */
3687 result = MR_NOTMATCHED;
3688 buf_len = fdata->pkt_len;
3689 for (i = 0; i < buf_len; i++) {
3692 c_char = toupper(c_char);
3693 if (c_char == ascii_text[c_match]) {
3696 if (c_match == textlen) {
3697 result = MR_MATCHED;
3698 cf->search_pos = i; /* Save the position of the last character
3699 for highlighting the field. */
3709 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3711 cbs_t *info = criterion;
3712 const guint8 *binary_data = info->data;
3713 size_t datalen = info->data_len;
3714 match_result result;
3719 /* Load the frame's data. */
3720 if (!cf_read_frame(cf, fdata)) {
3721 /* Attempt to get the packet failed. */
3725 result = MR_NOTMATCHED;
3726 buf_len = fdata->pkt_len;
3727 for (i = 0; i < buf_len; i++) {
3728 if (cf->pd[i] == binary_data[c_match]) {
3730 if (c_match == datalen) {
3731 result = MR_MATCHED;
3732 cf->search_pos = i; /* Save the position of the last character
3733 for highlighting the field. */
3743 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3744 search_direction dir)
3746 return find_packet(cf, match_dfilter, sfcode, dir);
3750 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3751 search_direction dir)
3756 if (!dfilter_compile(filter, &sfcode)) {
3758 * XXX - this shouldn't happen, as the filter string is machine
3763 if (sfcode == NULL) {
3765 * XXX - this shouldn't happen, as the filter string is machine
3770 result = find_packet(cf, match_dfilter, sfcode, dir);
3771 dfilter_free(sfcode);
3776 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3778 dfilter_t *sfcode = criterion;
3780 match_result result;
3782 /* Load the frame's data. */
3783 if (!cf_read_frame(cf, fdata)) {
3784 /* Attempt to get the packet failed. */
3788 epan_dissect_init(&edt, TRUE, FALSE);
3789 epan_dissect_prime_dfilter(&edt, sfcode);
3790 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3791 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3792 epan_dissect_cleanup(&edt);
3797 cf_find_packet_marked(capture_file *cf, search_direction dir)
3799 return find_packet(cf, match_marked, NULL, dir);
3803 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3805 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3809 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3811 return find_packet(cf, match_time_reference, NULL, dir);
3815 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3817 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3821 find_packet(capture_file *cf,
3822 match_result (*match_function)(capture_file *, frame_data *, void *),
3823 void *criterion, search_direction dir)
3825 frame_data *start_fd;
3827 frame_data *new_fd = NULL;
3828 progdlg_t *progbar = NULL;
3833 GTimeVal start_time;
3834 gchar status_str[100];
3835 int progbar_nextstep;
3836 int progbar_quantum;
3838 match_result result;
3840 start_fd = cf->current_frame;
3841 if (start_fd != NULL) {
3842 /* Iterate through the list of packets, starting at the packet we've
3843 picked, calling a routine to run the filter on the packet, see if
3844 it matches, and stop if so. */
3848 /* Update the progress bar when it gets to this value. */
3849 progbar_nextstep = 0;
3850 /* When we reach the value that triggers a progress bar update,
3851 bump that value by this amount. */
3852 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3853 /* Progress so far. */
3857 g_get_current_time(&start_time);
3860 title = cf->sfilter?cf->sfilter:"";
3862 /* Create the progress bar if necessary.
3863 We check on every iteration of the loop, so that it takes no
3864 longer than the standard time to create it (otherwise, for a
3865 large file, we might take considerably longer than that standard
3866 time in order to get to the next progress bar step). */
3867 if (progbar == NULL)
3868 progbar = delayed_create_progress_dlg("Searching", title,
3869 FALSE, &stop_flag, &start_time, progbar_val);
3871 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3872 when we update it, we have to run the GTK+ main loop to get it
3873 to repaint what's pending, and doing so may involve an "ioctl()"
3874 to see if there's any pending input from an X server, and doing
3875 that for every packet can be costly, especially on a big file. */
3876 if (count >= progbar_nextstep) {
3877 /* let's not divide by zero. I should never be started
3878 * with count == 0, so let's assert that
3880 g_assert(cf->count > 0);
3882 progbar_val = (gfloat) count / cf->count;
3884 if (progbar != NULL) {
3885 g_snprintf(status_str, sizeof(status_str),
3886 "%4u of %u packets", count, cf->count);
3887 update_progress_dlg(progbar, progbar_val, status_str);
3890 progbar_nextstep += progbar_quantum;
3894 /* Well, the user decided to abort the search. Go back to the
3895 frame where we started. */
3900 /* Go past the current frame. */
3901 if (dir == SD_BACKWARD) {
3902 /* Go on to the previous frame. */
3903 fdata = fdata->prev;
3904 if (fdata == NULL) {
3906 * XXX - other apps have a bit more of a detailed message
3907 * for this, and instead of offering "OK" and "Cancel",
3908 * they offer things such as "Continue" and "Cancel";
3909 * we need an API for popping up alert boxes with
3910 * {Verb} and "Cancel".
3913 if (prefs.gui_find_wrap)
3915 simple_status("Search reached the beginning. Continuing at end.");
3916 fdata = cf->plist_end; /* wrap around */
3920 simple_status("Search reached the beginning.");
3921 fdata = start_fd; /* stay on previous packet */
3925 /* Go on to the next frame. */
3926 fdata = fdata->next;
3927 if (fdata == NULL) {
3928 if (prefs.gui_find_wrap)
3930 simple_status("Search reached the end. Continuing at beginning.");
3931 fdata = cf->plist_start; /* wrap around */
3935 simple_status("Search reached the end.");
3936 fdata = start_fd; /* stay on previous packet */
3943 /* Is this packet in the display? */
3944 if (fdata->flags.passed_dfilter) {
3945 /* Yes. Does it match the search criterion? */
3946 result = (*match_function)(cf, fdata, criterion);
3947 if (result == MR_ERROR) {
3948 /* Error; our caller has reported the error. Go back to the frame
3949 where we started. */
3952 } else if (result == MR_MATCHED) {
3953 /* Yes. Go to the new frame. */
3959 if (fdata == start_fd) {
3960 /* We're back to the frame we were on originally, and that frame
3961 doesn't match the search filter. The search failed. */
3966 /* We're done scanning the packets; destroy the progress bar if it
3968 if (progbar != NULL)
3969 destroy_progress_dlg(progbar);
3972 if (new_fd != NULL) {
3973 #ifdef NEW_PACKET_LIST
3974 /* Find and select */
3975 row = new_packet_list_find_row_from_data(fdata, TRUE);
3977 /* We found a frame. Find what row it's in. */
3978 row = packet_list_find_row_from_data(new_fd);
3979 #endif /* NEW_PACKET_LIST */
3981 /* We didn't find a row even though we know that a frame
3982 * exists that satifies the search criteria. This means that the
3983 * frame isn't being displayed currently so we can't select it. */
3984 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3985 "%sEnd of capture exceeded!%s\n\n"
3986 "The capture file is probably not fully loaded.",
3987 simple_dialog_primary_start(), simple_dialog_primary_end());
3991 #ifndef NEW_PACKET_LIST
3992 /* Select that row, make it the focus row, and make it visible. */
3993 packet_list_set_selected_row(row);
3994 #endif /* NEW_PACKET_LIST */
3995 return TRUE; /* success */
3997 return FALSE; /* failure */
4001 cf_goto_frame(capture_file *cf, guint fnumber)
4006 for (fdata = cf->plist_start; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
4009 if (fdata == NULL) {
4010 /* we didn't find a packet with that packet number */
4011 simple_status("There is no packet number %u.", fnumber);
4012 return FALSE; /* we failed to go to that packet */
4014 if (!fdata->flags.passed_dfilter) {
4015 /* that packet currently isn't displayed */
4016 /* XXX - add it to the set of displayed packets? */
4017 simple_status("Packet number %u isn't displayed.", fnumber);
4018 return FALSE; /* we failed to go to that packet */
4021 #ifdef NEW_PACKET_LIST
4022 row = new_packet_list_find_row_from_data(fdata, TRUE);
4024 /* We found that packet, and it's currently being displayed.
4025 Find what row it's in. */
4026 row = packet_list_find_row_from_data(fdata);
4027 g_assert(row != -1);
4029 /* Select that row, make it the focus row, and make it visible. */
4030 packet_list_set_selected_row(row);
4031 #endif /* NEW_PACKET_LIST */
4032 return TRUE; /* we got to that packet */
4036 cf_goto_top_frame(capture_file *cf _U_)
4038 #ifdef NEW_PACKET_LIST
4039 /* Find and select */
4040 new_packet_list_select_first_row();
4044 frame_data *lowest_fdata = NULL;
4046 for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
4047 if (fdata->flags.passed_dfilter) {
4048 lowest_fdata = fdata;
4053 if (lowest_fdata == NULL) {
4057 /* We found that packet, and it's currently being displayed.
4058 Find what row it's in. */
4059 row = packet_list_find_row_from_data(lowest_fdata);
4060 g_assert(row != -1);
4062 /* Select that row, make it the focus row, and make it visible. */
4063 packet_list_set_selected_row(row);
4064 #endif /* NEW_PACKET_LIST */
4065 return TRUE; /* we got to that packet */
4069 cf_goto_bottom_frame(capture_file *cf _U_) /* cf is unused w/ NEW_PACKET_LIST */
4071 #ifdef NEW_PACKET_LIST
4072 /* Find and select */
4073 new_packet_list_select_last_row();
4077 frame_data *highest_fdata = NULL;
4079 for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
4080 if (fdata->flags.passed_dfilter) {
4081 highest_fdata = fdata;
4085 if (highest_fdata == NULL) {
4089 /* We found that packet, and it's currently being displayed.
4090 Find what row it's in. */
4091 row = packet_list_find_row_from_data(highest_fdata);
4092 g_assert(row != -1);
4094 /* Select that row, make it the focus row, and make it visible. */
4095 packet_list_set_selected_row(row);
4096 #endif /* NEW_PACKET_LIST */
4097 return TRUE; /* we got to that packet */
4101 * Go to frame specified by currently selected protocol tree item.
4104 cf_goto_framenum(capture_file *cf)
4106 header_field_info *hfinfo;
4109 if (cf->finfo_selected) {
4110 hfinfo = cf->finfo_selected->hfinfo;
4112 if (hfinfo->type == FT_FRAMENUM) {
4113 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
4115 return cf_goto_frame(cf, framenum);
4122 /* Select the packet on a given row. */
4124 cf_select_packet(capture_file *cf, int row)
4128 /* Get the frame data struct pointer for this frame */
4129 #ifdef NEW_PACKET_LIST
4130 fdata = new_packet_list_get_row_data(row);
4132 fdata = (frame_data *)packet_list_get_row_data(row);
4135 if (fdata == NULL) {
4136 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
4137 the first entry is added to it by "real_insert_row()", that row
4138 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
4139 our version and the vanilla GTK+ version).
4141 This means that a "select-row" signal is emitted; this causes
4142 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
4145 "cf_select_packet()" fetches, above, the data associated with the
4146 row that was selected; however, as "gtk_clist_append()", which
4147 called "real_insert_row()", hasn't yet returned, we haven't yet
4148 associated any data with that row, so we get back a null pointer.
4150 We can't assume that there's only one frame in the frame list,
4151 either, as we may be filtering the display.
4153 We therefore assume that, if "row" is 0, i.e. the first row
4154 is being selected, and "cf->first_displayed" equals
4155 "cf->last_displayed", i.e. there's only one frame being
4156 displayed, that frame is the frame we want.
4158 This means we have to set "cf->first_displayed" and
4159 "cf->last_displayed" before adding the row to the
4160 GtkCList; see the comment in "add_packet_to_packet_list()". */
4162 if (row == 0 && cf->first_displayed == cf->last_displayed)
4163 fdata = cf->first_displayed;
4166 /* If fdata _still_ isn't set simply give up. */
4167 if (fdata == NULL) {
4171 /* Get the data in that frame. */
4172 if (!cf_read_frame (cf, fdata)) {
4176 /* Record that this frame is the current frame. */
4177 cf->current_frame = fdata;
4178 cf->current_row = row;
4180 /* Create the logical protocol tree. */
4181 if (cf->edt != NULL)
4182 epan_dissect_free(cf->edt);
4184 /* We don't need the columns here. */
4185 cf->edt = epan_dissect_new(TRUE, TRUE);
4187 tap_build_interesting(cf->edt);
4188 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
4191 dfilter_macro_build_ftv_cache(cf->edt->tree);
4193 cf_callback_invoke(cf_cb_packet_selected, cf);
4196 /* Unselect the selected packet, if any. */
4198 cf_unselect_packet(capture_file *cf)
4200 /* Destroy the epan_dissect_t for the unselected packet. */
4201 if (cf->edt != NULL) {
4202 epan_dissect_free(cf->edt);
4206 /* No packet is selected. */
4207 cf->current_frame = NULL;
4208 cf->current_row = 0;
4210 cf_callback_invoke(cf_cb_packet_unselected, cf);
4212 /* No protocol tree means no selected field. */
4213 cf_unselect_field(cf);
4216 /* Unset the selected protocol tree field, if any. */
4218 cf_unselect_field(capture_file *cf)
4220 cf->finfo_selected = NULL;
4222 cf_callback_invoke(cf_cb_field_unselected, cf);
4226 * Mark a particular frame.
4229 cf_mark_frame(capture_file *cf, frame_data *frame)
4231 if (! frame->flags.marked) {
4232 frame->flags.marked = TRUE;
4233 if (cf->count > cf->marked_count)
4239 * Unmark a particular frame.
4242 cf_unmark_frame(capture_file *cf, frame_data *frame)
4244 if (frame->flags.marked) {
4245 frame->flags.marked = FALSE;
4246 if (cf->marked_count > 0)
4252 * Ignore a particular frame.
4255 cf_ignore_frame(capture_file *cf, frame_data *frame)
4257 if (! frame->flags.ignored) {
4258 frame->flags.ignored = TRUE;
4259 if (cf->count > cf->ignored_count)
4260 cf->ignored_count++;
4265 * Un-ignore a particular frame.
4268 cf_unignore_frame(capture_file *cf, frame_data *frame)
4270 if (frame->flags.ignored) {
4271 frame->flags.ignored = FALSE;
4272 if (cf->ignored_count > 0)
4273 cf->ignored_count--;
4280 } save_callback_args_t;
4283 * Save a capture to a file, in a particular format, saving either
4284 * all packets, all currently-displayed packets, or all marked packets.
4286 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4287 * up a message box for the failure.
4290 save_packet(capture_file *cf _U_, frame_data *fdata,
4291 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
4294 save_callback_args_t *args = argsp;
4295 struct wtap_pkthdr hdr;
4298 /* init the wtap header for saving */
4299 hdr.ts.secs = fdata->abs_ts.secs;
4300 hdr.ts.nsecs = fdata->abs_ts.nsecs;
4301 hdr.caplen = fdata->cap_len;
4302 hdr.len = fdata->pkt_len;
4303 hdr.pkt_encap = fdata->lnk_t;
4305 /* and save the packet */
4306 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
4307 cf_write_failure_alert_box(args->fname, err);
4314 * Can this capture file be saved in any format except by copying the raw data?
4317 cf_can_save_as(capture_file *cf)
4321 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
4322 /* To save a file with Wiretap, Wiretap has to handle that format,
4323 and its code to handle that format must be able to write a file
4324 with this file's encapsulation type. */
4325 if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
4326 /* OK, we can write it out in this type. */
4331 /* No, we couldn't save it in any format. */
4336 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
4338 gchar *from_filename;
4342 save_callback_args_t callback_args;
4344 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4346 /* don't write over an existing file. */
4347 /* this should've been already checked by our caller, just to be sure... */
4348 if (file_exists(fname)) {
4349 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4350 "%sCapture file: \"%s\" already exists!%s\n\n"
4351 "Please choose a different filename.",
4352 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
4356 packet_range_process_init(range);
4358 if (packet_range_process_all(range) && save_format == cf->cd_t) {
4359 /* We're not filtering packets, and we're saving it in the format
4360 it's already in, so we can just move or copy the raw data. */
4362 if (cf->is_tempfile) {
4363 /* The file being saved is a temporary file from a live
4364 capture, so it doesn't need to stay around under that name;
4365 first, try renaming the capture buffer file to the new name. */
4367 if (ws_rename(cf->filename, fname) == 0) {
4368 /* That succeeded - there's no need to copy the source file. */
4369 from_filename = NULL;
4372 if (errno == EXDEV) {
4373 /* They're on different file systems, so we have to copy the
4376 from_filename = cf->filename;
4378 /* The rename failed, but not because they're on different
4379 file systems - put up an error message. (Or should we
4380 just punt and try to copy? The only reason why I'd
4381 expect the rename to fail and the copy to succeed would
4382 be if we didn't have permission to remove the file from
4383 the temporary directory, and that might be fixable - but
4384 is it worth requiring the user to go off and fix it?) */
4385 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4386 file_rename_error_message(errno), fname);
4392 from_filename = cf->filename;
4395 /* It's a permanent file, so we should copy it, and not remove the
4398 from_filename = cf->filename;
4402 /* Copy the file, if we haven't moved it. */
4403 if (!copy_file_binary_mode(from_filename, fname))
4407 /* Either we're filtering packets, or we're saving in a different
4408 format; we can't do that by copying or moving the capture file,
4409 we have to do it by writing the packets out in Wiretap. */
4410 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
4413 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4417 /* XXX - we let the user save a subset of the packets.
4419 If we do that, should we make that file the current file? If so,
4420 it means we can no longer get at the other packets. What does
4423 /* Iterate through the list of packets, processing the packets we were
4426 XXX - we've already called "packet_range_process_init(range)", but
4427 "process_specified_packets()" will do it again. Fortunately,
4428 that's harmless in this case, as we haven't done anything to
4429 "range" since we initialized it. */
4430 callback_args.pdh = pdh;
4431 callback_args.fname = fname;
4432 switch (process_specified_packets(cf, range, "Saving", "selected packets",
4433 TRUE, save_packet, &callback_args)) {
4436 /* Completed successfully. */
4440 /* The user decided to abort the saving.
4441 XXX - remove the output file? */
4445 /* Error while saving. */
4446 wtap_dump_close(pdh, &err);
4450 if (!wtap_dump_close(pdh, &err)) {
4451 cf_close_failure_alert_box(fname, err);
4456 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4458 if (packet_range_process_all(range)) {
4459 /* We saved the entire capture, not just some packets from it.
4460 Open and read the file we saved it to.
4462 XXX - this is somewhat of a waste; we already have the
4463 packets, all this gets us is updated file type information
4464 (which we could just stuff into "cf"), and having the new
4465 file be the one we have opened and from which we're reading
4466 the data, and it means we have to spend time opening and
4467 reading the file, which could be a significant amount of
4468 time if the file is large. */
4469 cf->user_saved = TRUE;
4471 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
4472 /* XXX - report errors if this fails?
4473 What should we return if it fails or is aborted? */
4475 switch (cf_read(cf, TRUE)) {
4479 /* Just because we got an error, that doesn't mean we were unable
4480 to read any of the file; we handle what we could get from the
4484 case CF_READ_ABORTED:
4485 /* The user bailed out of re-reading the capture file; the
4486 capture file has been closed - just return (without
4487 changing any menu settings; "cf_close()" set them
4488 correctly for the "no capture file open" state). */
4491 cf_callback_invoke(cf_cb_file_save_reload_finished, cf);
4497 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4502 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
4503 gboolean for_writing, int file_type)
4506 /* Wiretap error. */
4509 case WTAP_ERR_NOT_REGULAR_FILE:
4510 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4511 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4515 case WTAP_ERR_RANDOM_OPEN_PIPE:
4516 /* Seen only when opening a capture file for reading. */
4517 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4518 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
4522 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
4523 /* Seen only when opening a capture file for reading. */
4524 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4525 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
4529 case WTAP_ERR_UNSUPPORTED:
4530 /* Seen only when opening a capture file for reading. */
4531 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4532 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
4534 filename, err_info);
4538 case WTAP_ERR_CANT_WRITE_TO_PIPE:
4539 /* Seen only when opening a capture file for writing. */
4540 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4541 "The file \"%s\" is a pipe, and %s capture files can't be "
4542 "written to a pipe.",
4543 filename, wtap_file_type_string(file_type));
4546 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
4547 /* Seen only when opening a capture file for writing. */
4548 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4549 "Wireshark doesn't support writing capture files in that format.");
4552 case WTAP_ERR_UNSUPPORTED_ENCAP:
4554 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4555 "Wireshark can't save this capture in that format.");
4557 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4558 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
4560 filename, err_info);
4565 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
4567 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4568 "Wireshark can't save this capture in that format.");
4570 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4571 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
4576 case WTAP_ERR_BAD_RECORD:
4577 /* Seen only when opening a capture file for reading. */
4578 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4579 "The file \"%s\" appears to be damaged or corrupt.\n"
4581 filename, err_info);
4585 case WTAP_ERR_CANT_OPEN:
4587 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4588 "The file \"%s\" could not be created for some unknown reason.",
4591 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4592 "The file \"%s\" could not be opened for some unknown reason.",
4597 case WTAP_ERR_SHORT_READ:
4598 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4599 "The file \"%s\" appears to have been cut short"
4600 " in the middle of a packet or other data.",
4604 case WTAP_ERR_SHORT_WRITE:
4605 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4606 "A full header couldn't be written to the file \"%s\".",
4610 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4611 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4612 "Gzip compression not supported by this file type.");
4616 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4617 "The file \"%s\" could not be %s: %s.",
4619 for_writing ? "created" : "opened",
4620 wtap_strerror(err));
4625 open_failure_alert_box(filename, err, for_writing);
4630 file_rename_error_message(int err)
4633 static char errmsg_errno[1024+1];
4638 errmsg = "The path to the file \"%s\" doesn't exist.";
4642 errmsg = "You don't have permission to move the capture file to \"%s\".";
4646 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4647 "The file \"%%s\" could not be moved: %s.",
4648 wtap_strerror(err));
4649 errmsg = errmsg_errno;
4656 cf_write_failure_alert_box(const char *filename, int err)
4659 /* Wiretap error. */
4660 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4661 "An error occurred while writing to the file \"%s\": %s.",
4662 filename, wtap_strerror(err));
4665 write_failure_alert_box(filename, err);
4669 /* Check for write errors - if the file is being written to an NFS server,
4670 a write error may not show up until the file is closed, as NFS clients
4671 might not send writes to the server until the "write()" call finishes,
4672 so that the write may fail on the server but the "write()" may succeed. */
4674 cf_close_failure_alert_box(const char *filename, int err)
4677 /* Wiretap error. */
4680 case WTAP_ERR_CANT_CLOSE:
4681 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4682 "The file \"%s\" couldn't be closed for some unknown reason.",
4686 case WTAP_ERR_SHORT_WRITE:
4687 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4688 "Not all the packets could be written to the file \"%s\".",
4693 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4694 "An error occurred while closing the file \"%s\": %s.",
4695 filename, wtap_strerror(err));
4700 We assume that a close error from the OS is really a write error. */
4701 write_failure_alert_box(filename, err);
4705 /* Reload the current capture file. */
4707 cf_reload(capture_file *cf) {
4709 gboolean is_tempfile;
4712 /* If the file could be opened, "cf_open()" calls "cf_close()"
4713 to get rid of state for the old capture file before filling in state
4714 for the new capture file. "cf_close()" will remove the file if
4715 it's a temporary file; we don't want that to happen (for one thing,
4716 it'd prevent subsequent reopens from working). Remember whether it's
4717 a temporary file, mark it as not being a temporary file, and then
4718 reopen it as the type of file it was.
4720 Also, "cf_close()" will free "cf->filename", so we must make
4721 a copy of it first. */
4722 filename = g_strdup(cf->filename);
4723 is_tempfile = cf->is_tempfile;
4724 cf->is_tempfile = FALSE;
4725 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4726 switch (cf_read(cf, FALSE)) {
4730 /* Just because we got an error, that doesn't mean we were unable
4731 to read any of the file; we handle what we could get from the
4735 case CF_READ_ABORTED:
4736 /* The user bailed out of re-reading the capture file; the
4737 capture file has been closed - just free the capture file name
4738 string and return (without changing the last containing
4744 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4745 Instead, the file was left open, so we should restore "cf->is_tempfile"
4748 XXX - change the menu? Presumably "cf_open()" will do that;
4749 make sure it does! */
4750 cf->is_tempfile = is_tempfile;
4752 /* "cf_open()" made a copy of the file name we handed it, so
4753 we should free up our copy. */
4763 * indent-tabs-mode: nil
4766 * ex: set shiftwidth=2 tabstop=8 expandtab
4767 * :indentSize=2:tabSize=8:noTabs=true: