6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #include <epan/epan.h>
47 #include <epan/filesystem.h>
50 #include "color_filters.h"
52 #include <epan/column.h>
53 #include <epan/packet.h>
54 #include <epan/column-utils.h>
55 #include "packet-range.h"
61 #include "alert_box.h"
62 #include "simple_dialog.h"
63 #include "main_statusbar.h"
64 #include "progress_dlg.h"
66 #include <epan/prefs.h>
67 #include <epan/dfilter/dfilter.h>
68 #include <epan/epan_dissect.h>
70 #include <epan/dissectors/packet-data.h>
71 #include <epan/dissectors/packet-ber.h>
72 #include <epan/timestamp.h>
73 #include <epan/dfilter/dfilter-macro.h>
74 #include <wsutil/file_util.h>
75 #include <epan/strutil.h>
78 gboolean auto_scroll_live;
81 static guint32 cum_bytes;
82 static nstime_t first_ts;
83 static nstime_t prev_dis_ts;
84 static nstime_t prev_cap_ts;
86 static gulong computed_elapsed;
88 static void cf_reset_state(capture_file *cf);
90 static int read_packet(capture_file *cf, dfilter_t *dfcode,
91 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset);
93 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
94 gboolean refilter, gboolean redissect);
101 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
103 static void match_subtree_text(proto_node *node, gpointer data);
104 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
106 static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
108 static match_result match_ascii(capture_file *cf, frame_data *fdata,
110 static match_result match_unicode(capture_file *cf, frame_data *fdata,
112 static match_result match_binary(capture_file *cf, frame_data *fdata,
114 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
116 static match_result match_marked(capture_file *cf, frame_data *fdata,
118 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
120 static gboolean find_packet(capture_file *cf,
121 match_result (*match_function)(capture_file *, frame_data *, void *),
122 void *criterion, search_direction dir);
124 static void cf_open_failure_alert_box(const char *filename, int err,
125 gchar *err_info, gboolean for_writing,
127 static const char *file_rename_error_message(int err);
128 static void cf_write_failure_alert_box(const char *filename, int err);
129 static void cf_close_failure_alert_box(const char *filename, int err);
130 #ifdef NEW_PACKET_LIST
131 static void ref_time_packets(capture_file *cf);
133 /* Update the progress bar this many times when reading a file. */
134 #define N_PROGBAR_UPDATES 100
135 /* We read around 200k/100ms don't update the progress bar more often than that */
136 #define MIN_QUANTUM 200000
137 #define MIN_NUMBER_OF_PACKET 1500
139 /* Number of "frame_data" structures per memory chunk.
140 XXX - is this the right number? */
141 #define FRAME_DATA_CHUNK_SIZE 1024
144 /* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
146 cf_callback_t cb_fct;
148 } cf_callback_data_t;
150 static GList *cf_callbacks = NULL;
153 cf_callback_invoke(int event, gpointer data)
155 cf_callback_data_t *cb;
156 GList *cb_item = cf_callbacks;
158 /* there should be at least one interested */
159 g_assert(cb_item != NULL);
161 while(cb_item != NULL) {
163 cb->cb_fct(event, data, cb->user_data);
164 cb_item = g_list_next(cb_item);
170 cf_callback_add(cf_callback_t func, gpointer user_data)
172 cf_callback_data_t *cb;
174 cb = g_malloc(sizeof(cf_callback_data_t));
176 cb->user_data = user_data;
178 cf_callbacks = g_list_append(cf_callbacks, cb);
182 cf_callback_remove(cf_callback_t func)
184 cf_callback_data_t *cb;
185 GList *cb_item = cf_callbacks;
187 while(cb_item != NULL) {
189 if(cb->cb_fct == func) {
190 cf_callbacks = g_list_remove(cf_callbacks, cb);
194 cb_item = g_list_next(cb_item);
197 g_assert_not_reached();
201 cf_timestamp_auto_precision(capture_file *cf)
203 #ifdef NEW_PACKET_LIST
206 int prec = timestamp_get_precision();
209 /* don't try to get the file's precision if none is opened */
210 if(cf->state == FILE_CLOSED) {
214 /* if we are in auto mode, set precision of current file */
215 if(prec == TS_PREC_AUTO ||
216 prec == TS_PREC_AUTO_SEC ||
217 prec == TS_PREC_AUTO_DSEC ||
218 prec == TS_PREC_AUTO_CSEC ||
219 prec == TS_PREC_AUTO_MSEC ||
220 prec == TS_PREC_AUTO_USEC ||
221 prec == TS_PREC_AUTO_NSEC)
223 switch(wtap_file_tsprecision(cf->wth)) {
224 case(WTAP_FILE_TSPREC_SEC):
225 timestamp_set_precision(TS_PREC_AUTO_SEC);
227 case(WTAP_FILE_TSPREC_DSEC):
228 timestamp_set_precision(TS_PREC_AUTO_DSEC);
230 case(WTAP_FILE_TSPREC_CSEC):
231 timestamp_set_precision(TS_PREC_AUTO_CSEC);
233 case(WTAP_FILE_TSPREC_MSEC):
234 timestamp_set_precision(TS_PREC_AUTO_MSEC);
236 case(WTAP_FILE_TSPREC_USEC):
237 timestamp_set_precision(TS_PREC_AUTO_USEC);
239 case(WTAP_FILE_TSPREC_NSEC):
240 timestamp_set_precision(TS_PREC_AUTO_NSEC);
243 g_assert_not_reached();
246 #ifdef NEW_PACKET_LIST
247 /* Set the column widths of those columns that show the time in
248 "command-line-specified" format. */
249 for (i = 0; i < cf->cinfo.num_cols; i++) {
250 if (col_has_time_fmt(&cf->cinfo, i)) {
251 new_packet_list_resize_column(i);
258 cf_get_computed_elapsed(void)
260 return computed_elapsed;
263 static void reset_elapsed(void)
265 computed_elapsed = 0;
268 static void compute_elapsed(GTimeVal *start_time)
273 g_get_current_time(&time_now);
275 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
276 time_now.tv_usec - start_time->tv_usec;
278 computed_elapsed = (gulong) (delta_time / 1000); /* ms*/
282 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
287 wth = wtap_open_offline(fname, err, &err_info, TRUE);
291 /* The open succeeded. Close whatever capture file we had open,
292 and fill in the information for this file. */
295 /* Cleanup all data structures used for dissection. */
296 cleanup_dissection();
297 /* Initialize all data structures used for dissection. */
300 /* We're about to start reading the file. */
301 cf->state = FILE_READ_IN_PROGRESS;
306 /* Set the file name because we need it to set the follow stream filter.
307 XXX - is that still true? We need it for other reasons, though,
309 cf->filename = g_strdup(fname);
311 /* Indicate whether it's a permanent or temporary file. */
312 cf->is_tempfile = is_tempfile;
314 /* If it's a temporary capture buffer file, mark it as not saved. */
315 cf->user_saved = !is_tempfile;
319 cf->cd_t = wtap_file_type(cf->wth);
321 cf->displayed_count = 0;
322 cf->marked_count = 0;
323 cf->ignored_count = 0;
324 cf->ref_time_count = 0;
325 cf->drops_known = FALSE;
327 cf->snap = wtap_snapshot_length(cf->wth);
329 /* Snapshot length not known. */
330 cf->has_snap = FALSE;
331 cf->snap = WTAP_MAX_PACKET_SIZE;
335 nstime_set_zero(&cf->elapsed_time);
336 nstime_set_unset(&first_ts);
337 nstime_set_unset(&prev_dis_ts);
338 nstime_set_unset(&prev_cap_ts);
341 #if GLIB_CHECK_VERSION(2,10,0)
343 /* memory chunks have been deprecated in favor of the slice allocator,
344 * which has been added in 2.10
346 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
348 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
350 g_assert(cf->plist_chunk);
353 #ifdef NEW_PACKET_LIST
354 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
355 cf_timestamp_auto_precision(cf);
357 new_packet_list_queue_draw();
359 /* change the time formats now, as we might have a new precision */
360 cf_change_time_formats(cf);
362 fileset_file_opened(fname);
364 if(cf->cd_t == WTAP_FILE_BER) {
365 /* tell the BER dissector the file name */
366 ber_set_filename(cf->filename);
372 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
378 * Reset the state for the currently closed file, but don't do the
379 * UI callbacks; this is for use in "cf_open()", where we don't
380 * want the UI to go from "file open" to "file closed" back to
381 * "file open", we want it to go from "old file open" to "new file
382 * open and being read".
385 cf_reset_state(capture_file *cf)
387 /* Die if we're in the middle of reading a file. */
388 g_assert(cf->state != FILE_READ_IN_PROGRESS);
394 /* We have no file open... */
395 if (cf->filename != NULL) {
396 /* If it's a temporary file, remove it. */
398 ws_unlink(cf->filename);
399 g_free(cf->filename);
402 /* ...which means we have nothing to save. */
403 cf->user_saved = FALSE;
405 #if GLIB_CHECK_VERSION(2,10,0)
406 if (cf->plist_start != NULL)
407 g_slice_free_chain(frame_data, cf->plist_start, next);
409 /* memory chunks have been deprecated in favor of the slice allocator,
410 * which has been added in 2.10
412 if (cf->plist_chunk != NULL) {
413 g_mem_chunk_destroy(cf->plist_chunk);
414 cf->plist_chunk = NULL;
417 dfilter_free(cf->rfcode);
419 cf->plist_start = NULL;
420 cf->plist_end = NULL;
421 cf_unselect_packet(cf); /* nothing to select */
422 cf->first_displayed = NULL;
423 cf->last_displayed = NULL;
425 /* No frame selected, no field in that frame selected. */
426 cf->current_frame = NULL;
428 cf->finfo_selected = NULL;
430 /* Clear the packet list. */
431 #ifdef NEW_PACKET_LIST
432 new_packet_list_freeze();
433 new_packet_list_clear();
434 new_packet_list_thaw();
436 packet_list_freeze();
443 nstime_set_zero(&cf->elapsed_time);
445 reset_tap_listeners();
447 /* We have no file open. */
448 cf->state = FILE_CLOSED;
450 fileset_file_closed();
453 /* Reset everything to a pristine state */
455 cf_close(capture_file *cf)
457 /* do GUI things even if file is already closed,
458 * e.g. to cleanup things if a capture couldn't be started */
459 cf_callback_invoke(cf_cb_file_closing, cf);
461 /* close things, if not already closed before */
462 if(cf->state != FILE_CLOSED) {
463 color_filters_cleanup();
465 cleanup_dissection();
468 cf_callback_invoke(cf_cb_file_closed, cf);
471 /* an out of memory exception occured, wait for a user button press to exit */
472 static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
478 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
482 progbar_val = (gfloat) file_pos / (gfloat) size;
483 if (progbar_val > 1.0) {
485 /* The file probably grew while we were reading it.
486 * Update file size, and try again.
488 size = wtap_file_size(cf->wth, NULL);
490 /* Another possibility is that we're reading a compressed file and we've
491 * read more (uncompressed) data from the file than exists in the
492 * (compressed) file. So check how much data we've actually read.
494 * This is inside this "if val > 1.0" check to avoid the lseek() when
495 * reading uncompressed files. Testing has (thus far) shown no progress
496 * bar weirdness resulting from switching from the data offset (when
497 * reading the first part of the file) to the real file position.
499 file_pos = wtap_read_so_far(cf->wth, NULL);
502 progbar_val = (gfloat) file_pos / (gfloat) size;
504 /* If it's still > 1, either "wtap_file_size()" failed (in which
505 * case there's not much we can do about it), or the file
506 * *shrank* (in which case there's not much we can do about
507 * it); just clip the progress value at 1.0.
509 if (progbar_val > 1.0f)
513 g_snprintf(status_str, status_size,
514 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
515 file_pos / 1024, size / 1024);
521 cf_read(capture_file *cf, gboolean from_save)
525 const gchar *name_ptr;
527 char errmsg_errno[1024+1];
529 progdlg_t *volatile progbar = NULL;
531 volatile gint64 size;
532 volatile float progbar_val;
534 gchar status_str[100];
535 volatile gint64 progbar_nextstep;
536 volatile gint64 progbar_quantum;
538 gboolean filtering_tap_listeners;
540 volatile int count = 0;
542 volatile int displayed_once = 0;
546 /* Compile the current display filter.
547 * We assume this will not fail since cf->dfilter is only set in
548 * cf_filter IFF the filter was valid.
550 compiled = dfilter_compile(cf->dfilter, &dfcode);
551 g_assert(!cf->dfilter || (compiled && dfcode));
553 /* Do we have any tap listeners with filters? */
554 filtering_tap_listeners = have_filtering_tap_listeners();
556 /* Get the union of the flags for all tap listeners. */
557 tap_flags = union_of_tap_listener_flags();
559 reset_tap_listeners();
561 name_ptr = get_basename(cf->filename);
563 if (from_save == FALSE)
564 cf_callback_invoke(cf_cb_file_read_started, cf);
566 cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr);
568 /* Find the size of the file. */
569 size = wtap_file_size(cf->wth, NULL);
571 /* Update the progress bar when it gets to this value. */
572 progbar_nextstep = 0;
573 /* When we reach the value that triggers a progress bar update,
574 bump that value by this amount. */
576 progbar_quantum = size/N_PROGBAR_UPDATES;
577 if (progbar_quantum < MIN_QUANTUM)
578 progbar_quantum = MIN_QUANTUM;
581 /* Progress so far. */
584 #ifdef NEW_PACKET_LIST
585 new_packet_list_freeze();
587 packet_list_freeze();
591 g_get_current_time(&start_time);
593 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
596 /* Create the progress bar if necessary.
597 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
599 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
600 progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str));
601 if (from_save == FALSE)
602 progbar = delayed_create_progress_dlg("Loading", name_ptr,
603 TRUE, &stop_flag, &start_time, progbar_val);
605 progbar = delayed_create_progress_dlg("Saving", name_ptr,
606 TRUE, &stop_flag, &start_time, progbar_val);
609 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
610 when we update it, we have to run the GTK+ main loop to get it
611 to repaint what's pending, and doing so may involve an "ioctl()"
612 to see if there's any pending input from an X server, and doing
613 that for every packet can be costly, especially on a big file. */
614 if (data_offset >= progbar_nextstep) {
615 if (progbar != NULL) {
616 progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str));
617 /* update the packet lists content on the first run or frequently on very large files */
618 /* (on smaller files the display update takes longer than reading the file) */
620 if (progbar_quantum > 500000 || displayed_once == 0) {
621 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
623 #ifdef NEW_PACKET_LIST
624 new_packet_list_thaw();
625 if (auto_scroll_live)
626 new_packet_list_moveto_end();
627 new_packet_list_freeze();
630 if (auto_scroll_live)
631 packet_list_moveto_end();
632 packet_list_freeze();
633 #endif /* NEW_PACKET_LIST */
636 #endif /* HAVE_LIBPCAP */
637 update_progress_dlg(progbar, progbar_val, status_str);
639 progbar_nextstep += progbar_quantum;
644 /* Well, the user decided to abort the read. He/She will be warned and
645 it might be enough for him/her to work with the already loaded
647 This is especially true for very large capture files, where you don't
648 want to wait loading the whole file (which may last minutes or even
649 hours even on fast machines) just to see that it was the wrong file. */
653 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
655 CATCH(OutOfMemoryError) {
658 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
659 "%sOut Of Memory!%s\n"
661 "Sorry, but Wireshark has to terminate now!\n"
663 "Some infos / workarounds can be found at:\n"
664 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
665 simple_dialog_primary_start(), simple_dialog_primary_end());
666 /* we have to terminate, as we cannot recover from the memory error */
667 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
669 main_window_update();
670 /* XXX - how to avoid a busy wait? */
678 /* Cleanup and release all dfilter resources */
680 dfilter_free(dfcode);
683 /* We're done reading the file; destroy the progress bar if it was created. */
685 destroy_progress_dlg(progbar);
687 /* We're done reading sequentially through the file. */
688 cf->state = FILE_READ_DONE;
690 /* Close the sequential I/O side, to free up memory it requires. */
691 wtap_sequential_close(cf->wth);
693 /* Allow the protocol dissectors to free up memory that they
694 * don't need after the sequential run-through of the packets. */
695 postseq_cleanup_all_protocols();
697 /* compute the time it took to load the file */
698 compute_elapsed(&start_time);
700 /* Set the file encapsulation type now; we don't know what it is until
701 we've looked at all the packets, as we don't know until then whether
702 there's more than one type (and thus whether it's
703 WTAP_ENCAP_PER_PACKET). */
704 cf->lnk_t = wtap_file_encap(cf->wth);
706 cf->current_frame = cf->first_displayed;
709 #ifdef NEW_PACKET_LIST
710 new_packet_list_thaw();
714 if (from_save == FALSE)
715 cf_callback_invoke(cf_cb_file_read_finished, cf);
717 cf_callback_invoke(cf_cb_file_save_finished, cf);
719 /* If we have any displayed packets to select, select the first of those
720 packets by making the first row the selected row. */
721 if (cf->first_displayed != NULL){
722 #ifdef NEW_PACKET_LIST
723 new_packet_list_select_first_row();
725 packet_list_select_row(0);
726 #endif /* NEW_PACKET_LIST */
730 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
731 "%sFile loading was cancelled!%s\n"
733 "The remaining packets in the file were discarded.\n"
735 "As a lot of packets from the original file will be missing,\n"
736 "remember to be careful when saving the current content to a file.\n",
737 simple_dialog_primary_start(), simple_dialog_primary_end());
738 return CF_READ_ERROR;
742 /* Put up a message box noting that the read failed somewhere along
743 the line. Don't throw out the stuff we managed to read, though,
747 case WTAP_ERR_UNSUPPORTED_ENCAP:
748 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
749 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
752 errmsg = errmsg_errno;
755 case WTAP_ERR_CANT_READ:
756 errmsg = "An attempt to read from the capture file failed for"
757 " some unknown reason.";
760 case WTAP_ERR_SHORT_READ:
761 errmsg = "The capture file appears to have been cut short"
762 " in the middle of a packet.";
765 case WTAP_ERR_BAD_RECORD:
766 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
767 "The capture file appears to be damaged or corrupt.\n(%s)",
770 errmsg = errmsg_errno;
774 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
775 "An error occurred while reading the"
776 " capture file: %s.", wtap_strerror(err));
777 errmsg = errmsg_errno;
780 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
781 return CF_READ_ERROR;
788 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
790 cf_status_t cf_status;
792 cf_status = cf_open(cf, fname, is_tempfile, err);
797 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
799 gint64 data_offset = 0;
801 volatile int newly_displayed_packets = 0;
803 gboolean filtering_tap_listeners;
807 /* Compile the current display filter.
808 * We assume this will not fail since cf->dfilter is only set in
809 * cf_filter IFF the filter was valid.
811 compiled = dfilter_compile(cf->dfilter, &dfcode);
812 g_assert(!cf->dfilter || (compiled && dfcode));
814 /* Do we have any tap listeners with filters? */
815 filtering_tap_listeners = have_filtering_tap_listeners();
817 /* Get the union of the flags for all tap listeners. */
818 tap_flags = union_of_tap_listener_flags();
822 #ifdef NEW_PACKET_LIST
823 new_packet_list_check_end();
824 /* Don't freeze/thaw the list when doing live capture */
825 /*new_packet_list_freeze();*/
827 packet_list_check_end();
828 packet_list_freeze();
831 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
833 while (to_read != 0) {
834 wtap_cleareof(cf->wth);
835 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
838 if (cf->state == FILE_READ_ABORTED) {
839 /* Well, the user decided to exit Wireshark. Break out of the
840 loop, and let the code below (which is called even if there
841 aren't any packets left to read) exit. */
845 if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
846 data_offset) != -1) {
847 newly_displayed_packets++;
850 CATCH(OutOfMemoryError) {
853 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
854 "%sOut Of Memory!%s\n"
856 "Sorry, but Wireshark has to terminate now!\n"
858 "The capture file is not lost, it can be found at:\n"
861 "Some infos / workarounds can be found at:\n"
862 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
863 simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
864 /* we have to terminate, as we cannot recover from the memory error */
865 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
867 main_window_update();
868 /* XXX - how to avoid a busy wait? */
871 #ifdef NEW_PACKET_LIST
872 /* Don't freeze/thaw the list when doing live capture */
873 /*new_packet_list_thaw();*/
877 return CF_READ_ABORTED;
883 /* Cleanup and release all dfilter resources */
885 dfilter_free(dfcode);
888 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
889 cf->count, cf->state, *err);*/
891 #ifdef NEW_PACKET_LIST
892 /* Don't freeze/thaw the list when doing live capture */
893 /*new_packet_list_thaw();*/
894 /* With the new packet list the first packet
895 * isn't automatically selected.
897 if(!cf->current_frame)
898 new_packet_list_select_first_row();
900 /* XXX - this causes "flickering" of the list */
904 /* moving to the end of the packet list - if the user requested so and
905 we have some new packets. */
906 if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL)
907 #ifdef NEW_PACKET_LIST
908 new_packet_list_moveto_end();
910 /* this doesn't seem to work well with a frozen GTK_Clist, so do this after
911 packet_list_thaw() is done, see bugzilla 1188 */
912 /* XXX - this cheats and looks inside the packet list to find the final
914 packet_list_moveto_end();
915 #endif /* NEW_PACKET_LIST */
917 if (cf->state == FILE_READ_ABORTED) {
918 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
919 so that our caller can kill off the capture child process;
920 this will cause an EOF on the pipe from the child, so
921 "cf_finish_tail()" will be called, and it will clean up
923 return CF_READ_ABORTED;
924 } else if (*err != 0) {
925 /* We got an error reading the capture file.
926 XXX - pop up a dialog box instead? */
927 g_warning("Error \"%s\" while reading: \"%s\"\n",
928 wtap_strerror(*err), cf->filename);
930 return CF_READ_ERROR;
936 cf_fake_continue_tail(capture_file *cf) {
937 cf->state = FILE_READ_DONE;
941 cf_finish_tail(capture_file *cf, int *err)
946 gboolean filtering_tap_listeners;
950 /* Compile the current display filter.
951 * We assume this will not fail since cf->dfilter is only set in
952 * cf_filter IFF the filter was valid.
954 compiled = dfilter_compile(cf->dfilter, &dfcode);
955 g_assert(!cf->dfilter || (compiled && dfcode));
957 /* Do we have any tap listeners with filters? */
958 filtering_tap_listeners = have_filtering_tap_listeners();
960 /* Get the union of the flags for all tap listeners. */
961 tap_flags = union_of_tap_listener_flags();
963 if(cf->wth == NULL) {
965 return CF_READ_ERROR;
968 #ifdef NEW_PACKET_LIST
969 new_packet_list_check_end();
970 /* Don't freeze/thaw the list when doing live capture */
971 /*new_packet_list_freeze();*/
973 packet_list_check_end();
974 packet_list_freeze();
977 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
978 if (cf->state == FILE_READ_ABORTED) {
979 /* Well, the user decided to abort the read. Break out of the
980 loop, and let the code below (which is called even if there
981 aren't any packets left to read) exit. */
984 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
987 /* Cleanup and release all dfilter resources */
989 dfilter_free(dfcode);
992 #ifdef NEW_PACKET_LIST
993 /* Don't freeze/thaw the list when doing live capture */
994 /*new_packet_list_thaw();*/
999 if (cf->state == FILE_READ_ABORTED) {
1000 /* Well, the user decided to abort the read. We're only called
1001 when the child capture process closes the pipe to us (meaning
1002 it's probably exited), so we can just close the capture
1003 file; we return CF_READ_ABORTED so our caller can do whatever
1004 is appropriate when that happens. */
1006 return CF_READ_ABORTED;
1009 if (auto_scroll_live && cf->plist_end != NULL)
1010 #ifdef NEW_PACKET_LIST
1011 new_packet_list_moveto_end();
1013 /* XXX - this cheats and looks inside the packet list to find the final
1015 packet_list_moveto_end();
1018 /* We're done reading sequentially through the file. */
1019 cf->state = FILE_READ_DONE;
1021 /* We're done reading sequentially through the file; close the
1022 sequential I/O side, to free up memory it requires. */
1023 wtap_sequential_close(cf->wth);
1025 /* Allow the protocol dissectors to free up memory that they
1026 * don't need after the sequential run-through of the packets. */
1027 postseq_cleanup_all_protocols();
1029 /* Set the file encapsulation type now; we don't know what it is until
1030 we've looked at all the packets, as we don't know until then whether
1031 there's more than one type (and thus whether it's
1032 WTAP_ENCAP_PER_PACKET). */
1033 cf->lnk_t = wtap_file_encap(cf->wth);
1036 /* We got an error reading the capture file.
1037 XXX - pop up a dialog box? */
1038 return CF_READ_ERROR;
1043 #endif /* HAVE_LIBPCAP */
1046 cf_get_display_name(capture_file *cf)
1048 const gchar *displayname;
1050 /* Return a name to use in displays */
1051 if (!cf->is_tempfile) {
1052 /* Get the last component of the file name, and use that. */
1054 displayname = get_basename(cf->filename);
1056 displayname="(No file)";
1059 /* The file we read is a temporary file from a live capture;
1060 we don't mention its name. */
1062 displayname = cf->source;
1064 displayname = "(Untitled)";
1070 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1076 cf->source = g_strdup(source);
1078 cf->source = g_strdup("");
1082 const gchar *cf_get_tempfile_source(capture_file *cf) {
1090 /* XXX - use a macro instead? */
1092 cf_get_packet_count(capture_file *cf)
1097 /* XXX - use a macro instead? */
1099 cf_set_packet_count(capture_file *cf, int packet_count)
1101 cf->count = packet_count;
1104 /* XXX - use a macro instead? */
1106 cf_is_tempfile(capture_file *cf)
1108 return cf->is_tempfile;
1111 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1113 cf->is_tempfile = is_tempfile;
1117 /* XXX - use a macro instead? */
1118 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1120 cf->drops_known = drops_known;
1123 /* XXX - use a macro instead? */
1124 void cf_set_drops(capture_file *cf, guint32 drops)
1129 /* XXX - use a macro instead? */
1130 gboolean cf_get_drops_known(capture_file *cf)
1132 return cf->drops_known;
1135 /* XXX - use a macro instead? */
1136 guint32 cf_get_drops(capture_file *cf)
1141 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1143 cf->rfcode = rfcode;
1146 #ifdef NEW_PACKET_LIST
1148 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1149 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1151 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1153 gboolean add_to_packet_list)
1155 gboolean create_proto_tree = FALSE;
1160 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1162 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1163 &first_ts, &prev_dis_ts, &prev_cap_ts);
1166 + we have a display filter and are re-applying it;
1167 + we have tap listeners with filters;
1168 + we have tap listeners that require a protocol tree;
1170 allocate a protocol tree root node, so that we'll construct
1171 a protocol tree against which a filter expression can be
1173 if ((dfcode != NULL && refilter) ||
1174 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1175 create_proto_tree = TRUE;
1177 /* Dissect the frame. */
1178 epan_dissect_init(&edt, create_proto_tree, FALSE);
1180 if (dfcode != NULL && refilter) {
1181 epan_dissect_prime_dfilter(&edt, dfcode);
1184 tap_queue_init(&edt);
1185 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1186 tap_push_tapped_queue(&edt);
1188 /* If we have a display filter, apply it if we're refiltering, otherwise
1189 leave the "passed_dfilter" flag alone.
1191 If we don't have a display filter, set "passed_dfilter" to 1. */
1192 if (dfcode != NULL) {
1194 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1197 fdata->flags.passed_dfilter = 1;
1199 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1200 cf->displayed_count++;
1202 if (add_to_packet_list) {
1203 /* We fill the needed columns from new_packet_list */
1204 row = new_packet_list_append(cinfo, fdata, &edt.pi);
1207 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1209 frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1211 /* If we haven't yet seen the first frame, this is it.
1213 XXX - we must do this before we add the row to the display,
1214 as, if the display's GtkCList's selection mode is
1215 GTK_SELECTION_BROWSE, when the first entry is added to it,
1216 "cf_select_packet()" will be called, and it will fetch the row
1217 data for the 0th row, and will get a null pointer rather than
1218 "fdata", as "gtk_clist_append()" won't yet have returned and
1219 thus "gtk_clist_set_row_data()" won't yet have been called.
1221 We thus need to leave behind bread crumbs so that
1222 "cf_select_packet()" can find this frame. See the comment
1223 in "cf_select_packet()". */
1224 if (cf->first_displayed == NULL)
1225 cf->first_displayed = fdata;
1227 /* This is the last frame we've seen so far. */
1228 cf->last_displayed = fdata;
1231 epan_dissect_cleanup(&edt);
1238 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1239 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1241 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1243 gboolean add_to_packet_list _U_)
1245 gboolean create_proto_tree = FALSE;
1252 /* just add some value here until we know if it is being displayed or not */
1253 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1255 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1256 &first_ts, &prev_dis_ts, &prev_cap_ts);
1260 we have a display filter and are re-applying it;
1262 we have a list of color filters;
1264 we have tap listeners with filters;
1266 we have tap listeners that require a protocol tree;
1268 we have custom columns;
1270 allocate a protocol tree root node, so that we'll construct
1271 a protocol tree against which a filter expression can be
1273 if ((dfcode != NULL && refilter) ||
1274 color_filters_used() ||
1275 have_custom_cols(cinfo) ||
1276 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1277 create_proto_tree = TRUE;
1279 /* Dissect the frame. */
1280 epan_dissect_init(&edt, create_proto_tree, FALSE);
1282 if (dfcode != NULL && refilter) {
1283 epan_dissect_prime_dfilter(&edt, dfcode);
1286 /* prepare color filters */
1287 color_filters_prime_edt(&edt);
1288 col_custom_prime_edt(&edt, cinfo);
1290 tap_queue_init(&edt);
1291 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1292 tap_push_tapped_queue(&edt);
1294 /* If we have a display filter, apply it if we're refiltering, otherwise
1295 leave the "passed_dfilter" flag alone.
1297 If we don't have a display filter, set "passed_dfilter" to 1. */
1298 if (dfcode != NULL) {
1300 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1303 fdata->flags.passed_dfilter = 1;
1305 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) )
1307 frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1309 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
1311 /* If we haven't yet seen the first frame, this is it.
1313 XXX - we must do this before we add the row to the display,
1314 as, if the display's GtkCList's selection mode is
1315 GTK_SELECTION_BROWSE, when the first entry is added to it,
1316 "cf_select_packet()" will be called, and it will fetch the row
1317 data for the 0th row, and will get a null pointer rather than
1318 "fdata", as "gtk_clist_append()" won't yet have returned and
1319 thus "gtk_clist_set_row_data()" won't yet have been called.
1321 We thus need to leave behind bread crumbs so that
1322 "cf_select_packet()" can find this frame. See the comment
1323 in "cf_select_packet()". */
1324 if (cf->first_displayed == NULL)
1325 cf->first_displayed = fdata;
1327 /* This is the last frame we've seen so far. */
1328 cf->last_displayed = fdata;
1330 row = packet_list_append(cinfo->col_data, fdata);
1332 /* colorize packet: first apply color filters
1333 * then if packet is marked, use preferences to overwrite color
1334 * we do both to make sure that when a packet gets un-marked, the
1335 * color will be correctly set (fixes bug 2038)
1337 fdata->color_filter = color_filters_colorize_packet(row, &edt);
1338 if (fdata->flags.marked) {
1339 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
1341 if (fdata->flags.ignored) {
1342 packet_list_set_colors(row, &prefs.gui_ignored_fg, &prefs.gui_ignored_bg);
1345 cf->displayed_count++;
1348 epan_dissect_cleanup(&edt);
1353 /* read in a new packet */
1354 /* returns the row of the new packet in the packet list or -1 if not displayed */
1356 read_packet(capture_file *cf, dfilter_t *dfcode,
1357 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1359 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1360 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1361 const guchar *buf = wtap_buf_ptr(cf->wth);
1368 /* Allocate the next list entry, and add it to the list.
1369 * memory chunks have been deprecated in favor of the slice allocator,
1370 * which has been added in 2.10
1372 #if GLIB_CHECK_VERSION(2,10,0)
1373 fdata = g_slice_new(frame_data);
1375 fdata = g_mem_chunk_alloc(cf->plist_chunk);
1378 frame_data_init(fdata, cf->count, phdr, offset, cum_bytes);
1380 #ifdef NEW_PACKET_LIST
1381 fdata->col_text_len = se_alloc0(sizeof(fdata->col_text_len) * (cf->cinfo.num_cols));
1382 fdata->col_text = se_alloc0(sizeof(fdata->col_text) * (cf->cinfo.num_cols));
1388 epan_dissect_init(&edt, TRUE, FALSE);
1389 epan_dissect_prime_dfilter(&edt, cf->rfcode);
1390 epan_dissect_run(&edt, pseudo_header, buf, fdata, NULL);
1391 passed = dfilter_apply_edt(cf->rfcode, &edt);
1392 epan_dissect_cleanup(&edt);
1396 cap_file_add_fdata(cf, fdata);
1398 cf->f_datalen = offset + fdata->cap_len;
1400 if (!cf->redissecting) {
1401 row = add_packet_to_packet_list(fdata, cf, dfcode,
1402 filtering_tap_listeners, tap_flags,
1403 pseudo_header, buf, TRUE, TRUE);
1406 /* We didn't pass read filter so roll back count */
1409 /* XXX - if we didn't have read filters, or if we could avoid
1410 allocating the "frame_data" structure until we knew whether
1411 the frame passed the read filter, we could use a G_ALLOC_ONLY
1414 ...but, at least in one test I did, where I just made the chunk
1415 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
1416 seem to save a noticeable amount of time or space. */
1417 #if GLIB_CHECK_VERSION(2,10,0)
1418 /* memory chunks have been deprecated in favor of the slice allocator,
1419 * which has been added in 2.10
1421 g_slice_free(frame_data,fdata);
1423 g_mem_chunk_free(cf->plist_chunk, fdata);
1431 cf_merge_files(char **out_filenamep, int in_file_count,
1432 char *const *in_filenames, int file_type, gboolean do_append)
1434 merge_in_file_t *in_files;
1440 int open_err, read_err, write_err, close_err;
1444 char errmsg_errno[1024+1];
1446 gboolean got_read_error = FALSE, got_write_error = FALSE;
1448 progdlg_t *progbar = NULL;
1450 gint64 f_len, file_pos;
1452 GTimeVal start_time;
1453 gchar status_str[100];
1454 gint64 progbar_nextstep;
1455 gint64 progbar_quantum;
1457 /* open the input files */
1458 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1459 &open_err, &err_info, &err_fileno)) {
1461 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1466 if (*out_filenamep != NULL) {
1467 out_filename = *out_filenamep;
1468 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1472 out_fd = create_tempfile(&tmpname, "wireshark");
1475 out_filename = g_strdup(tmpname);
1476 *out_filenamep = out_filename;
1480 merge_close_in_files(in_file_count, in_files);
1482 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1486 pdh = wtap_dump_fdopen(out_fd, file_type,
1487 merge_select_frame_type(in_file_count, in_files),
1488 merge_max_snapshot_length(in_file_count, in_files),
1489 FALSE /* compressed */, &open_err);
1492 merge_close_in_files(in_file_count, in_files);
1494 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1499 /* Get the sum of the sizes of all the files. */
1501 for (i = 0; i < in_file_count; i++)
1502 f_len += in_files[i].size;
1504 /* Update the progress bar when it gets to this value. */
1505 progbar_nextstep = 0;
1506 /* When we reach the value that triggers a progress bar update,
1507 bump that value by this amount. */
1508 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1509 /* Progress so far. */
1513 g_get_current_time(&start_time);
1515 /* do the merge (or append) */
1518 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1521 wth = merge_read_packet(in_file_count, in_files, &read_err,
1525 got_read_error = TRUE;
1529 /* Get the sum of the data offsets in all of the files. */
1531 for (i = 0; i < in_file_count; i++)
1532 data_offset += in_files[i].data_offset;
1534 /* Create the progress bar if necessary.
1535 We check on every iteration of the loop, so that it takes no
1536 longer than the standard time to create it (otherwise, for a
1537 large file, we might take considerably longer than that standard
1538 time in order to get to the next progress bar step). */
1539 if (progbar == NULL) {
1540 progbar = delayed_create_progress_dlg("Merging", "files",
1541 FALSE, &stop_flag, &start_time, progbar_val);
1544 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1545 when we update it, we have to run the GTK+ main loop to get it
1546 to repaint what's pending, and doing so may involve an "ioctl()"
1547 to see if there's any pending input from an X server, and doing
1548 that for every packet can be costly, especially on a big file. */
1549 if (data_offset >= progbar_nextstep) {
1550 /* Get the sum of the seek positions in all of the files. */
1552 for (i = 0; i < in_file_count; i++)
1553 file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1554 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1555 if (progbar_val > 1.0f) {
1556 /* Some file probably grew while we were reading it.
1557 That "shouldn't happen", so we'll just clip the progress
1561 if (progbar != NULL) {
1562 g_snprintf(status_str, sizeof(status_str),
1563 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1564 file_pos / 1024, f_len / 1024);
1565 update_progress_dlg(progbar, progbar_val, status_str);
1567 progbar_nextstep += progbar_quantum;
1571 /* Well, the user decided to abort the merge. */
1575 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1576 wtap_buf_ptr(wth), &write_err)) {
1577 got_write_error = TRUE;
1582 /* We're done merging the files; destroy the progress bar if it was created. */
1583 if (progbar != NULL)
1584 destroy_progress_dlg(progbar);
1586 merge_close_in_files(in_file_count, in_files);
1587 if (!got_read_error && !got_write_error) {
1588 if (!wtap_dump_close(pdh, &write_err))
1589 got_write_error = TRUE;
1591 wtap_dump_close(pdh, &close_err);
1593 if (got_read_error) {
1595 * Find the file on which we got the error, and report the error.
1597 for (i = 0; i < in_file_count; i++) {
1598 if (in_files[i].state == GOT_ERROR) {
1599 /* Put up a message box noting that a read failed somewhere along
1603 case WTAP_ERR_UNSUPPORTED_ENCAP:
1604 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1605 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1608 errmsg = errmsg_errno;
1611 case WTAP_ERR_CANT_READ:
1612 errmsg = "An attempt to read from the capture file %s failed for"
1613 " some unknown reason.";
1616 case WTAP_ERR_SHORT_READ:
1617 errmsg = "The capture file %s appears to have been cut short"
1618 " in the middle of a packet.";
1621 case WTAP_ERR_BAD_RECORD:
1622 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1623 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1626 errmsg = errmsg_errno;
1630 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1631 "An error occurred while reading the"
1632 " capture file %%s: %s.", wtap_strerror(read_err));
1633 errmsg = errmsg_errno;
1636 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
1641 if (got_write_error) {
1642 /* Put up an alert box for the write error. */
1643 cf_write_failure_alert_box(out_filename, write_err);
1646 if (got_read_error || got_write_error || stop_flag) {
1647 /* Callers aren't expected to treat an error or an explicit abort
1648 differently - we put up error dialogs ourselves, so they don't
1656 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1658 const char *filter_new = dftext ? dftext : "";
1659 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1661 GTimeVal start_time;
1663 /* if new filter equals old one, do nothing unless told to do so */
1664 if (!force && strcmp(filter_new, filter_old) == 0) {
1670 if (dftext == NULL) {
1671 /* The new filter is an empty filter (i.e., display all packets).
1672 * so leave dfcode==NULL
1676 * We have a filter; make a copy of it (as we'll be saving it),
1677 * and try to compile it.
1679 dftext = g_strdup(dftext);
1680 if (!dfilter_compile(dftext, &dfcode)) {
1681 /* The attempt failed; report an error. */
1682 gchar *safe_dftext = simple_dialog_format_message(dftext);
1683 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1685 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1688 "The following display filter isn't a valid display filter:\n%s\n"
1689 "See the help for a description of the display filter syntax.",
1690 simple_dialog_primary_start(), safe_dfilter_error_msg,
1691 simple_dialog_primary_end(), safe_dftext);
1692 g_free(safe_dfilter_error_msg);
1693 g_free(safe_dftext);
1699 if (dfcode == NULL) {
1700 /* Yes - free the filter text, and set it to null. */
1706 /* We have a valid filter. Replace the current filter. */
1707 g_free(cf->dfilter);
1708 cf->dfilter = dftext;
1709 g_get_current_time(&start_time);
1712 /* Now rescan the packet list, applying the new filter, but not
1713 throwing away information constructed on a previous pass. */
1714 if (dftext == NULL) {
1715 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1717 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1720 /* Cleanup and release all dfilter resources */
1721 dfilter_free(dfcode);
1727 cf_colorize_packets(capture_file *cf)
1729 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1733 cf_reftime_packets(capture_file *cf)
1736 #ifdef NEW_PACKET_LIST
1737 ref_time_packets(cf);
1739 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1744 cf_redissect_packets(capture_file *cf)
1746 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1750 cf_read_frame_r(capture_file *cf, frame_data *fdata,
1751 union wtap_pseudo_header *pseudo_header, guint8 *pd)
1755 char errmsg_errno[1024+1];
1757 if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
1758 fdata->cap_len, &err, &err_info)) {
1761 case WTAP_ERR_UNSUPPORTED_ENCAP:
1762 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1763 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1768 case WTAP_ERR_BAD_RECORD:
1769 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1770 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
1771 wtap_strerror(err), err_info);
1776 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1777 "An error occurred while reading from the file \"%%s\": %s.",
1778 wtap_strerror(err));
1781 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg_errno, cf->filename);
1788 cf_read_frame(capture_file *cf, frame_data *fdata)
1790 return cf_read_frame_r(cf, fdata, &cf->pseudo_header, cf->pd);
1793 /* Rescan the list of packets, reconstructing the CList.
1795 "action" describes why we're doing this; it's used in the progress
1798 "action_item" describes what we're doing; it's used in the progress
1801 "refilter" is TRUE if we need to re-evaluate the filter expression.
1803 "redissect" is TRUE if we need to make the dissectors reconstruct
1804 any state information they have (because a preference that affects
1805 some dissector has changed, meaning some dissector might construct
1806 its state differently from the way it was constructed the last time). */
1807 #ifdef NEW_PACKET_LIST
1809 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1810 gboolean refilter, gboolean redissect)
1812 /* Rescan packets new packet list */
1814 progdlg_t *progbar = NULL;
1817 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1818 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1819 gboolean selected_frame_seen;
1822 GTimeVal start_time;
1823 gchar status_str[100];
1824 int progbar_nextstep;
1825 int progbar_quantum;
1827 gboolean filtering_tap_listeners;
1829 gboolean add_to_packet_list = FALSE;
1832 /* Compile the current display filter.
1833 * We assume this will not fail since cf->dfilter is only set in
1834 * cf_filter IFF the filter was valid.
1836 compiled = dfilter_compile(cf->dfilter, &dfcode);
1837 g_assert(!cf->dfilter || (compiled && dfcode));
1839 /* Do we have any tap listeners with filters? */
1840 filtering_tap_listeners = have_filtering_tap_listeners();
1842 /* Get the union of the flags for all tap listeners. */
1843 tap_flags = union_of_tap_listener_flags();
1845 reset_tap_listeners();
1846 /* Which frame, if any, is the currently selected frame?
1847 XXX - should the selected frame or the focus frame be the "current"
1848 frame, that frame being the one from which "Find Frame" searches
1850 selected_frame = cf->current_frame;
1852 /* Mark frame num as not found */
1853 selected_frame_num = -1;
1855 /* Freeze the packet list while we redo it, so we don't get any
1856 screen updates while it happens. */
1857 new_packet_list_freeze();
1860 /* We need to re-initialize all the state information that protocols
1861 keep, because some preference that controls a dissector has changed,
1862 which might cause the state information to be constructed differently
1863 by that dissector. */
1865 /* We might receive new packets while redissecting, and we don't
1866 want to dissect those before their time. */
1867 cf->redissecting = TRUE;
1869 /* Cleanup all data structures used for dissection. */
1870 cleanup_dissection();
1871 /* Initialize all data structures used for dissection. */
1874 /* We need to redissect the packets so we have to discard our old
1875 * packet list store. */
1876 new_packet_list_clear();
1877 add_to_packet_list = TRUE;
1880 /* We don't yet know which will be the first and last frames displayed. */
1881 cf->first_displayed = NULL;
1882 cf->last_displayed = NULL;
1884 /* We currently don't display any packets */
1885 cf->displayed_count = 0;
1887 /* Iterate through the list of frames. Call a routine for each frame
1888 to check whether it should be displayed and, if so, add it to
1889 the display list. */
1890 nstime_set_unset(&first_ts);
1891 nstime_set_unset(&prev_dis_ts);
1892 nstime_set_unset(&prev_cap_ts);
1895 /* Update the progress bar when it gets to this value. */
1896 progbar_nextstep = 0;
1897 /* When we reach the value that triggers a progress bar update,
1898 bump that value by this amount. */
1899 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1900 /* Count of packets at which we've looked. */
1902 /* Progress so far. */
1906 g_get_current_time(&start_time);
1908 /* no previous row yet */
1910 prev_frame_num = -1;
1913 preceding_frame_num = -1;
1914 preceding_frame = NULL;
1915 following_frame_num = -1;
1916 following_frame = NULL;
1918 selected_frame_seen = FALSE;
1920 for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
1921 /* Create the progress bar if necessary.
1922 We check on every iteration of the loop, so that it takes no
1923 longer than the standard time to create it (otherwise, for a
1924 large file, we might take considerably longer than that standard
1925 time in order to get to the next progress bar step). */
1926 if (progbar == NULL)
1927 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1928 &stop_flag, &start_time,
1931 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1932 when we update it, we have to run the GTK+ main loop to get it
1933 to repaint what's pending, and doing so may involve an "ioctl()"
1934 to see if there's any pending input from an X server, and doing
1935 that for every packet can be costly, especially on a big file. */
1936 if (count >= progbar_nextstep) {
1937 /* let's not divide by zero. I should never be started
1938 * with count == 0, so let's assert that
1940 g_assert(cf->count > 0);
1941 progbar_val = (gfloat) count / cf->count;
1943 if (progbar != NULL) {
1944 g_snprintf(status_str, sizeof(status_str),
1945 "%4u of %u frames", count, cf->count);
1946 update_progress_dlg(progbar, progbar_val, status_str);
1949 progbar_nextstep += progbar_quantum;
1953 /* Well, the user decided to abort the filtering. Just stop.
1955 XXX - go back to the previous filter? Users probably just
1956 want not to wait for a filtering operation to finish;
1957 unless we cancel by having no filter, reverting to the
1958 previous filter will probably be even more expensive than
1959 continuing the filtering, as it involves going back to the
1960 beginning and filtering, and even with no filter we currently
1961 have to re-generate the entire clist, which is also expensive.
1963 I'm not sure what Network Monitor does, but it doesn't appear
1964 to give you an unfiltered display if you cancel. */
1971 /* Since all state for the frame was destroyed, mark the frame
1972 * as not visited, free the GSList referring to the state
1973 * data (the per-frame data itself was freed by
1974 * "init_dissection()"), and null out the GSList pointer. */
1975 fdata->flags.visited = 0;
1976 frame_data_cleanup(fdata);
1978 /* cleanup_dissection() calls se_free_all();
1979 * And after that fdata->col_text (which is allocated using se_alloc0())
1980 * no longer points to valid memory.
1982 fdata->col_text_len = se_alloc0(sizeof(fdata->col_text_len) * (cf->cinfo.num_cols));
1983 fdata->col_text = se_alloc0(sizeof(fdata->col_text) * (cf->cinfo.num_cols));
1986 if (!cf_read_frame(cf, fdata))
1987 break; /* error reading the frame */
1989 /* If the previous frame is displayed, and we haven't yet seen the
1990 selected frame, remember that frame - it's the closest one we've
1991 yet seen before the selected frame. */
1992 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1993 preceding_frame_num = prev_frame_num;
1994 preceding_frame = prev_frame;
1996 add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1997 tap_flags, &cf->pseudo_header, cf->pd,
1999 add_to_packet_list);
2001 /* If this frame is displayed, and this is the first frame we've
2002 seen displayed after the selected frame, remember this frame -
2003 it's the closest one we've yet seen at or after the selected
2005 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
2006 following_frame_num = fdata->num;
2007 following_frame = fdata;
2009 if (fdata == selected_frame) {
2010 selected_frame_seen = TRUE;
2011 if (fdata->flags.passed_dfilter)
2012 selected_frame_num = fdata->num;
2015 /* Remember this frame - it'll be the previous frame
2016 on the next pass through the loop. */
2017 prev_frame_num = fdata->num;
2021 /* We are done redissecting the packet list. */
2022 cf->redissecting = FALSE;
2025 /* Clear out what remains of the visited flags and per-frame data
2028 XXX - that may cause various forms of bogosity when dissecting
2029 these frames, as they won't have been seen by this sequential
2030 pass, but the only alternative I see is to keep scanning them
2031 even though the user requested that the scan stop, and that
2032 would leave the user stuck with an Wireshark grinding on
2033 until it finishes. Should we just stick them with that? */
2034 for (; fdata != NULL; fdata = fdata->next) {
2035 fdata->flags.visited = 0;
2036 frame_data_cleanup(fdata);
2040 /* We're done filtering the packets; destroy the progress bar if it
2042 if (progbar != NULL)
2043 destroy_progress_dlg(progbar);
2045 /* Unfreeze the packet list. */
2046 if (!add_to_packet_list)
2047 new_packet_list_recreate_visible_rows();
2049 /* Compute the time it took to filter the file */
2050 compute_elapsed(&start_time);
2052 new_packet_list_thaw();
2054 if (selected_frame_num == -1) {
2055 /* The selected frame didn't pass the filter. */
2056 if (selected_frame == NULL) {
2057 /* That's because there *was* no selected frame. Make the first
2058 displayed frame the current frame. */
2059 selected_frame_num = 0;
2061 /* Find the nearest displayed frame to the selected frame (whether
2062 it's before or after that frame) and make that the current frame.
2063 If the next and previous displayed frames are equidistant from the
2064 selected frame, choose the next one. */
2065 g_assert(following_frame == NULL ||
2066 following_frame->num >= selected_frame->num);
2067 g_assert(preceding_frame == NULL ||
2068 preceding_frame->num <= selected_frame->num);
2069 if (following_frame == NULL) {
2070 /* No frame after the selected frame passed the filter, so we
2071 have to select the last displayed frame before the selected
2073 selected_frame_num = preceding_frame_num;
2074 selected_frame = preceding_frame;
2075 } else if (preceding_frame == NULL) {
2076 /* No frame before the selected frame passed the filter, so we
2077 have to select the first displayed frame after the selected
2079 selected_frame_num = following_frame_num;
2080 selected_frame = following_frame;
2082 /* Frames before and after the selected frame passed the filter, so
2083 we'll select the previous frame */
2084 selected_frame_num = preceding_frame_num;
2085 selected_frame = preceding_frame;
2090 if (selected_frame_num == -1) {
2091 /* There are no frames displayed at all. */
2092 cf_unselect_packet(cf);
2094 /* Either the frame that was selected passed the filter, or we've
2095 found the nearest displayed frame to that frame. Select it, make
2096 it the focus row, and make it visible. */
2097 /* Set to invalid to force update of packet list and packet details */
2098 cf->current_row = -1;
2099 if (selected_frame_num == 0) {
2100 new_packet_list_select_first_row();
2102 new_packet_list_find_row_from_data(selected_frame, TRUE);
2106 /* Cleanup and release all dfilter resources */
2107 dfilter_free(dfcode);
2113 rescan_packets(capture_file *cf, const char *action, const char *action_item,
2114 gboolean refilter, gboolean redissect)
2117 progdlg_t *progbar = NULL;
2120 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
2121 int selected_row, prev_row, preceding_row, following_row;
2122 gboolean selected_frame_seen;
2125 GTimeVal start_time;
2126 gchar status_str[100];
2127 int progbar_nextstep;
2128 int progbar_quantum;
2130 gboolean filtering_tap_listeners;
2132 gboolean add_to_packet_list = TRUE;
2135 /* Compile the current display filter.
2136 * We assume this will not fail since cf->dfilter is only set in
2137 * cf_filter IFF the filter was valid.
2139 compiled = dfilter_compile(cf->dfilter, &dfcode);
2140 g_assert(!cf->dfilter || (compiled && dfcode));
2142 /* Do we have any tap listeners with filters? */
2143 filtering_tap_listeners = have_filtering_tap_listeners();
2145 /* Get the union of the flags for all tap listeners. */
2146 tap_flags = union_of_tap_listener_flags();
2148 reset_tap_listeners();
2149 /* Which frame, if any, is the currently selected frame?
2150 XXX - should the selected frame or the focus frame be the "current"
2151 frame, that frame being the one from which "Find Frame" searches
2153 selected_frame = cf->current_frame;
2155 /* We don't yet know what row that frame will be on, if any, after we
2156 rebuild the clist, however. */
2159 /* Freeze the packet list while we redo it, so we don't get any
2160 screen updates while it happens. */
2161 packet_list_freeze();
2164 packet_list_clear();
2167 /* We need to re-initialize all the state information that protocols
2168 keep, because some preference that controls a dissector has changed,
2169 which might cause the state information to be constructed differently
2170 by that dissector. */
2172 /* We might receive new packets while redissecting, and we don't
2173 want to dissect those before their time. */
2174 cf->redissecting = TRUE;
2176 /* Cleanup all data structures used for dissection. */
2177 cleanup_dissection();
2178 /* Initialize all data structures used for dissection. */
2183 /* We don't yet know which will be the first and last frames displayed. */
2184 cf->first_displayed = NULL;
2185 cf->last_displayed = NULL;
2189 /* We currently don't display any packets */
2190 cf->displayed_count = 0;
2192 /* Iterate through the list of frames. Call a routine for each frame
2193 to check whether it should be displayed and, if so, add it to
2194 the display list. */
2195 nstime_set_unset(&first_ts);
2196 nstime_set_unset(&prev_dis_ts);
2197 nstime_set_unset(&prev_cap_ts);
2200 /* Update the progress bar when it gets to this value. */
2201 progbar_nextstep = 0;
2202 /* When we reach the value that triggers a progress bar update,
2203 bump that value by this amount. */
2204 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2205 /* Count of packets at which we've looked. */
2207 /* Progress so far. */
2211 g_get_current_time(&start_time);
2213 row = -1; /* no previous row yet */
2218 preceding_frame = NULL;
2220 following_frame = NULL;
2222 selected_frame_seen = FALSE;
2224 for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
2225 /* Create the progress bar if necessary.
2226 We check on every iteration of the loop, so that it takes no
2227 longer than the standard time to create it (otherwise, for a
2228 large file, we might take considerably longer than that standard
2229 time in order to get to the next progress bar step). */
2230 if (progbar == NULL)
2231 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
2232 &stop_flag, &start_time,
2235 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2236 when we update it, we have to run the GTK+ main loop to get it
2237 to repaint what's pending, and doing so may involve an "ioctl()"
2238 to see if there's any pending input from an X server, and doing
2239 that for every packet can be costly, especially on a big file. */
2240 if (count >= progbar_nextstep) {
2241 /* let's not divide by zero. I should never be started
2242 * with count == 0, so let's assert that
2244 g_assert(cf->count > 0);
2245 progbar_val = (gfloat) count / cf->count;
2247 if (progbar != NULL) {
2248 g_snprintf(status_str, sizeof(status_str),
2249 "%4u of %u frames", count, cf->count);
2250 update_progress_dlg(progbar, progbar_val, status_str);
2253 progbar_nextstep += progbar_quantum;
2257 /* Well, the user decided to abort the filtering. Just stop.
2259 XXX - go back to the previous filter? Users probably just
2260 want not to wait for a filtering operation to finish;
2261 unless we cancel by having no filter, reverting to the
2262 previous filter will probably be even more expensive than
2263 continuing the filtering, as it involves going back to the
2264 beginning and filtering, and even with no filter we currently
2265 have to re-generate the entire clist, which is also expensive.
2267 I'm not sure what Network Monitor does, but it doesn't appear
2268 to give you an unfiltered display if you cancel. */
2275 /* Since all state for the frame was destroyed, mark the frame
2276 * as not visited, free the GSList referring to the state
2277 * data (the per-frame data itself was freed by
2278 * "init_dissection()"), and null out the GSList pointer.
2280 fdata->flags.visited = 0;
2281 frame_data_cleanup(fdata);
2284 if (!cf_read_frame(cf, fdata))
2285 break; /* error reading the frame */
2287 /* If the previous frame is displayed, and we haven't yet seen the
2288 selected frame, remember that frame - it's the closest one we've
2289 yet seen before the selected frame. */
2290 if (prev_row != -1 && !selected_frame_seen) {
2291 preceding_row = prev_row;
2292 preceding_frame = prev_frame;
2294 row = add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
2295 tap_flags, &cf->pseudo_header, cf->pd,
2297 add_to_packet_list);
2299 /* If this frame is displayed, and this is the first frame we've
2300 seen displayed after the selected frame, remember this frame -
2301 it's the closest one we've yet seen at or after the selected
2303 if (row != -1 && selected_frame_seen && following_row == -1) {
2304 following_row = row;
2305 following_frame = fdata;
2307 if (fdata == selected_frame) {
2309 selected_frame_seen = TRUE;
2312 /* Remember this row/frame - it'll be the previous row/frame
2313 on the next pass through the loop. */
2318 /* We are done redissecting the packet list. */
2319 cf->redissecting = FALSE;
2322 /* Clear out what remains of the visited flags and per-frame data
2325 XXX - that may cause various forms of bogosity when dissecting
2326 these frames, as they won't have been seen by this sequential
2327 pass, but the only alternative I see is to keep scanning them
2328 even though the user requested that the scan stop, and that
2329 would leave the user stuck with an Wireshark grinding on
2330 until it finishes. Should we just stick them with that? */
2331 for (; fdata != NULL; fdata = fdata->next) {
2332 fdata->flags.visited = 0;
2333 frame_data_cleanup(fdata);
2337 /* We're done filtering the packets; destroy the progress bar if it
2339 if (progbar != NULL)
2340 destroy_progress_dlg(progbar);
2342 /* Unfreeze the packet list. */
2345 if (selected_row == -1) {
2346 /* The selected frame didn't pass the filter. */
2347 if (selected_frame == NULL) {
2348 /* That's because there *was* no selected frame. Make the first
2349 displayed frame the current frame. */
2352 /* Find the nearest displayed frame to the selected frame (whether
2353 it's before or after that frame) and make that the current frame.
2354 If the next and previous displayed frames are equidistant from the
2355 selected frame, choose the next one. */
2356 g_assert(following_frame == NULL ||
2357 following_frame->num >= selected_frame->num);
2358 g_assert(preceding_frame == NULL ||
2359 preceding_frame->num <= selected_frame->num);
2360 if (following_frame == NULL) {
2361 /* No frame after the selected frame passed the filter, so we
2362 have to select the last displayed frame before the selected
2364 selected_row = preceding_row;
2365 } else if (preceding_frame == NULL) {
2366 /* No frame before the selected frame passed the filter, so we
2367 have to select the first displayed frame after the selected
2369 selected_row = following_row;
2371 /* Frames before and after the selected frame passed the filter, so
2372 we'll select the previous frame */
2373 selected_row = preceding_row;
2378 if (selected_row == -1) {
2379 /* There are no frames displayed at all. */
2380 cf_unselect_packet(cf);
2382 /* Either the frame that was selected passed the filter, or we've
2383 found the nearest displayed frame to that frame. Select it, make
2384 it the focus row, and make it visible. */
2385 if (selected_row == 0) {
2386 /* Set to invalid to force update of packet list and packet details */
2387 cf->current_row = -1;
2389 packet_list_set_selected_row(selected_row);
2392 /* Cleanup and release all dfilter resources */
2393 dfilter_free(dfcode);
2395 #endif /* NEW_PACKET_LIST */
2398 * Scan trough all frame data and recalculate the ref time
2399 * without rereading the file.
2400 * XXX - do we need a progres bar or is this fast enough?
2402 #ifdef NEW_PACKET_LIST
2404 ref_time_packets(capture_file *cf)
2408 nstime_set_unset(&first_ts);
2409 nstime_set_unset(&prev_dis_ts);
2412 for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
2413 /* just add some value here until we know if it is being displayed or not */
2414 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
2420 /* If we don't have the time stamp of the first packet in the
2421 capture, it's because this is the first packet. Save the time
2422 stamp of this packet as the time stamp of the first packet. */
2423 if (nstime_is_unset(&first_ts)) {
2424 first_ts = fdata->abs_ts;
2426 /* if this frames is marked as a reference time frame, reset
2427 firstsec and firstusec to this frame */
2428 if(fdata->flags.ref_time){
2429 first_ts = fdata->abs_ts;
2432 /* If we don't have the time stamp of the previous displayed packet,
2433 it's because this is the first displayed packet. Save the time
2434 stamp of this packet as the time stamp of the previous displayed
2436 if (nstime_is_unset(&prev_dis_ts)) {
2437 prev_dis_ts = fdata->abs_ts;
2440 /* Get the time elapsed between the first packet and this packet. */
2441 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
2443 /* If it's greater than the current elapsed time, set the elapsed time
2444 to it (we check for "greater than" so as not to be confused by
2445 time moving backwards). */
2446 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
2447 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
2448 cf->elapsed_time = fdata->rel_ts;
2451 /* Get the time elapsed between the previous displayed packet and
2453 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
2455 prev_dis_ts = fdata->abs_ts;
2460 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
2461 /* This frame either passed the display filter list or is marked as
2462 a time reference frame. All time reference frames are displayed
2463 even if they dont pass the display filter */
2464 if(fdata->flags.ref_time){
2465 /* if this was a TIME REF frame we should reset the cum_bytes field */
2466 cum_bytes = fdata->pkt_len;
2467 fdata->cum_bytes = cum_bytes;
2469 /* increase cum_bytes with this packets length */
2470 cum_bytes += fdata->pkt_len;
2484 process_specified_packets(capture_file *cf, packet_range_t *range,
2485 const char *string1, const char *string2, gboolean terminate_is_stop,
2486 gboolean (*callback)(capture_file *, frame_data *,
2487 union wtap_pseudo_header *, const guint8 *, void *),
2488 void *callback_args)
2491 union wtap_pseudo_header pseudo_header;
2492 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
2493 psp_return_t ret = PSP_FINISHED;
2495 progdlg_t *progbar = NULL;
2498 gboolean progbar_stop_flag;
2499 GTimeVal progbar_start_time;
2500 gchar progbar_status_str[100];
2501 int progbar_nextstep;
2502 int progbar_quantum;
2503 range_process_e process_this;
2505 /* Update the progress bar when it gets to this value. */
2506 progbar_nextstep = 0;
2507 /* When we reach the value that triggers a progress bar update,
2508 bump that value by this amount. */
2509 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2510 /* Count of packets at which we've looked. */
2512 /* Progress so far. */
2515 progbar_stop_flag = FALSE;
2516 g_get_current_time(&progbar_start_time);
2518 packet_range_process_init(range);
2520 /* Iterate through the list of packets, printing the packets that
2521 were selected by the current display filter. */
2522 for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
2523 /* Create the progress bar if necessary.
2524 We check on every iteration of the loop, so that it takes no
2525 longer than the standard time to create it (otherwise, for a
2526 large file, we might take considerably longer than that standard
2527 time in order to get to the next progress bar step). */
2528 if (progbar == NULL)
2529 progbar = delayed_create_progress_dlg(string1, string2,
2532 &progbar_start_time,
2535 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2536 when we update it, we have to run the GTK+ main loop to get it
2537 to repaint what's pending, and doing so may involve an "ioctl()"
2538 to see if there's any pending input from an X server, and doing
2539 that for every packet can be costly, especially on a big file. */
2540 if (progbar_count >= progbar_nextstep) {
2541 /* let's not divide by zero. I should never be started
2542 * with count == 0, so let's assert that
2544 g_assert(cf->count > 0);
2545 progbar_val = (gfloat) progbar_count / cf->count;
2547 if (progbar != NULL) {
2548 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2549 "%4u of %u packets", progbar_count, cf->count);
2550 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2553 progbar_nextstep += progbar_quantum;
2556 if (progbar_stop_flag) {
2557 /* Well, the user decided to abort the operation. Just stop,
2558 and arrange to return PSP_STOPPED to our caller, so they know
2559 it was stopped explicitly. */
2566 /* do we have to process this packet? */
2567 process_this = packet_range_process_packet(range, fdata);
2568 if (process_this == range_process_next) {
2569 /* this packet uninteresting, continue with next one */
2571 } else if (process_this == range_processing_finished) {
2572 /* all interesting packets processed, stop the loop */
2576 /* Get the packet */
2577 if (!cf_read_frame_r(cf, fdata, &pseudo_header, pd)) {
2578 /* Attempt to get the packet failed. */
2582 /* Process the packet */
2583 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
2584 /* Callback failed. We assume it reported the error appropriately. */
2590 /* We're done printing the packets; destroy the progress bar if
2592 if (progbar != NULL)
2593 destroy_progress_dlg(progbar);
2599 gboolean construct_protocol_tree;
2601 } retap_callback_args_t;
2604 retap_packet(capture_file *cf _U_, frame_data *fdata,
2605 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2608 retap_callback_args_t *args = argsp;
2611 epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
2612 tap_queue_init(&edt);
2613 epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
2614 tap_push_tapped_queue(&edt);
2615 epan_dissect_cleanup(&edt);
2621 cf_retap_packets(capture_file *cf)
2623 packet_range_t range;
2624 retap_callback_args_t callback_args;
2625 gboolean filtering_tap_listeners;
2628 /* Do we have any tap listeners with filters? */
2629 filtering_tap_listeners = have_filtering_tap_listeners();
2631 tap_flags = union_of_tap_listener_flags();
2633 /* If any tap listeners have filters, or require the protocol tree,
2634 construct the protocol tree. */
2635 callback_args.construct_protocol_tree = filtering_tap_listeners ||
2636 (tap_flags & TL_REQUIRES_PROTO_TREE);
2638 /* If any tap listeners require the columns, construct them. */
2639 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2641 /* Reset the tap listeners. */
2642 reset_tap_listeners();
2644 /* Iterate through the list of packets, dissecting all packets and
2645 re-running the taps. */
2646 packet_range_init(&range);
2647 packet_range_process_init(&range);
2648 switch (process_specified_packets(cf, &range, "Recalculating statistics on",
2649 "all packets", TRUE, retap_packet,
2652 /* Completed successfully. */
2656 /* Well, the user decided to abort the refiltering.
2657 Return CF_READ_ABORTED so our caller knows they did that. */
2658 return CF_READ_ABORTED;
2661 /* Error while retapping. */
2662 return CF_READ_ERROR;
2665 g_assert_not_reached();
2670 print_args_t *print_args;
2671 gboolean print_header_line;
2672 char *header_line_buf;
2673 int header_line_buf_len;
2674 gboolean print_formfeed;
2675 gboolean print_separator;
2679 } print_callback_args_t;
2682 print_packet(capture_file *cf, frame_data *fdata,
2683 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2686 print_callback_args_t *args = argsp;
2693 gboolean proto_tree_needed;
2694 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2695 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2697 /* Create the protocol tree, and make it visible, if we're printing
2698 the dissection or the hex data.
2699 XXX - do we need it if we're just printing the hex data? */
2701 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2702 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2704 /* Fill in the column information if we're printing the summary
2706 if (args->print_args->print_summary) {
2707 col_custom_prime_edt(&edt, &cf->cinfo);
2708 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2709 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2711 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2713 if (args->print_formfeed) {
2714 if (!new_page(args->print_args->stream))
2717 if (args->print_separator) {
2718 if (!print_line(args->print_args->stream, 0, ""))
2724 * We generate bookmarks, if the output format supports them.
2725 * The name is "__frameN__".
2727 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2729 if (args->print_args->print_summary) {
2730 if (args->print_header_line) {
2731 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2733 args->print_header_line = FALSE; /* we might not need to print any more */
2735 cp = &args->line_buf[0];
2737 for (i = 0; i < cf->cinfo.num_cols; i++) {
2738 /* Find the length of the string for this column. */
2739 column_len = (int) strlen(cf->cinfo.col_data[i]);
2740 if (args->col_widths[i] > column_len)
2741 column_len = args->col_widths[i];
2743 /* Make sure there's room in the line buffer for the column; if not,
2744 double its length. */
2745 line_len += column_len + 1; /* "+1" for space */
2746 if (line_len > args->line_buf_len) {
2747 cp_off = (int) (cp - args->line_buf);
2748 args->line_buf_len = 2 * line_len;
2749 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2750 cp = args->line_buf + cp_off;
2753 /* Right-justify the packet number column. */
2754 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2755 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
2757 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
2759 if (i != cf->cinfo.num_cols - 1)
2765 * Generate a bookmark, using the summary line as the title.
2767 if (!print_bookmark(args->print_args->stream, bookmark_name,
2771 if (!print_line(args->print_args->stream, 0, args->line_buf))
2775 * Generate a bookmark, using "Frame N" as the title, as we're not
2776 * printing the summary line.
2778 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2779 if (!print_bookmark(args->print_args->stream, bookmark_name,
2782 } /* if (print_summary) */
2784 if (args->print_args->print_dissections != print_dissections_none) {
2785 if (args->print_args->print_summary) {
2786 /* Separate the summary line from the tree with a blank line. */
2787 if (!print_line(args->print_args->stream, 0, ""))
2791 /* Print the information in that tree. */
2792 if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
2795 /* Print a blank line if we print anything after this (aka more than one packet). */
2796 args->print_separator = TRUE;
2798 /* Print a header line if we print any more packet summaries */
2799 args->print_header_line = TRUE;
2802 if (args->print_args->print_hex) {
2803 /* Print the full packet data as hex. */
2804 if (!print_hex_data(args->print_args->stream, &edt))
2807 /* Print a blank line if we print anything after this (aka more than one packet). */
2808 args->print_separator = TRUE;
2810 /* Print a header line if we print any more packet summaries */
2811 args->print_header_line = TRUE;
2812 } /* if (args->print_args->print_dissections != print_dissections_none) */
2814 epan_dissect_cleanup(&edt);
2816 /* do we want to have a formfeed between each packet from now on? */
2817 if(args->print_args->print_formfeed) {
2818 args->print_formfeed = TRUE;
2824 epan_dissect_cleanup(&edt);
2829 cf_print_packets(capture_file *cf, print_args_t *print_args)
2832 print_callback_args_t callback_args;
2840 callback_args.print_args = print_args;
2841 callback_args.print_header_line = TRUE;
2842 callback_args.header_line_buf = NULL;
2843 callback_args.header_line_buf_len = 256;
2844 callback_args.print_formfeed = FALSE;
2845 callback_args.print_separator = FALSE;
2846 callback_args.line_buf = NULL;
2847 callback_args.line_buf_len = 256;
2848 callback_args.col_widths = NULL;
2850 if (!print_preamble(print_args->stream, cf->filename)) {
2851 destroy_print_stream(print_args->stream);
2852 return CF_PRINT_WRITE_ERROR;
2855 if (print_args->print_summary) {
2856 /* We're printing packet summaries. Allocate the header line buffer
2857 and get the column widths. */
2858 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2860 /* Find the widths for each of the columns - maximum of the
2861 width of the title and the width of the data - and construct
2862 a buffer with a line containing the column titles. */
2863 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2864 cp = &callback_args.header_line_buf[0];
2866 for (i = 0; i < cf->cinfo.num_cols; i++) {
2867 /* Don't pad the last column. */
2868 if (i == cf->cinfo.num_cols - 1)
2869 callback_args.col_widths[i] = 0;
2871 callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
2872 data_width = get_column_char_width(get_column_format(i));
2873 if (data_width > callback_args.col_widths[i])
2874 callback_args.col_widths[i] = data_width;
2877 /* Find the length of the string for this column. */
2878 column_len = (int) strlen(cf->cinfo.col_title[i]);
2879 if (callback_args.col_widths[i] > column_len)
2880 column_len = callback_args.col_widths[i];
2882 /* Make sure there's room in the line buffer for the column; if not,
2883 double its length. */
2884 line_len += column_len + 1; /* "+1" for space */
2885 if (line_len > callback_args.header_line_buf_len) {
2886 cp_off = (int) (cp - callback_args.header_line_buf);
2887 callback_args.header_line_buf_len = 2 * line_len;
2888 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2889 callback_args.header_line_buf_len + 1);
2890 cp = callback_args.header_line_buf + cp_off;
2893 /* Right-justify the packet number column. */
2894 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2895 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2897 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2899 if (i != cf->cinfo.num_cols - 1)
2904 /* Now start out the main line buffer with the same length as the
2905 header line buffer. */
2906 callback_args.line_buf_len = callback_args.header_line_buf_len;
2907 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2908 } /* if (print_summary) */
2910 /* Iterate through the list of packets, printing the packets we were
2912 ret = process_specified_packets(cf, &print_args->range, "Printing",
2913 "selected packets", TRUE, print_packet,
2916 g_free(callback_args.header_line_buf);
2917 g_free(callback_args.line_buf);
2918 g_free(callback_args.col_widths);
2923 /* Completed successfully. */
2927 /* Well, the user decided to abort the printing.
2929 XXX - note that what got generated before they did that
2930 will get printed if we're piping to a print program; we'd
2931 have to write to a file and then hand that to the print
2932 program to make it actually not print anything. */
2936 /* Error while printing.
2938 XXX - note that what got generated before they did that
2939 will get printed if we're piping to a print program; we'd
2940 have to write to a file and then hand that to the print
2941 program to make it actually not print anything. */
2942 destroy_print_stream(print_args->stream);
2943 return CF_PRINT_WRITE_ERROR;
2946 if (!print_finale(print_args->stream)) {
2947 destroy_print_stream(print_args->stream);
2948 return CF_PRINT_WRITE_ERROR;
2951 if (!destroy_print_stream(print_args->stream))
2952 return CF_PRINT_WRITE_ERROR;
2958 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2959 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2965 /* Create the protocol tree, but don't fill in the column information. */
2966 epan_dissect_init(&edt, TRUE, TRUE);
2967 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2969 /* Write out the information in that tree. */
2970 proto_tree_write_pdml(&edt, fh);
2972 epan_dissect_cleanup(&edt);
2978 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2983 fh = ws_fopen(print_args->file, "w");
2985 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2987 write_pdml_preamble(fh);
2990 return CF_PRINT_WRITE_ERROR;
2993 /* Iterate through the list of packets, printing the packets we were
2995 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2996 "selected packets", TRUE,
2997 write_pdml_packet, fh);
3002 /* Completed successfully. */
3006 /* Well, the user decided to abort the printing. */
3010 /* Error while printing. */
3012 return CF_PRINT_WRITE_ERROR;
3015 write_pdml_finale(fh);
3018 return CF_PRINT_WRITE_ERROR;
3021 /* XXX - check for an error */
3028 write_psml_packet(capture_file *cf, frame_data *fdata,
3029 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3034 gboolean proto_tree_needed;
3036 /* Fill in the column information, only create the protocol tree
3037 if having custom columns. */
3038 proto_tree_needed = have_custom_cols(&cf->cinfo);
3039 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
3040 col_custom_prime_edt(&edt, &cf->cinfo);
3041 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
3042 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
3044 /* Write out the information in that tree. */
3045 proto_tree_write_psml(&edt, fh);
3047 epan_dissect_cleanup(&edt);
3053 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
3058 fh = ws_fopen(print_args->file, "w");
3060 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
3062 write_psml_preamble(fh);
3065 return CF_PRINT_WRITE_ERROR;
3068 /* Iterate through the list of packets, printing the packets we were
3070 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
3071 "selected packets", TRUE,
3072 write_psml_packet, fh);
3077 /* Completed successfully. */
3081 /* Well, the user decided to abort the printing. */
3085 /* Error while printing. */
3087 return CF_PRINT_WRITE_ERROR;
3090 write_psml_finale(fh);
3093 return CF_PRINT_WRITE_ERROR;
3096 /* XXX - check for an error */
3103 write_csv_packet(capture_file *cf, frame_data *fdata,
3104 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3109 gboolean proto_tree_needed;
3111 /* Fill in the column information, only create the protocol tree
3112 if having custom columns. */
3113 proto_tree_needed = have_custom_cols(&cf->cinfo);
3114 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
3115 col_custom_prime_edt(&edt, &cf->cinfo);
3116 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
3117 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
3119 /* Write out the information in that tree. */
3120 proto_tree_write_csv(&edt, fh);
3122 epan_dissect_cleanup(&edt);
3128 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
3133 fh = ws_fopen(print_args->file, "w");
3135 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
3137 write_csv_preamble(fh);
3140 return CF_PRINT_WRITE_ERROR;
3143 /* Iterate through the list of packets, printing the packets we were
3145 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
3146 "selected packets", TRUE,
3147 write_csv_packet, fh);
3152 /* Completed successfully. */
3156 /* Well, the user decided to abort the printing. */
3160 /* Error while printing. */
3162 return CF_PRINT_WRITE_ERROR;
3165 write_csv_finale(fh);
3168 return CF_PRINT_WRITE_ERROR;
3171 /* XXX - check for an error */
3178 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
3179 union wtap_pseudo_header *pseudo_header _U_,
3180 const guint8 *pd, void *argsp)
3184 proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh);
3189 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
3194 fh = ws_fopen(print_args->file, "w");
3197 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
3199 write_carrays_preamble(fh);
3203 return CF_PRINT_WRITE_ERROR;
3206 /* Iterate through the list of packets, printing the packets we were
3208 ret = process_specified_packets(cf, &print_args->range,
3210 "selected packets", TRUE,
3211 write_carrays_packet, fh);
3214 /* Completed successfully. */
3217 /* Well, the user decided to abort the printing. */
3220 /* Error while printing. */
3222 return CF_PRINT_WRITE_ERROR;
3225 write_carrays_finale(fh);
3229 return CF_PRINT_WRITE_ERROR;
3236 #ifndef NEW_PACKET_LIST /* This function is not needed with the new packet list */
3238 /* Scan through the packet list and change all columns that use the
3239 "command-line-specified" time stamp format to use the current
3240 value of that format. */
3242 cf_change_time_formats(capture_file *cf)
3246 progdlg_t *progbar = NULL;
3251 GTimeVal start_time;
3252 gchar status_str[100];
3253 int progbar_nextstep;
3254 int progbar_quantum;
3255 gboolean sorted_by_frame_column;
3257 /* Adjust timestamp precision if auto is selected */
3258 cf_timestamp_auto_precision(cf);
3260 /* Are there any columns with time stamps in the "command-line-specified"
3263 XXX - we have to force the "column is writable" flag on, as it
3264 might be off from the last frame that was dissected. */
3265 col_set_writable(&cf->cinfo, TRUE);
3266 if (!check_col(&cf->cinfo, COL_CLS_TIME) &&
3267 !check_col(&cf->cinfo, COL_ABS_TIME) &&
3268 !check_col(&cf->cinfo, COL_ABS_DATE_TIME) &&
3269 !check_col(&cf->cinfo, COL_REL_TIME) &&
3270 !check_col(&cf->cinfo, COL_DELTA_TIME) &&
3271 !check_col(&cf->cinfo, COL_DELTA_TIME_DIS)) {
3272 /* No, there aren't any columns in that format, so we have no work
3277 /* Freeze the packet list while we redo it, so we don't get any
3278 screen updates while it happens. */
3279 packet_list_freeze();
3281 /* Update the progress bar when it gets to this value. */
3282 progbar_nextstep = 0;
3283 /* When we reach the value that triggers a progress bar update,
3284 bump that value by this amount. */
3285 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3286 /* Count of packets at which we've looked. */
3288 /* Progress so far. */
3291 /* If the rows are currently sorted by the frame column then we know
3292 * the row number of each packet: it's the row number of the previously
3293 * displayed packet + 1.
3295 * Otherwise, if the display is sorted by a different column then we have
3296 * to use the O(N) packet_list_find_row_from_data() (thus making the job
3297 * of changing the time display format O(N**2)).
3299 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
3300 * the row number and walks that many elements down the clist to find
3301 * the appropriate element.)
3303 sorted_by_frame_column = FALSE;
3304 for (i = 0; i < cf->cinfo.num_cols; i++) {
3305 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
3307 sorted_by_frame_column = (i == packet_list_get_sort_column());
3313 g_get_current_time(&start_time);
3315 /* Iterate through the list of packets, checking whether the packet
3316 is in a row of the summary list and, if so, whether there are
3317 any columns that show the time in the "command-line-specified"
3318 format and, if so, update that row. */
3319 for (fdata = cf->plist_start, row = -1; fdata != NULL; fdata = fdata->next) {
3320 /* Create the progress bar if necessary.
3321 We check on every iteration of the loop, so that it takes no
3322 longer than the standard time to create it (otherwise, for a
3323 large file, we might take considerably longer than that standard
3324 time in order to get to the next progress bar step). */
3325 if (progbar == NULL)
3326 progbar = delayed_create_progress_dlg("Changing", "time display",
3327 TRUE, &stop_flag, &start_time, progbar_val);
3329 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3330 when we update it, we have to run the GTK+ main loop to get it
3331 to repaint what's pending, and doing so may involve an "ioctl()"
3332 to see if there's any pending input from an X server, and doing
3333 that for every packet can be costly, especially on a big file. */
3334 if (count >= progbar_nextstep) {
3335 /* let's not divide by zero. I should never be started
3336 * with count == 0, so let's assert that
3338 g_assert(cf->count > 0);
3340 progbar_val = (gfloat) count / cf->count;
3342 if (progbar != NULL) {
3343 g_snprintf(status_str, sizeof(status_str),
3344 "%4u of %u packets", count, cf->count);
3345 update_progress_dlg(progbar, progbar_val, status_str);
3348 progbar_nextstep += progbar_quantum;
3352 /* Well, the user decided to abort the redisplay. Just stop.
3354 XXX - this leaves the time field in the old format in
3355 frames we haven't yet processed. So it goes; should we
3356 simply not offer them the option of stopping? */
3362 /* Find what row this packet is in. */
3363 if (!sorted_by_frame_column) {
3364 /* This function is O(N), so we try to avoid using it... */
3365 row = packet_list_find_row_from_data(fdata);
3367 /* ...which we do by maintaining a count of packets that are
3368 being displayed (i.e., that have passed the display filter),
3369 and using the current value of that count as the row number
3370 (which is why we can only do it when the display is sorted
3371 by the frame number). */
3372 if (fdata->flags.passed_dfilter)
3379 /* This packet is in the summary list, on row "row". */
3381 for (i = 0; i < cf->cinfo.num_cols; i++) {
3382 if (col_has_time_fmt(&cf->cinfo, i)) {
3383 /* This is one of the columns that shows the time in
3384 "command-line-specified" format; update it. */
3385 cf->cinfo.col_buf[i][0] = '\0';
3386 col_set_fmt_time(fdata, &cf->cinfo, cf->cinfo.col_fmt[i], i);
3387 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
3393 /* We're done redisplaying the packets; destroy the progress bar if it
3395 if (progbar != NULL)
3396 destroy_progress_dlg(progbar);
3398 /* Set the column widths of those columns that show the time in
3399 "command-line-specified" format. */
3400 for (i = 0; i < cf->cinfo.num_cols; i++) {
3401 if (col_has_time_fmt(&cf->cinfo, i)) {
3402 packet_list_set_time_width(cf->cinfo.col_fmt[i], i);
3406 /* Unfreeze the packet list. */
3409 #endif /* NEW_PACKET_LIST */
3416 gboolean frame_matched;
3420 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
3421 search_direction dir)
3425 mdata.string = string;
3426 mdata.string_len = strlen(string);
3427 return find_packet(cf, match_protocol_tree, &mdata, dir);
3431 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
3433 match_data *mdata = criterion;
3436 /* Load the frame's data. */
3437 if (!cf_read_frame(cf, fdata)) {
3438 /* Attempt to get the packet failed. */
3442 /* Construct the protocol tree, including the displayed text */
3443 epan_dissect_init(&edt, TRUE, TRUE);
3444 /* We don't need the column information */
3445 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3447 /* Iterate through all the nodes, seeing if they have text that matches. */
3449 mdata->frame_matched = FALSE;
3450 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
3451 epan_dissect_cleanup(&edt);
3452 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3456 match_subtree_text(proto_node *node, gpointer data)
3458 match_data *mdata = (match_data*) data;
3459 const gchar *string = mdata->string;
3460 size_t string_len = mdata->string_len;
3461 capture_file *cf = mdata->cf;
3462 field_info *fi = PNODE_FINFO(node);
3463 gchar label_str[ITEM_LABEL_LENGTH];
3470 g_assert(fi && "dissection with an invisible proto tree?");
3472 if (mdata->frame_matched) {
3473 /* We already had a match; don't bother doing any more work. */
3477 /* Don't match invisible entries. */
3478 if (PROTO_ITEM_IS_HIDDEN(node))
3481 /* was a free format label produced? */
3483 label_ptr = fi->rep->representation;
3485 /* no, make a generic label */
3486 label_ptr = label_str;
3487 proto_item_fill_label(fi, label_str);
3490 /* Does that label match? */
3491 label_len = strlen(label_ptr);
3492 for (i = 0; i < label_len; i++) {
3493 c_char = label_ptr[i];
3495 c_char = toupper(c_char);
3496 if (c_char == string[c_match]) {
3498 if (c_match == string_len) {
3499 /* No need to look further; we have a match */
3500 mdata->frame_matched = TRUE;
3507 /* Recurse into the subtree, if it exists */
3508 if (node->first_child != NULL)
3509 proto_tree_children_foreach(node, match_subtree_text, mdata);
3513 cf_find_packet_summary_line(capture_file *cf, const char *string,
3514 search_direction dir)
3518 mdata.string = string;
3519 mdata.string_len = strlen(string);
3520 return find_packet(cf, match_summary_line, &mdata, dir);
3524 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3526 match_data *mdata = criterion;
3527 const gchar *string = mdata->string;
3528 size_t string_len = mdata->string_len;
3530 const char *info_column;
3531 size_t info_column_len;
3532 match_result result = MR_NOTMATCHED;
3538 /* Load the frame's data. */
3539 if (!cf_read_frame(cf, fdata)) {
3540 /* Attempt to get the packet failed. */
3544 /* Don't bother constructing the protocol tree */
3545 epan_dissect_init(&edt, FALSE, FALSE);
3546 /* Get the column information */
3547 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
3549 /* Find the Info column */
3550 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3551 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
3552 /* Found it. See if we match. */
3553 info_column = edt.pi.cinfo->col_data[colx];
3554 info_column_len = strlen(info_column);
3555 for (i = 0; i < info_column_len; i++) {
3556 c_char = info_column[i];
3558 c_char = toupper(c_char);
3559 if (c_char == string[c_match]) {
3561 if (c_match == string_len) {
3562 result = MR_MATCHED;
3571 epan_dissect_cleanup(&edt);
3578 } cbs_t; /* "Counted byte string" */
3581 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3582 search_direction dir)
3587 info.data_len = string_size;
3589 /* String or hex search? */
3591 /* String search - what type of string? */
3592 switch (cf->scs_type) {
3594 case SCS_ASCII_AND_UNICODE:
3595 return find_packet(cf, match_ascii_and_unicode, &info, dir);
3598 return find_packet(cf, match_ascii, &info, dir);
3601 return find_packet(cf, match_unicode, &info, dir);
3604 g_assert_not_reached();
3608 return find_packet(cf, match_binary, &info, dir);
3612 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3614 cbs_t *info = criterion;
3615 const guint8 *ascii_text = info->data;
3616 size_t textlen = info->data_len;
3617 match_result result;
3623 /* Load the frame's data. */
3624 if (!cf_read_frame(cf, fdata)) {
3625 /* Attempt to get the packet failed. */
3629 result = MR_NOTMATCHED;
3630 buf_len = fdata->pkt_len;
3631 for (i = 0; i < buf_len; i++) {
3634 c_char = toupper(c_char);
3636 if (c_char == ascii_text[c_match]) {
3638 if (c_match == textlen) {
3639 result = MR_MATCHED;
3640 cf->search_pos = i; /* Save the position of the last character
3641 for highlighting the field. */
3652 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
3654 cbs_t *info = criterion;
3655 const guint8 *ascii_text = info->data;
3656 size_t textlen = info->data_len;
3657 match_result result;
3663 /* Load the frame's data. */
3664 if (!cf_read_frame(cf, fdata)) {
3665 /* Attempt to get the packet failed. */
3669 result = MR_NOTMATCHED;
3670 buf_len = fdata->pkt_len;
3671 for (i = 0; i < buf_len; i++) {
3674 c_char = toupper(c_char);
3675 if (c_char == ascii_text[c_match]) {
3677 if (c_match == textlen) {
3678 result = MR_MATCHED;
3679 cf->search_pos = i; /* Save the position of the last character
3680 for highlighting the field. */
3690 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3692 cbs_t *info = criterion;
3693 const guint8 *ascii_text = info->data;
3694 size_t textlen = info->data_len;
3695 match_result result;
3701 /* Load the frame's data. */
3702 if (!cf_read_frame(cf, fdata)) {
3703 /* Attempt to get the packet failed. */
3707 result = MR_NOTMATCHED;
3708 buf_len = fdata->pkt_len;
3709 for (i = 0; i < buf_len; i++) {
3712 c_char = toupper(c_char);
3713 if (c_char == ascii_text[c_match]) {
3716 if (c_match == textlen) {
3717 result = MR_MATCHED;
3718 cf->search_pos = i; /* Save the position of the last character
3719 for highlighting the field. */
3729 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3731 cbs_t *info = criterion;
3732 const guint8 *binary_data = info->data;
3733 size_t datalen = info->data_len;
3734 match_result result;
3739 /* Load the frame's data. */
3740 if (!cf_read_frame(cf, fdata)) {
3741 /* Attempt to get the packet failed. */
3745 result = MR_NOTMATCHED;
3746 buf_len = fdata->pkt_len;
3747 for (i = 0; i < buf_len; i++) {
3748 if (cf->pd[i] == binary_data[c_match]) {
3750 if (c_match == datalen) {
3751 result = MR_MATCHED;
3752 cf->search_pos = i; /* Save the position of the last character
3753 for highlighting the field. */
3763 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3764 search_direction dir)
3766 return find_packet(cf, match_dfilter, sfcode, dir);
3770 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3771 search_direction dir)
3776 if (!dfilter_compile(filter, &sfcode)) {
3778 * XXX - this shouldn't happen, as the filter string is machine
3783 if (sfcode == NULL) {
3785 * XXX - this shouldn't happen, as the filter string is machine
3790 result = find_packet(cf, match_dfilter, sfcode, dir);
3791 dfilter_free(sfcode);
3796 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3798 dfilter_t *sfcode = criterion;
3800 match_result result;
3802 /* Load the frame's data. */
3803 if (!cf_read_frame(cf, fdata)) {
3804 /* Attempt to get the packet failed. */
3808 epan_dissect_init(&edt, TRUE, FALSE);
3809 epan_dissect_prime_dfilter(&edt, sfcode);
3810 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3811 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3812 epan_dissect_cleanup(&edt);
3817 cf_find_packet_marked(capture_file *cf, search_direction dir)
3819 return find_packet(cf, match_marked, NULL, dir);
3823 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3825 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3829 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3831 return find_packet(cf, match_time_reference, NULL, dir);
3835 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3837 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3841 find_packet(capture_file *cf,
3842 match_result (*match_function)(capture_file *, frame_data *, void *),
3843 void *criterion, search_direction dir)
3845 frame_data *start_fd;
3847 frame_data *new_fd = NULL;
3848 progdlg_t *progbar = NULL;
3853 GTimeVal start_time;
3854 gchar status_str[100];
3855 int progbar_nextstep;
3856 int progbar_quantum;
3858 match_result result;
3860 start_fd = cf->current_frame;
3861 if (start_fd != NULL) {
3862 /* Iterate through the list of packets, starting at the packet we've
3863 picked, calling a routine to run the filter on the packet, see if
3864 it matches, and stop if so. */
3868 /* Update the progress bar when it gets to this value. */
3869 progbar_nextstep = 0;
3870 /* When we reach the value that triggers a progress bar update,
3871 bump that value by this amount. */
3872 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3873 /* Progress so far. */
3877 g_get_current_time(&start_time);
3880 title = cf->sfilter?cf->sfilter:"";
3882 /* Create the progress bar if necessary.
3883 We check on every iteration of the loop, so that it takes no
3884 longer than the standard time to create it (otherwise, for a
3885 large file, we might take considerably longer than that standard
3886 time in order to get to the next progress bar step). */
3887 if (progbar == NULL)
3888 progbar = delayed_create_progress_dlg("Searching", title,
3889 FALSE, &stop_flag, &start_time, progbar_val);
3891 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3892 when we update it, we have to run the GTK+ main loop to get it
3893 to repaint what's pending, and doing so may involve an "ioctl()"
3894 to see if there's any pending input from an X server, and doing
3895 that for every packet can be costly, especially on a big file. */
3896 if (count >= progbar_nextstep) {
3897 /* let's not divide by zero. I should never be started
3898 * with count == 0, so let's assert that
3900 g_assert(cf->count > 0);
3902 progbar_val = (gfloat) count / cf->count;
3904 if (progbar != NULL) {
3905 g_snprintf(status_str, sizeof(status_str),
3906 "%4u of %u packets", count, cf->count);
3907 update_progress_dlg(progbar, progbar_val, status_str);
3910 progbar_nextstep += progbar_quantum;
3914 /* Well, the user decided to abort the search. Go back to the
3915 frame where we started. */
3920 /* Go past the current frame. */
3921 if (dir == SD_BACKWARD) {
3922 /* Go on to the previous frame. */
3923 fdata = fdata->prev;
3924 if (fdata == NULL) {
3926 * XXX - other apps have a bit more of a detailed message
3927 * for this, and instead of offering "OK" and "Cancel",
3928 * they offer things such as "Continue" and "Cancel";
3929 * we need an API for popping up alert boxes with
3930 * {Verb} and "Cancel".
3933 if (prefs.gui_find_wrap)
3935 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3936 fdata = cf->plist_end; /* wrap around */
3940 statusbar_push_temporary_msg("Search reached the beginning.");
3941 fdata = start_fd; /* stay on previous packet */
3945 /* Go on to the next frame. */
3946 fdata = fdata->next;
3947 if (fdata == NULL) {
3948 if (prefs.gui_find_wrap)
3950 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3951 fdata = cf->plist_start; /* wrap around */
3955 statusbar_push_temporary_msg("Search reached the end.");
3956 fdata = start_fd; /* stay on previous packet */
3963 /* Is this packet in the display? */
3964 if (fdata->flags.passed_dfilter) {
3965 /* Yes. Does it match the search criterion? */
3966 result = (*match_function)(cf, fdata, criterion);
3967 if (result == MR_ERROR) {
3968 /* Error; our caller has reported the error. Go back to the frame
3969 where we started. */
3972 } else if (result == MR_MATCHED) {
3973 /* Yes. Go to the new frame. */
3979 if (fdata == start_fd) {
3980 /* We're back to the frame we were on originally, and that frame
3981 doesn't match the search filter. The search failed. */
3986 /* We're done scanning the packets; destroy the progress bar if it
3988 if (progbar != NULL)
3989 destroy_progress_dlg(progbar);
3992 if (new_fd != NULL) {
3993 #ifdef NEW_PACKET_LIST
3994 /* Find and select */
3995 row = new_packet_list_find_row_from_data(fdata, TRUE);
3997 /* We found a frame. Find what row it's in. */
3998 row = packet_list_find_row_from_data(new_fd);
3999 #endif /* NEW_PACKET_LIST */
4001 /* We didn't find a row even though we know that a frame
4002 * exists that satifies the search criteria. This means that the
4003 * frame isn't being displayed currently so we can't select it. */
4004 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
4005 "%sEnd of capture exceeded!%s\n\n"
4006 "The capture file is probably not fully loaded.",
4007 simple_dialog_primary_start(), simple_dialog_primary_end());
4011 #ifndef NEW_PACKET_LIST
4012 /* Select that row, make it the focus row, and make it visible. */
4013 packet_list_set_selected_row(row);
4014 #endif /* NEW_PACKET_LIST */
4015 return TRUE; /* success */
4017 return FALSE; /* failure */
4021 cf_goto_frame(capture_file *cf, guint fnumber)
4026 for (fdata = cf->plist_start; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
4029 if (fdata == NULL) {
4030 /* we didn't find a packet with that packet number */
4031 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
4032 return FALSE; /* we failed to go to that packet */
4034 if (!fdata->flags.passed_dfilter) {
4035 /* that packet currently isn't displayed */
4036 /* XXX - add it to the set of displayed packets? */
4037 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
4038 return FALSE; /* we failed to go to that packet */
4041 #ifdef NEW_PACKET_LIST
4042 row = new_packet_list_find_row_from_data(fdata, TRUE);
4044 /* We found that packet, and it's currently being displayed.
4045 Find what row it's in. */
4046 row = packet_list_find_row_from_data(fdata);
4047 g_assert(row != -1);
4049 /* Select that row, make it the focus row, and make it visible. */
4050 packet_list_set_selected_row(row);
4051 #endif /* NEW_PACKET_LIST */
4052 return TRUE; /* we got to that packet */
4056 cf_goto_top_frame(capture_file *cf _U_)
4058 #ifdef NEW_PACKET_LIST
4059 /* Find and select */
4060 new_packet_list_select_first_row();
4064 frame_data *lowest_fdata = NULL;
4066 for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
4067 if (fdata->flags.passed_dfilter) {
4068 lowest_fdata = fdata;
4073 if (lowest_fdata == NULL) {
4077 /* We found that packet, and it's currently being displayed.
4078 Find what row it's in. */
4079 row = packet_list_find_row_from_data(lowest_fdata);
4080 g_assert(row != -1);
4082 /* Select that row, make it the focus row, and make it visible. */
4083 packet_list_set_selected_row(row);
4084 #endif /* NEW_PACKET_LIST */
4085 return TRUE; /* we got to that packet */
4089 cf_goto_bottom_frame(capture_file *cf _U_) /* cf is unused w/ NEW_PACKET_LIST */
4091 #ifdef NEW_PACKET_LIST
4092 /* Find and select */
4093 new_packet_list_select_last_row();
4097 frame_data *highest_fdata = NULL;
4099 for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
4100 if (fdata->flags.passed_dfilter) {
4101 highest_fdata = fdata;
4105 if (highest_fdata == NULL) {
4109 /* We found that packet, and it's currently being displayed.
4110 Find what row it's in. */
4111 row = packet_list_find_row_from_data(highest_fdata);
4112 g_assert(row != -1);
4114 /* Select that row, make it the focus row, and make it visible. */
4115 packet_list_set_selected_row(row);
4116 #endif /* NEW_PACKET_LIST */
4117 return TRUE; /* we got to that packet */
4121 * Go to frame specified by currently selected protocol tree item.
4124 cf_goto_framenum(capture_file *cf)
4126 header_field_info *hfinfo;
4129 if (cf->finfo_selected) {
4130 hfinfo = cf->finfo_selected->hfinfo;
4132 if (hfinfo->type == FT_FRAMENUM) {
4133 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
4135 return cf_goto_frame(cf, framenum);
4142 /* Select the packet on a given row. */
4144 cf_select_packet(capture_file *cf, int row)
4148 /* Get the frame data struct pointer for this frame */
4149 #ifdef NEW_PACKET_LIST
4150 fdata = new_packet_list_get_row_data(row);
4152 fdata = (frame_data *)packet_list_get_row_data(row);
4155 if (fdata == NULL) {
4156 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
4157 the first entry is added to it by "real_insert_row()", that row
4158 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
4159 our version and the vanilla GTK+ version).
4161 This means that a "select-row" signal is emitted; this causes
4162 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
4165 "cf_select_packet()" fetches, above, the data associated with the
4166 row that was selected; however, as "gtk_clist_append()", which
4167 called "real_insert_row()", hasn't yet returned, we haven't yet
4168 associated any data with that row, so we get back a null pointer.
4170 We can't assume that there's only one frame in the frame list,
4171 either, as we may be filtering the display.
4173 We therefore assume that, if "row" is 0, i.e. the first row
4174 is being selected, and "cf->first_displayed" equals
4175 "cf->last_displayed", i.e. there's only one frame being
4176 displayed, that frame is the frame we want.
4178 This means we have to set "cf->first_displayed" and
4179 "cf->last_displayed" before adding the row to the
4180 GtkCList; see the comment in "add_packet_to_packet_list()". */
4182 if (row == 0 && cf->first_displayed == cf->last_displayed)
4183 fdata = cf->first_displayed;
4186 /* If fdata _still_ isn't set simply give up. */
4187 if (fdata == NULL) {
4191 /* Get the data in that frame. */
4192 if (!cf_read_frame (cf, fdata)) {
4196 /* Record that this frame is the current frame. */
4197 cf->current_frame = fdata;
4198 cf->current_row = row;
4200 /* Create the logical protocol tree. */
4201 if (cf->edt != NULL)
4202 epan_dissect_free(cf->edt);
4204 /* We don't need the columns here. */
4205 cf->edt = epan_dissect_new(TRUE, TRUE);
4207 tap_build_interesting(cf->edt);
4208 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
4211 dfilter_macro_build_ftv_cache(cf->edt->tree);
4213 cf_callback_invoke(cf_cb_packet_selected, cf);
4216 /* Unselect the selected packet, if any. */
4218 cf_unselect_packet(capture_file *cf)
4220 /* Destroy the epan_dissect_t for the unselected packet. */
4221 if (cf->edt != NULL) {
4222 epan_dissect_free(cf->edt);
4226 /* No packet is selected. */
4227 cf->current_frame = NULL;
4228 cf->current_row = 0;
4230 cf_callback_invoke(cf_cb_packet_unselected, cf);
4232 /* No protocol tree means no selected field. */
4233 cf_unselect_field(cf);
4236 /* Unset the selected protocol tree field, if any. */
4238 cf_unselect_field(capture_file *cf)
4240 cf->finfo_selected = NULL;
4242 cf_callback_invoke(cf_cb_field_unselected, cf);
4246 * Mark a particular frame.
4249 cf_mark_frame(capture_file *cf, frame_data *frame)
4251 if (! frame->flags.marked) {
4252 frame->flags.marked = TRUE;
4253 if (cf->count > cf->marked_count)
4259 * Unmark a particular frame.
4262 cf_unmark_frame(capture_file *cf, frame_data *frame)
4264 if (frame->flags.marked) {
4265 frame->flags.marked = FALSE;
4266 if (cf->marked_count > 0)
4272 * Ignore a particular frame.
4275 cf_ignore_frame(capture_file *cf, frame_data *frame)
4277 if (! frame->flags.ignored) {
4278 frame->flags.ignored = TRUE;
4279 if (cf->count > cf->ignored_count)
4280 cf->ignored_count++;
4285 * Un-ignore a particular frame.
4288 cf_unignore_frame(capture_file *cf, frame_data *frame)
4290 if (frame->flags.ignored) {
4291 frame->flags.ignored = FALSE;
4292 if (cf->ignored_count > 0)
4293 cf->ignored_count--;
4300 } save_callback_args_t;
4303 * Save a capture to a file, in a particular format, saving either
4304 * all packets, all currently-displayed packets, or all marked packets.
4306 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4307 * up a message box for the failure.
4310 save_packet(capture_file *cf _U_, frame_data *fdata,
4311 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
4314 save_callback_args_t *args = argsp;
4315 struct wtap_pkthdr hdr;
4318 /* init the wtap header for saving */
4319 hdr.ts.secs = fdata->abs_ts.secs;
4320 hdr.ts.nsecs = fdata->abs_ts.nsecs;
4321 hdr.caplen = fdata->cap_len;
4322 hdr.len = fdata->pkt_len;
4323 hdr.pkt_encap = fdata->lnk_t;
4325 /* and save the packet */
4326 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
4327 cf_write_failure_alert_box(args->fname, err);
4334 * Can this capture file be saved in any format except by copying the raw data?
4337 cf_can_save_as(capture_file *cf)
4341 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
4342 /* To save a file with Wiretap, Wiretap has to handle that format,
4343 and its code to handle that format must be able to write a file
4344 with this file's encapsulation type. */
4345 if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
4346 /* OK, we can write it out in this type. */
4351 /* No, we couldn't save it in any format. */
4356 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
4358 gchar *from_filename;
4362 save_callback_args_t callback_args;
4364 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4366 /* don't write over an existing file. */
4367 /* this should've been already checked by our caller, just to be sure... */
4368 if (file_exists(fname)) {
4369 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4370 "%sCapture file: \"%s\" already exists!%s\n\n"
4371 "Please choose a different filename.",
4372 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
4376 packet_range_process_init(range);
4378 if (packet_range_process_all(range) && save_format == cf->cd_t) {
4379 /* We're not filtering packets, and we're saving it in the format
4380 it's already in, so we can just move or copy the raw data. */
4382 if (cf->is_tempfile) {
4383 /* The file being saved is a temporary file from a live
4384 capture, so it doesn't need to stay around under that name;
4385 first, try renaming the capture buffer file to the new name. */
4387 if (ws_rename(cf->filename, fname) == 0) {
4388 /* That succeeded - there's no need to copy the source file. */
4389 from_filename = NULL;
4392 if (errno == EXDEV) {
4393 /* They're on different file systems, so we have to copy the
4396 from_filename = cf->filename;
4398 /* The rename failed, but not because they're on different
4399 file systems - put up an error message. (Or should we
4400 just punt and try to copy? The only reason why I'd
4401 expect the rename to fail and the copy to succeed would
4402 be if we didn't have permission to remove the file from
4403 the temporary directory, and that might be fixable - but
4404 is it worth requiring the user to go off and fix it?) */
4405 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4406 file_rename_error_message(errno), fname);
4412 from_filename = cf->filename;
4415 /* It's a permanent file, so we should copy it, and not remove the
4418 from_filename = cf->filename;
4422 /* Copy the file, if we haven't moved it. */
4423 if (!copy_file_binary_mode(from_filename, fname))
4427 /* Either we're filtering packets, or we're saving in a different
4428 format; we can't do that by copying or moving the capture file,
4429 we have to do it by writing the packets out in Wiretap. */
4430 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
4433 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4437 /* XXX - we let the user save a subset of the packets.
4439 If we do that, should we make that file the current file? If so,
4440 it means we can no longer get at the other packets. What does
4443 /* Iterate through the list of packets, processing the packets we were
4446 XXX - we've already called "packet_range_process_init(range)", but
4447 "process_specified_packets()" will do it again. Fortunately,
4448 that's harmless in this case, as we haven't done anything to
4449 "range" since we initialized it. */
4450 callback_args.pdh = pdh;
4451 callback_args.fname = fname;
4452 switch (process_specified_packets(cf, range, "Saving", "selected packets",
4453 TRUE, save_packet, &callback_args)) {
4456 /* Completed successfully. */
4460 /* The user decided to abort the saving.
4461 XXX - remove the output file? */
4465 /* Error while saving. */
4466 wtap_dump_close(pdh, &err);
4470 if (!wtap_dump_close(pdh, &err)) {
4471 cf_close_failure_alert_box(fname, err);
4476 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4478 if (packet_range_process_all(range)) {
4479 /* We saved the entire capture, not just some packets from it.
4480 Open and read the file we saved it to.
4482 XXX - this is somewhat of a waste; we already have the
4483 packets, all this gets us is updated file type information
4484 (which we could just stuff into "cf"), and having the new
4485 file be the one we have opened and from which we're reading
4486 the data, and it means we have to spend time opening and
4487 reading the file, which could be a significant amount of
4488 time if the file is large. */
4489 cf->user_saved = TRUE;
4491 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
4492 /* XXX - report errors if this fails?
4493 What should we return if it fails or is aborted? */
4495 switch (cf_read(cf, TRUE)) {
4499 /* Just because we got an error, that doesn't mean we were unable
4500 to read any of the file; we handle what we could get from the
4504 case CF_READ_ABORTED:
4505 /* The user bailed out of re-reading the capture file; the
4506 capture file has been closed - just return (without
4507 changing any menu settings; "cf_close()" set them
4508 correctly for the "no capture file open" state). */
4511 cf_callback_invoke(cf_cb_file_save_reload_finished, cf);
4517 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4522 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
4523 gboolean for_writing, int file_type)
4526 /* Wiretap error. */
4529 case WTAP_ERR_NOT_REGULAR_FILE:
4530 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4531 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4535 case WTAP_ERR_RANDOM_OPEN_PIPE:
4536 /* Seen only when opening a capture file for reading. */
4537 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4538 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
4542 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
4543 /* Seen only when opening a capture file for reading. */
4544 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4545 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
4549 case WTAP_ERR_UNSUPPORTED:
4550 /* Seen only when opening a capture file for reading. */
4551 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4552 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
4554 filename, err_info);
4558 case WTAP_ERR_CANT_WRITE_TO_PIPE:
4559 /* Seen only when opening a capture file for writing. */
4560 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4561 "The file \"%s\" is a pipe, and %s capture files can't be "
4562 "written to a pipe.",
4563 filename, wtap_file_type_string(file_type));
4566 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
4567 /* Seen only when opening a capture file for writing. */
4568 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4569 "Wireshark doesn't support writing capture files in that format.");
4572 case WTAP_ERR_UNSUPPORTED_ENCAP:
4574 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4575 "Wireshark can't save this capture in that format.");
4577 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4578 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
4580 filename, err_info);
4585 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
4587 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4588 "Wireshark can't save this capture in that format.");
4590 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4591 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
4596 case WTAP_ERR_BAD_RECORD:
4597 /* Seen only when opening a capture file for reading. */
4598 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4599 "The file \"%s\" appears to be damaged or corrupt.\n"
4601 filename, err_info);
4605 case WTAP_ERR_CANT_OPEN:
4607 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4608 "The file \"%s\" could not be created for some unknown reason.",
4611 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4612 "The file \"%s\" could not be opened for some unknown reason.",
4617 case WTAP_ERR_SHORT_READ:
4618 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4619 "The file \"%s\" appears to have been cut short"
4620 " in the middle of a packet or other data.",
4624 case WTAP_ERR_SHORT_WRITE:
4625 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4626 "A full header couldn't be written to the file \"%s\".",
4630 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4631 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4632 "Gzip compression not supported by this file type.");
4636 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4637 "The file \"%s\" could not be %s: %s.",
4639 for_writing ? "created" : "opened",
4640 wtap_strerror(err));
4645 open_failure_alert_box(filename, err, for_writing);
4650 file_rename_error_message(int err)
4653 static char errmsg_errno[1024+1];
4658 errmsg = "The path to the file \"%s\" doesn't exist.";
4662 errmsg = "You don't have permission to move the capture file to \"%s\".";
4666 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4667 "The file \"%%s\" could not be moved: %s.",
4668 wtap_strerror(err));
4669 errmsg = errmsg_errno;
4676 cf_write_failure_alert_box(const char *filename, int err)
4679 /* Wiretap error. */
4680 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4681 "An error occurred while writing to the file \"%s\": %s.",
4682 filename, wtap_strerror(err));
4685 write_failure_alert_box(filename, err);
4689 /* Check for write errors - if the file is being written to an NFS server,
4690 a write error may not show up until the file is closed, as NFS clients
4691 might not send writes to the server until the "write()" call finishes,
4692 so that the write may fail on the server but the "write()" may succeed. */
4694 cf_close_failure_alert_box(const char *filename, int err)
4697 /* Wiretap error. */
4700 case WTAP_ERR_CANT_CLOSE:
4701 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4702 "The file \"%s\" couldn't be closed for some unknown reason.",
4706 case WTAP_ERR_SHORT_WRITE:
4707 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4708 "Not all the packets could be written to the file \"%s\".",
4713 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4714 "An error occurred while closing the file \"%s\": %s.",
4715 filename, wtap_strerror(err));
4720 We assume that a close error from the OS is really a write error. */
4721 write_failure_alert_box(filename, err);
4725 /* Reload the current capture file. */
4727 cf_reload(capture_file *cf) {
4729 gboolean is_tempfile;
4732 /* If the file could be opened, "cf_open()" calls "cf_close()"
4733 to get rid of state for the old capture file before filling in state
4734 for the new capture file. "cf_close()" will remove the file if
4735 it's a temporary file; we don't want that to happen (for one thing,
4736 it'd prevent subsequent reopens from working). Remember whether it's
4737 a temporary file, mark it as not being a temporary file, and then
4738 reopen it as the type of file it was.
4740 Also, "cf_close()" will free "cf->filename", so we must make
4741 a copy of it first. */
4742 filename = g_strdup(cf->filename);
4743 is_tempfile = cf->is_tempfile;
4744 cf->is_tempfile = FALSE;
4745 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4746 switch (cf_read(cf, FALSE)) {
4750 /* Just because we got an error, that doesn't mean we were unable
4751 to read any of the file; we handle what we could get from the
4755 case CF_READ_ABORTED:
4756 /* The user bailed out of re-reading the capture file; the
4757 capture file has been closed - just free the capture file name
4758 string and return (without changing the last containing
4764 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4765 Instead, the file was left open, so we should restore "cf->is_tempfile"
4768 XXX - change the menu? Presumably "cf_open()" will do that;
4769 make sure it does! */
4770 cf->is_tempfile = is_tempfile;
4772 /* "cf_open()" made a copy of the file name we handed it, so
4773 we should free up our copy. */
4783 * indent-tabs-mode: nil
4786 * ex: set shiftwidth=2 tabstop=8 expandtab
4787 * :indentSize=2:tabSize=8:noTabs=true: