6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #include <epan/epan.h>
47 #include <epan/filesystem.h>
50 #include "color_filters.h"
52 #include <epan/column.h>
53 #include <epan/packet.h>
54 #include <epan/column-utils.h>
55 #include "packet-range.h"
61 #include "alert_box.h"
62 #include "simple_dialog.h"
63 #include "progress_dlg.h"
65 #include <epan/prefs.h>
66 #include <epan/dfilter/dfilter.h>
67 #include <epan/epan_dissect.h>
69 #include <epan/dissectors/packet-data.h>
70 #include <epan/dissectors/packet-ber.h>
71 #include <epan/timestamp.h>
72 #include <epan/dfilter/dfilter-macro.h>
73 #include <wsutil/file_util.h>
74 #include <epan/strutil.h>
78 gboolean auto_scroll_live;
81 static nstime_t first_ts;
82 static nstime_t prev_dis_ts;
83 static guint32 cum_bytes = 0;
84 static gulong computed_elapsed;
86 static void cf_reset_state(capture_file *cf);
88 static int read_packet(capture_file *cf, dfilter_t *dfcode,
89 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset);
91 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
92 gboolean refilter, gboolean redissect);
94 static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata,
96 static void match_subtree_text(proto_node *node, gpointer data);
97 static gboolean match_summary_line(capture_file *cf, frame_data *fdata,
99 static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
101 static gboolean match_ascii(capture_file *cf, frame_data *fdata,
103 static gboolean match_unicode(capture_file *cf, frame_data *fdata,
105 static gboolean match_binary(capture_file *cf, frame_data *fdata,
107 static gboolean match_dfilter(capture_file *cf, frame_data *fdata,
109 static gboolean find_packet(capture_file *cf,
110 gboolean (*match_function)(capture_file *, frame_data *, void *),
113 static void cf_open_failure_alert_box(const char *filename, int err,
114 gchar *err_info, gboolean for_writing,
116 static const char *file_rename_error_message(int err);
117 static void cf_write_failure_alert_box(const char *filename, int err);
118 static void cf_close_failure_alert_box(const char *filename, int err);
119 #ifdef NEW_PACKET_LIST
120 static void ref_time_packets(capture_file *cf);
122 /* Update the progress bar this many times when reading a file. */
123 #define N_PROGBAR_UPDATES 100
125 /* Number of "frame_data" structures per memory chunk.
126 XXX - is this the right number? */
127 #define FRAME_DATA_CHUNK_SIZE 1024
130 /* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
132 cf_callback_t cb_fct;
134 } cf_callback_data_t;
136 static GList *cf_callbacks = NULL;
139 cf_callback_invoke(int event, gpointer data)
141 cf_callback_data_t *cb;
142 GList *cb_item = cf_callbacks;
144 /* there should be at least one interested */
145 g_assert(cb_item != NULL);
147 while(cb_item != NULL) {
149 cb->cb_fct(event, data, cb->user_data);
150 cb_item = g_list_next(cb_item);
156 cf_callback_add(cf_callback_t func, gpointer user_data)
158 cf_callback_data_t *cb;
160 cb = g_malloc(sizeof(cf_callback_data_t));
162 cb->user_data = user_data;
164 cf_callbacks = g_list_append(cf_callbacks, cb);
168 cf_callback_remove(cf_callback_t func)
170 cf_callback_data_t *cb;
171 GList *cb_item = cf_callbacks;
173 while(cb_item != NULL) {
175 if(cb->cb_fct == func) {
176 cf_callbacks = g_list_remove(cf_callbacks, cb);
180 cb_item = g_list_next(cb_item);
183 g_assert_not_reached();
187 cf_timestamp_auto_precision(capture_file *cf)
189 int prec = timestamp_get_precision();
192 /* don't try to get the file's precision if none is opened */
193 if(cf->state == FILE_CLOSED) {
197 /* if we are in auto mode, set precision of current file */
198 if(prec == TS_PREC_AUTO ||
199 prec == TS_PREC_AUTO_SEC ||
200 prec == TS_PREC_AUTO_DSEC ||
201 prec == TS_PREC_AUTO_CSEC ||
202 prec == TS_PREC_AUTO_MSEC ||
203 prec == TS_PREC_AUTO_USEC ||
204 prec == TS_PREC_AUTO_NSEC)
206 switch(wtap_file_tsprecision(cf->wth)) {
207 case(WTAP_FILE_TSPREC_SEC):
208 timestamp_set_precision(TS_PREC_AUTO_SEC);
210 case(WTAP_FILE_TSPREC_DSEC):
211 timestamp_set_precision(TS_PREC_AUTO_DSEC);
213 case(WTAP_FILE_TSPREC_CSEC):
214 timestamp_set_precision(TS_PREC_AUTO_CSEC);
216 case(WTAP_FILE_TSPREC_MSEC):
217 timestamp_set_precision(TS_PREC_AUTO_MSEC);
219 case(WTAP_FILE_TSPREC_USEC):
220 timestamp_set_precision(TS_PREC_AUTO_USEC);
222 case(WTAP_FILE_TSPREC_NSEC):
223 timestamp_set_precision(TS_PREC_AUTO_NSEC);
226 g_assert_not_reached();
233 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
238 wth = wtap_open_offline(fname, err, &err_info, TRUE);
242 /* The open succeeded. Close whatever capture file we had open,
243 and fill in the information for this file. */
246 /* Initialize all data structures used for dissection. */
249 /* We're about to start reading the file. */
250 cf->state = FILE_READ_IN_PROGRESS;
255 /* Set the file name because we need it to set the follow stream filter.
256 XXX - is that still true? We need it for other reasons, though,
258 cf->filename = g_strdup(fname);
260 /* Indicate whether it's a permanent or temporary file. */
261 cf->is_tempfile = is_tempfile;
263 /* If it's a temporary capture buffer file, mark it as not saved. */
264 cf->user_saved = !is_tempfile;
266 cf->cd_t = wtap_file_type(cf->wth);
268 cf->displayed_count = 0;
269 cf->marked_count = 0;
270 cf->drops_known = FALSE;
272 cf->snap = wtap_snapshot_length(cf->wth);
274 /* Snapshot length not known. */
275 cf->has_snap = FALSE;
276 cf->snap = WTAP_MAX_PACKET_SIZE;
279 nstime_set_zero(&cf->elapsed_time);
280 nstime_set_unset(&first_ts);
281 nstime_set_unset(&prev_dis_ts);
283 #if GLIB_CHECK_VERSION(2,10,0)
285 /* memory chunks have been deprecated in favor of the slice allocator,
286 * which has been added in 2.10
288 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
290 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
292 g_assert(cf->plist_chunk);
294 /* change the time formats now, as we might have a new precision */
295 cf_change_time_formats(cf);
297 fileset_file_opened(fname);
299 if(cf->cd_t == WTAP_FILE_BER) {
300 /* tell the BER dissector the file name */
301 ber_set_filename(cf->filename);
307 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
313 * Reset the state for the currently closed file, but don't do the
314 * UI callbacks; this is for use in "cf_open()", where we don't
315 * want the UI to go from "file open" to "file closed" back to
316 * "file open", we want it to go from "old file open" to "new file
317 * open and being read".
320 cf_reset_state(capture_file *cf)
322 /* Die if we're in the middle of reading a file. */
323 g_assert(cf->state != FILE_READ_IN_PROGRESS);
329 /* We have no file open... */
330 if (cf->filename != NULL) {
331 /* If it's a temporary file, remove it. */
333 ws_unlink(cf->filename);
334 g_free(cf->filename);
337 /* ...which means we have nothing to save. */
338 cf->user_saved = FALSE;
340 #if GLIB_CHECK_VERSION(2,10,0)
341 if (cf->plist != NULL)
342 g_slice_free_chain(frame_data, cf->plist, next);
344 /* memory chunks have been deprecated in favor of the slice allocator,
345 * which has been added in 2.10
347 if (cf->plist_chunk != NULL) {
348 g_mem_chunk_destroy(cf->plist_chunk);
349 cf->plist_chunk = NULL;
352 if (cf->rfcode != NULL) {
353 dfilter_free(cf->rfcode);
357 cf->plist_end = NULL;
358 cf_unselect_packet(cf); /* nothing to select */
359 cf->first_displayed = NULL;
360 cf->last_displayed = NULL;
362 /* No frame selected, no field in that frame selected. */
363 cf->current_frame = NULL;
365 cf->finfo_selected = NULL;
367 /* Clear the packet list. */
368 #ifdef NEW_PACKET_LIST
369 new_packet_list_freeze();
370 new_packet_list_clear();
371 new_packet_list_thaw();
373 packet_list_freeze();
380 nstime_set_zero(&cf->elapsed_time);
382 reset_tap_listeners();
384 /* We have no file open. */
385 cf->state = FILE_CLOSED;
387 fileset_file_closed();
390 /* Reset everything to a pristine state */
392 cf_close(capture_file *cf)
394 /* do GUI things even if file is already closed,
395 * e.g. to cleanup things if a capture couldn't be started */
396 cf_callback_invoke(cf_cb_file_closing, cf);
398 /* close things, if not already closed before */
399 if(cf->state != FILE_CLOSED) {
400 color_filters_cleanup();
402 cleanup_dissection();
405 cf_callback_invoke(cf_cb_file_closed, cf);
408 /* an out of memory exception occured, wait for a user button press to exit */
409 void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
415 cf_get_computed_elapsed(void){
416 return computed_elapsed;
418 static void compute_elapsed(GTimeVal *start_time)
423 g_get_current_time(&time_now);
425 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
426 time_now.tv_usec - start_time->tv_usec;
428 computed_elapsed = (gulong) (delta_time / 1000); /* ms*/
432 cf_read(capture_file *cf)
436 const gchar *name_ptr;
438 char errmsg_errno[1024+1];
440 progdlg_t *volatile progbar = NULL;
442 volatile gint64 size;
444 volatile float progbar_val;
446 gchar status_str[100];
447 volatile gint64 progbar_nextstep;
448 volatile gint64 progbar_quantum;
450 gboolean filtering_tap_listeners;
453 volatile int displayed_once = 0;
456 /* Compile the current display filter.
457 * We assume this will not fail since cf->dfilter is only set in
458 * cf_filter IFF the filter was valid.
462 dfilter_compile(cf->dfilter, &dfcode);
465 /* Do we have any tap listeners with filters? */
466 filtering_tap_listeners = have_filtering_tap_listeners();
468 /* Get the union of the flags for all tap listeners. */
469 tap_flags = union_of_tap_listener_flags();
473 reset_tap_listeners();
475 cf_callback_invoke(cf_cb_file_read_start, cf);
477 name_ptr = get_basename(cf->filename);
479 /* Find the size of the file. */
480 size = wtap_file_size(cf->wth, NULL);
482 /* Update the progress bar when it gets to this value. */
483 progbar_nextstep = 0;
484 /* When we reach the value that triggers a progress bar update,
485 bump that value by this amount. */
487 progbar_quantum = size/N_PROGBAR_UPDATES;
490 /* Progress so far. */
493 #ifdef NEW_PACKET_LIST
494 new_packet_list_freeze();
496 packet_list_freeze();
500 g_get_current_time(&start_time);
502 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
504 /* Create the progress bar if necessary.
505 We check on every iteration of the loop, so that it takes no
506 longer than the standard time to create it (otherwise, for a
507 large file, we might take considerably longer than that standard
508 time in order to get to the next progress bar step). */
509 if (progbar == NULL) {
510 progbar = delayed_create_progress_dlg("Loading", name_ptr,
511 TRUE, &stop_flag, &start_time, progbar_val);
514 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
515 when we update it, we have to run the GTK+ main loop to get it
516 to repaint what's pending, and doing so may involve an "ioctl()"
517 to see if there's any pending input from an X server, and doing
518 that for every packet can be costly, especially on a big file. */
519 if (data_offset >= progbar_nextstep) {
520 file_pos = wtap_read_so_far(cf->wth, NULL);
521 progbar_val = (gfloat) file_pos / (gfloat) size;
522 if (progbar_val > 1.0) {
523 /* The file probably grew while we were reading it.
524 Update file size, and try again. */
525 size = wtap_file_size(cf->wth, NULL);
527 progbar_val = (gfloat) file_pos / (gfloat) size;
528 /* If it's still > 1, either "wtap_file_size()" failed (in which
529 case there's not much we can do about it), or the file
530 *shrank* (in which case there's not much we can do about
531 it); just clip the progress value at 1.0. */
532 if (progbar_val > 1.0f)
535 if (progbar != NULL) {
536 /* update the packet lists content on the first run or frequently on very large files */
537 /* (on smaller files the display update takes longer than reading the file) */
539 if (progbar_quantum > 500000 || displayed_once == 0) {
540 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
542 #ifdef NEW_PACKET_LIST
543 /* XXX - Add move to end function call. Freeze/thaw if
547 if (auto_scroll_live)
548 packet_list_moveto_end();
549 packet_list_freeze();
550 #endif /* NEW_PACKET_LIST */
553 #endif /* HAVE_LIBPCAP */
554 g_snprintf(status_str, sizeof(status_str),
555 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
556 file_pos / 1024, size / 1024);
557 update_progress_dlg(progbar, progbar_val, status_str);
559 progbar_nextstep += progbar_quantum;
564 /* Well, the user decided to abort the read. He/She will be warned and
565 it might be enough for him/her to work with the already loaded
567 This is especially true for very large capture files, where you don't
568 want to wait loading the whole file (which may last minutes or even
569 hours even on fast machines) just to see that it was the wrong file. */
573 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
575 CATCH(OutOfMemoryError) {
578 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
579 "%sOut Of Memory!%s\n"
581 "Sorry, but Wireshark has to terminate now!\n"
583 "Some infos / workarounds can be found at:\n"
584 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
585 simple_dialog_primary_start(), simple_dialog_primary_end());
586 /* we have to terminate, as we cannot recover from the memory error */
587 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
589 main_window_update();
590 /* XXX - how to avoid a busy wait? */
598 /* Cleanup and release all dfilter resources */
600 dfilter_free(dfcode);
603 /* We're done reading the file; destroy the progress bar if it was created. */
605 destroy_progress_dlg(progbar);
607 /* We're done reading sequentially through the file. */
608 cf->state = FILE_READ_DONE;
610 /* Close the sequential I/O side, to free up memory it requires. */
611 wtap_sequential_close(cf->wth);
613 /* Allow the protocol dissectors to free up memory that they
614 * don't need after the sequential run-through of the packets. */
615 postseq_cleanup_all_protocols();
617 /* compute the time it took to load the file */
618 compute_elapsed(&start_time);
620 /* Set the file encapsulation type now; we don't know what it is until
621 we've looked at all the packets, as we don't know until then whether
622 there's more than one type (and thus whether it's
623 WTAP_ENCAP_PER_PACKET). */
624 cf->lnk_t = wtap_file_encap(cf->wth);
626 cf->current_frame = cf->first_displayed;
629 #ifdef NEW_PACKET_LIST
630 new_packet_list_thaw();
635 cf_callback_invoke(cf_cb_file_read_finished, cf);
637 /* If we have any displayed packets to select, select the first of those
638 packets by making the first row the selected row. */
639 if (cf->first_displayed != NULL){
640 #ifdef NEW_PACKET_LIST
641 new_packet_list_select_first_row();
643 packet_list_select_row(0);
644 #endif /* NEW_PACKET_LIST */
648 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
649 "%sFile loading was cancelled!%s\n"
651 "The remaining packets in the file were discarded.\n"
653 "As a lot of packets from the original file will be missing,\n"
654 "remember to be careful when saving the current content to a file.\n",
655 simple_dialog_primary_start(), simple_dialog_primary_end());
656 return CF_READ_ERROR;
660 /* Put up a message box noting that the read failed somewhere along
661 the line. Don't throw out the stuff we managed to read, though,
665 case WTAP_ERR_UNSUPPORTED_ENCAP:
666 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
667 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
670 errmsg = errmsg_errno;
673 case WTAP_ERR_CANT_READ:
674 errmsg = "An attempt to read from the capture file failed for"
675 " some unknown reason.";
678 case WTAP_ERR_SHORT_READ:
679 errmsg = "The capture file appears to have been cut short"
680 " in the middle of a packet.";
683 case WTAP_ERR_BAD_RECORD:
684 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
685 "The capture file appears to be damaged or corrupt.\n(%s)",
688 errmsg = errmsg_errno;
692 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
693 "An error occurred while reading the"
694 " capture file: %s.", wtap_strerror(err));
695 errmsg = errmsg_errno;
698 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
699 return CF_READ_ERROR;
706 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
708 cf_status_t cf_status;
710 cf_status = cf_open(cf, fname, is_tempfile, err);
715 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
717 gint64 data_offset = 0;
719 volatile int newly_displayed_packets = 0;
721 gboolean filtering_tap_listeners;
724 /* Compile the current display filter.
725 * We assume this will not fail since cf->dfilter is only set in
726 * cf_filter IFF the filter was valid.
730 dfilter_compile(cf->dfilter, &dfcode);
733 /* Do we have any tap listeners with filters? */
734 filtering_tap_listeners = have_filtering_tap_listeners();
736 /* Get the union of the flags for all tap listeners. */
737 tap_flags = union_of_tap_listener_flags();
741 #ifdef NEW_PACKET_LIST
742 new_packet_list_freeze();
744 packet_list_check_end();
745 packet_list_freeze();
748 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
750 while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
751 if (cf->state == FILE_READ_ABORTED) {
752 /* Well, the user decided to exit Wireshark. Break out of the
753 loop, and let the code below (which is called even if there
754 aren't any packets left to read) exit. */
758 if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
759 data_offset) != -1) {
760 newly_displayed_packets++;
763 CATCH(OutOfMemoryError) {
766 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
767 "%sOut Of Memory!%s\n"
769 "Sorry, but Wireshark has to terminate now!\n"
771 "The capture file is not lost, it can be found at:\n"
774 "Some infos / workarounds can be found at:\n"
775 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
776 simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
777 /* we have to terminate, as we cannot recover from the memory error */
778 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
780 main_window_update();
781 /* XXX - how to avoid a busy wait? */
784 #ifdef NEW_PACKET_LIST
785 new_packet_list_thaw();
789 return CF_READ_ABORTED;
795 /* Cleanup and release all dfilter resources */
797 dfilter_free(dfcode);
800 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
801 cf->count, cf->state, *err);*/
803 #ifdef NEW_PACKET_LIST
804 new_packet_list_thaw();
806 /* XXX - this causes "flickering" of the list */
810 #ifndef NEW_PACKET_LIST
811 /* moving to the end of the packet list - if the user requested so and
812 we have some new packets.
813 this doesn't seem to work well with a frozen GTK_Clist, so do this after
814 packet_list_thaw() is done, see bugzilla 1188 */
815 /* XXX - this cheats and looks inside the packet list to find the final
817 if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL)
818 packet_list_moveto_end();
819 #endif /* NEW_PACKET_LIST */
821 if (cf->state == FILE_READ_ABORTED) {
822 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
823 so that our caller can kill off the capture child process;
824 this will cause an EOF on the pipe from the child, so
825 "cf_finish_tail()" will be called, and it will clean up
827 return CF_READ_ABORTED;
828 } else if (*err != 0) {
829 /* We got an error reading the capture file.
830 XXX - pop up a dialog box instead? */
831 g_warning("Error \"%s\" while reading: \"%s\"\n",
832 wtap_strerror(*err), cf->filename);
834 return CF_READ_ERROR;
840 cf_finish_tail(capture_file *cf, int *err)
845 gboolean filtering_tap_listeners;
848 /* Compile the current display filter.
849 * We assume this will not fail since cf->dfilter is only set in
850 * cf_filter IFF the filter was valid.
854 dfilter_compile(cf->dfilter, &dfcode);
857 /* Do we have any tap listeners with filters? */
858 filtering_tap_listeners = have_filtering_tap_listeners();
860 /* Get the union of the flags for all tap listeners. */
861 tap_flags = union_of_tap_listener_flags();
863 if(cf->wth == NULL) {
865 return CF_READ_ERROR;
868 #ifdef NEW_PACKET_LIST
869 new_packet_list_freeze();
871 packet_list_check_end();
872 packet_list_freeze();
875 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
876 if (cf->state == FILE_READ_ABORTED) {
877 /* Well, the user decided to abort the read. Break out of the
878 loop, and let the code below (which is called even if there
879 aren't any packets left to read) exit. */
882 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
885 /* Cleanup and release all dfilter resources */
887 dfilter_free(dfcode);
890 #ifdef NEW_PACKET_LIST
891 new_packet_list_thaw();
896 if (cf->state == FILE_READ_ABORTED) {
897 /* Well, the user decided to abort the read. We're only called
898 when the child capture process closes the pipe to us (meaning
899 it's probably exited), so we can just close the capture
900 file; we return CF_READ_ABORTED so our caller can do whatever
901 is appropriate when that happens. */
903 return CF_READ_ABORTED;
906 #ifndef NEW_PACKET_LIST
907 if (auto_scroll_live && cf->plist_end != NULL)
908 /* XXX - this cheats and looks inside the packet list to find the final
910 packet_list_moveto_end();
913 /* We're done reading sequentially through the file. */
914 cf->state = FILE_READ_DONE;
916 /* We're done reading sequentially through the file; close the
917 sequential I/O side, to free up memory it requires. */
918 wtap_sequential_close(cf->wth);
920 /* Allow the protocol dissectors to free up memory that they
921 * don't need after the sequential run-through of the packets. */
922 postseq_cleanup_all_protocols();
924 /* Set the file encapsulation type now; we don't know what it is until
925 we've looked at all the packets, as we don't know until then whether
926 there's more than one type (and thus whether it's
927 WTAP_ENCAP_PER_PACKET). */
928 cf->lnk_t = wtap_file_encap(cf->wth);
931 /* We got an error reading the capture file.
932 XXX - pop up a dialog box? */
933 return CF_READ_ERROR;
938 #endif /* HAVE_LIBPCAP */
941 cf_get_display_name(capture_file *cf)
943 const gchar *displayname;
945 /* Return a name to use in displays */
946 if (!cf->is_tempfile) {
947 /* Get the last component of the file name, and use that. */
949 displayname = get_basename(cf->filename);
951 displayname="(No file)";
954 /* The file we read is a temporary file from a live capture;
955 we don't mention its name. */
956 displayname = "(Untitled)";
961 /* XXX - use a macro instead? */
963 cf_get_packet_count(capture_file *cf)
968 /* XXX - use a macro instead? */
970 cf_set_packet_count(capture_file *cf, int packet_count)
972 cf->count = packet_count;
975 /* XXX - use a macro instead? */
977 cf_is_tempfile(capture_file *cf)
979 return cf->is_tempfile;
982 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
984 cf->is_tempfile = is_tempfile;
988 /* XXX - use a macro instead? */
989 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
991 cf->drops_known = drops_known;
994 /* XXX - use a macro instead? */
995 void cf_set_drops(capture_file *cf, guint32 drops)
1000 /* XXX - use a macro instead? */
1001 gboolean cf_get_drops_known(capture_file *cf)
1003 return cf->drops_known;
1006 /* XXX - use a macro instead? */
1007 guint32 cf_get_drops(capture_file *cf)
1012 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1014 cf->rfcode = rfcode;
1018 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1019 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1021 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1023 #ifdef NEW_PACKET_LIST
1024 gboolean add_to_packet_list)
1026 gboolean add_to_packet_list _U_)
1029 gboolean create_proto_tree = FALSE;
1034 #ifdef NEW_PACKET_LIST
1035 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1040 /* just add some value here until we know if it is being displayed or not */
1041 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1043 /* If we don't have the time stamp of the first packet in the
1044 capture, it's because this is the first packet. Save the time
1045 stamp of this packet as the time stamp of the first packet. */
1046 if (nstime_is_unset(&first_ts)) {
1047 first_ts = fdata->abs_ts;
1049 /* if this frames is marked as a reference time frame, reset
1050 firstsec and firstusec to this frame */
1051 if(fdata->flags.ref_time){
1052 first_ts = fdata->abs_ts;
1055 /* If we don't have the time stamp of the previous displayed packet,
1056 it's because this is the first displayed packet. Save the time
1057 stamp of this packet as the time stamp of the previous displayed
1059 if (nstime_is_unset(&prev_dis_ts)) {
1060 prev_dis_ts = fdata->abs_ts;
1063 /* Get the time elapsed between the first packet and this packet. */
1064 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
1066 /* If it's greater than the current elapsed time, set the elapsed time
1067 to it (we check for "greater than" so as not to be confused by
1068 time moving backwards). */
1069 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
1070 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
1071 cf->elapsed_time = fdata->rel_ts;
1074 /* Get the time elapsed between the previous displayed packet and
1076 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
1080 we have a display filter and are re-applying it;
1082 we have a list of color filters;
1084 we have tap listeners with filters;
1086 we have tap listeners that require a protocol tree;
1088 we have custom columns;
1090 allocate a protocol tree root node, so that we'll construct
1091 a protocol tree against which a filter expression can be
1093 if ((dfcode != NULL && refilter) ||
1094 #ifndef NEW_PACKET_LIST
1095 color_filters_used() ||
1096 have_custom_cols(cinfo) ||
1098 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1099 create_proto_tree = TRUE;
1101 /* Dissect the frame. */
1102 epan_dissect_init(&edt, create_proto_tree, FALSE);
1104 if (dfcode != NULL && refilter) {
1105 epan_dissect_prime_dfilter(&edt, dfcode);
1108 /* prepare color filters */
1109 #ifndef NEW_PACKET_LIST
1110 color_filters_prime_edt(&edt);
1111 col_custom_prime_edt(&edt, cinfo);
1114 tap_queue_init(&edt);
1115 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1116 tap_push_tapped_queue(&edt);
1118 /* If we have a display filter, apply it if we're refiltering, otherwise
1119 leave the "passed_dfilter" flag alone.
1121 If we don't have a display filter, set "passed_dfilter" to 1. */
1122 if (dfcode != NULL) {
1124 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1127 fdata->flags.passed_dfilter = 1;
1129 #ifdef NEW_PACKET_LIST
1130 if (add_to_packet_list) {
1131 /* We fill the needed columns from new_packet_list */
1132 row = new_packet_list_append(cinfo, fdata, &edt.pi);
1136 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) )
1138 /* This frame either passed the display filter list or is marked as
1139 a time reference frame. All time reference frames are displayed
1140 even if they dont pass the display filter */
1141 if(fdata->flags.ref_time){
1142 /* if this was a TIME REF frame we should reset the cul bytes field */
1143 cum_bytes = fdata->pkt_len;
1144 fdata->cum_bytes = cum_bytes;
1146 /* increase cum_bytes with this packets length */
1147 cum_bytes += fdata->pkt_len;
1150 #ifndef NEW_PACKET_LIST
1151 epan_dissect_fill_in_columns(&edt, TRUE);
1154 /* If we haven't yet seen the first frame, this is it.
1156 XXX - we must do this before we add the row to the display,
1157 as, if the display's GtkCList's selection mode is
1158 GTK_SELECTION_BROWSE, when the first entry is added to it,
1159 "cf_select_packet()" will be called, and it will fetch the row
1160 data for the 0th row, and will get a null pointer rather than
1161 "fdata", as "gtk_clist_append()" won't yet have returned and
1162 thus "gtk_clist_set_row_data()" won't yet have been called.
1164 We thus need to leave behind bread crumbs so that
1165 "cf_select_packet()" can find this frame. See the comment
1166 in "cf_select_packet()". */
1167 if (cf->first_displayed == NULL)
1168 cf->first_displayed = fdata;
1170 /* This is the last frame we've seen so far. */
1171 cf->last_displayed = fdata;
1173 #ifndef NEW_PACKET_LIST
1174 row = packet_list_append(cinfo->col_data, fdata);
1176 /* colorize packet: first apply color filters
1177 * then if packet is marked, use preferences to overwrite color
1178 * we do both to make sure that when a packet gets un-marked, the
1179 * color will be correctly set (fixes bug 2038)
1181 fdata->color_filter = color_filters_colorize_packet(row, &edt);
1182 if (fdata->flags.marked) {
1183 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
1185 #endif /* NEW_PACKET_LIST */
1187 /* Set the time of the previous displayed frame to the time of this
1189 prev_dis_ts = fdata->abs_ts;
1191 cf->displayed_count++;
1194 epan_dissect_cleanup(&edt);
1198 /* read in a new packet */
1199 /* returns the row of the new packet in the packet list or -1 if not displayed */
1201 read_packet(capture_file *cf, dfilter_t *dfcode,
1202 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1204 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1205 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1206 const guchar *buf = wtap_buf_ptr(cf->wth);
1209 frame_data *plist_end;
1212 /* Allocate the next list entry, and add it to the list.
1213 * memory chunks have been deprecated in favor of the slice allocator,
1214 * which has been added in 2.10
1216 #if GLIB_CHECK_VERSION(2,10,0)
1217 fdata = g_slice_new(frame_data);
1219 fdata = g_mem_chunk_alloc(cf->plist_chunk);
1225 fdata->pkt_len = phdr->len;
1226 fdata->cap_len = phdr->caplen;
1227 fdata->file_off = offset;
1228 fdata->lnk_t = phdr->pkt_encap;
1229 fdata->flags.encoding = CHAR_ASCII;
1230 fdata->flags.visited = 0;
1231 fdata->flags.marked = 0;
1232 fdata->flags.ref_time = 0;
1233 fdata->color_filter = NULL;
1234 fdata->col_text = NULL;
1236 fdata->abs_ts.secs = phdr->ts.secs;
1237 fdata->abs_ts.nsecs = phdr->ts.nsecs;
1239 if (cf->plist_end != NULL)
1240 nstime_delta(&fdata->del_cap_ts, &fdata->abs_ts, &cf->plist_end->abs_ts);
1242 nstime_set_zero(&fdata->del_cap_ts);
1247 epan_dissect_init(&edt, TRUE, FALSE);
1248 epan_dissect_prime_dfilter(&edt, cf->rfcode);
1249 epan_dissect_run(&edt, pseudo_header, buf, fdata, NULL);
1250 passed = dfilter_apply_edt(cf->rfcode, &edt);
1251 epan_dissect_cleanup(&edt);
1254 plist_end = cf->plist_end;
1255 fdata->prev = plist_end;
1256 if (plist_end != NULL)
1257 plist_end->next = fdata;
1260 cf->plist_end = fdata;
1263 cf->f_datalen = offset + phdr->caplen;
1264 fdata->num = cf->count;
1265 if (!cf->redissecting) {
1266 row = add_packet_to_packet_list(fdata, cf, dfcode,
1267 filtering_tap_listeners, tap_flags,
1268 pseudo_header, buf, TRUE, TRUE);
1271 /* XXX - if we didn't have read filters, or if we could avoid
1272 allocating the "frame_data" structure until we knew whether
1273 the frame passed the read filter, we could use a G_ALLOC_ONLY
1276 ...but, at least in one test I did, where I just made the chunk
1277 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
1278 seem to save a noticeable amount of time or space. */
1279 #if GLIB_CHECK_VERSION(2,10,0)
1280 /* memory chunks have been deprecated in favor of the slice allocator,
1281 * which has been added in 2.10
1283 g_slice_free(frame_data,fdata);
1285 g_mem_chunk_free(cf->plist_chunk, fdata);
1293 cf_merge_files(char **out_filenamep, int in_file_count,
1294 char *const *in_filenames, int file_type, gboolean do_append)
1296 merge_in_file_t *in_files;
1302 int open_err, read_err, write_err, close_err;
1306 char errmsg_errno[1024+1];
1308 gboolean got_read_error = FALSE, got_write_error = FALSE;
1310 progdlg_t *progbar = NULL;
1312 gint64 f_len, file_pos;
1314 GTimeVal start_time;
1315 gchar status_str[100];
1316 gint64 progbar_nextstep;
1317 gint64 progbar_quantum;
1319 /* open the input files */
1320 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1321 &open_err, &err_info, &err_fileno)) {
1323 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1328 if (*out_filenamep != NULL) {
1329 out_filename = *out_filenamep;
1330 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1334 out_fd = create_tempfile(&tmpname, "wireshark");
1337 out_filename = g_strdup(tmpname);
1338 *out_filenamep = out_filename;
1342 merge_close_in_files(in_file_count, in_files);
1344 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1348 pdh = wtap_dump_fdopen(out_fd, file_type,
1349 merge_select_frame_type(in_file_count, in_files),
1350 merge_max_snapshot_length(in_file_count, in_files),
1351 FALSE /* compressed */, &open_err);
1354 merge_close_in_files(in_file_count, in_files);
1356 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1361 /* Get the sum of the sizes of all the files. */
1363 for (i = 0; i < in_file_count; i++)
1364 f_len += in_files[i].size;
1366 /* Update the progress bar when it gets to this value. */
1367 progbar_nextstep = 0;
1368 /* When we reach the value that triggers a progress bar update,
1369 bump that value by this amount. */
1370 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1371 /* Progress so far. */
1375 g_get_current_time(&start_time);
1377 /* do the merge (or append) */
1380 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1383 wth = merge_read_packet(in_file_count, in_files, &read_err,
1387 got_read_error = TRUE;
1391 /* Get the sum of the data offsets in all of the files. */
1393 for (i = 0; i < in_file_count; i++)
1394 data_offset += in_files[i].data_offset;
1396 /* Create the progress bar if necessary.
1397 We check on every iteration of the loop, so that it takes no
1398 longer than the standard time to create it (otherwise, for a
1399 large file, we might take considerably longer than that standard
1400 time in order to get to the next progress bar step). */
1401 if (progbar == NULL) {
1402 progbar = delayed_create_progress_dlg("Merging", "files",
1403 FALSE, &stop_flag, &start_time, progbar_val);
1406 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1407 when we update it, we have to run the GTK+ main loop to get it
1408 to repaint what's pending, and doing so may involve an "ioctl()"
1409 to see if there's any pending input from an X server, and doing
1410 that for every packet can be costly, especially on a big file. */
1411 if (data_offset >= progbar_nextstep) {
1412 /* Get the sum of the seek positions in all of the files. */
1414 for (i = 0; i < in_file_count; i++)
1415 file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1416 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1417 if (progbar_val > 1.0f) {
1418 /* Some file probably grew while we were reading it.
1419 That "shouldn't happen", so we'll just clip the progress
1423 if (progbar != NULL) {
1424 g_snprintf(status_str, sizeof(status_str),
1425 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1426 file_pos / 1024, f_len / 1024);
1427 update_progress_dlg(progbar, progbar_val, status_str);
1429 progbar_nextstep += progbar_quantum;
1433 /* Well, the user decided to abort the merge. */
1437 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1438 wtap_buf_ptr(wth), &write_err)) {
1439 got_write_error = TRUE;
1444 /* We're done merging the files; destroy the progress bar if it was created. */
1445 if (progbar != NULL)
1446 destroy_progress_dlg(progbar);
1448 merge_close_in_files(in_file_count, in_files);
1449 if (!got_read_error && !got_write_error) {
1450 if (!wtap_dump_close(pdh, &write_err))
1451 got_write_error = TRUE;
1453 wtap_dump_close(pdh, &close_err);
1455 if (got_read_error) {
1457 * Find the file on which we got the error, and report the error.
1459 for (i = 0; i < in_file_count; i++) {
1460 if (in_files[i].state == GOT_ERROR) {
1461 /* Put up a message box noting that a read failed somewhere along
1465 case WTAP_ERR_UNSUPPORTED_ENCAP:
1466 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1467 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1470 errmsg = errmsg_errno;
1473 case WTAP_ERR_CANT_READ:
1474 errmsg = "An attempt to read from the capture file %s failed for"
1475 " some unknown reason.";
1478 case WTAP_ERR_SHORT_READ:
1479 errmsg = "The capture file %s appears to have been cut short"
1480 " in the middle of a packet.";
1483 case WTAP_ERR_BAD_RECORD:
1484 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1485 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1488 errmsg = errmsg_errno;
1492 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1493 "An error occurred while reading the"
1494 " capture file %%s: %s.", wtap_strerror(read_err));
1495 errmsg = errmsg_errno;
1498 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
1503 if (got_write_error) {
1504 /* Put up an alert box for the write error. */
1505 cf_write_failure_alert_box(out_filename, write_err);
1508 if (got_read_error || got_write_error || stop_flag) {
1509 /* Callers aren't expected to treat an error or an explicit abort
1510 differently - we put up error dialogs ourselves, so they don't
1518 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1520 const char *filter_new = dftext ? dftext : "";
1521 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1524 /* if new filter equals old one, do nothing unless told to do so */
1525 if (!force && strcmp(filter_new, filter_old) == 0) {
1531 if (dftext == NULL) {
1532 /* The new filter is an empty filter (i.e., display all packets).
1533 * so leave dfcode==NULL
1537 * We have a filter; make a copy of it (as we'll be saving it),
1538 * and try to compile it.
1540 dftext = g_strdup(dftext);
1541 if (!dfilter_compile(dftext, &dfcode)) {
1542 /* The attempt failed; report an error. */
1543 gchar *safe_dftext = simple_dialog_format_message(dftext);
1544 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1546 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1549 "The following display filter isn't a valid display filter:\n%s\n"
1550 "See the help for a description of the display filter syntax.",
1551 simple_dialog_primary_start(), safe_dfilter_error_msg,
1552 simple_dialog_primary_end(), safe_dftext);
1553 g_free(safe_dfilter_error_msg);
1554 g_free(safe_dftext);
1560 if (dfcode == NULL) {
1561 /* Yes - free the filter text, and set it to null. */
1567 /* We have a valid filter. Replace the current filter. */
1568 g_free(cf->dfilter);
1569 cf->dfilter = dftext;
1571 /* Now rescan the packet list, applying the new filter, but not
1572 throwing away information constructed on a previous pass. */
1573 if (dftext == NULL) {
1574 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1576 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1579 /* Cleanup and release all dfilter resources */
1580 if (dfcode != NULL){
1581 dfilter_free(dfcode);
1587 cf_colorize_packets(capture_file *cf)
1589 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1593 cf_reftime_packets(capture_file *cf)
1596 #ifdef NEW_PACKET_LIST
1597 ref_time_packets(cf);
1599 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1604 cf_redissect_packets(capture_file *cf)
1606 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1609 /* Rescan the list of packets, reconstructing the CList.
1611 "action" describes why we're doing this; it's used in the progress
1614 "action_item" describes what we're doing; it's used in the progress
1617 "refilter" is TRUE if we need to re-evaluate the filter expression.
1619 "redissect" is TRUE if we need to make the dissectors reconstruct
1620 any state information they have (because a preference that affects
1621 some dissector has changed, meaning some dissector might construct
1622 its state differently from the way it was constructed the last time). */
1624 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1625 gboolean refilter, gboolean redissect)
1628 progdlg_t *progbar = NULL;
1633 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1634 int selected_row, prev_row, preceding_row, following_row;
1635 gboolean selected_frame_seen;
1638 GTimeVal start_time;
1639 gchar status_str[100];
1640 int progbar_nextstep;
1641 int progbar_quantum;
1643 gboolean filtering_tap_listeners;
1645 #ifdef NEW_PACKET_LIST
1646 gboolean add_to_packet_list = FALSE;
1648 gboolean add_to_packet_list = TRUE;
1651 /* Compile the current display filter.
1652 * We assume this will not fail since cf->dfilter is only set in
1653 * cf_filter IFF the filter was valid.
1657 dfilter_compile(cf->dfilter, &dfcode);
1660 /* Do we have any tap listeners with filters? */
1661 filtering_tap_listeners = have_filtering_tap_listeners();
1663 /* Get the union of the flags for all tap listeners. */
1664 tap_flags = union_of_tap_listener_flags();
1667 reset_tap_listeners();
1668 /* Which frame, if any, is the currently selected frame?
1669 XXX - should the selected frame or the focus frame be the "current"
1670 frame, that frame being the one from which "Find Frame" searches
1672 selected_frame = cf->current_frame;
1674 /* We don't yet know what row that frame will be on, if any, after we
1675 rebuild the clist, however. */
1678 /* Freeze the packet list while we redo it, so we don't get any
1679 screen updates while it happens. */
1680 #ifdef NEW_PACKET_LIST
1681 new_packet_list_freeze();
1683 packet_list_freeze();
1686 packet_list_clear();
1690 /* We need to re-initialize all the state information that protocols
1691 keep, because some preference that controls a dissector has changed,
1692 which might cause the state information to be constructed differently
1693 by that dissector. */
1695 /* We might receive new packets while redissecting, and we don't
1696 want to dissect those before their time. */
1697 cf->redissecting = TRUE;
1699 /* Initialize all data structures used for dissection. */
1702 #ifdef NEW_PACKET_LIST
1703 /* We need to redissect the packets so we have to discard our old
1704 * packet list store. */
1705 new_packet_list_clear();
1706 add_to_packet_list = TRUE;
1710 /* We don't yet know which will be the first and last frames displayed. */
1711 cf->first_displayed = NULL;
1712 cf->last_displayed = NULL;
1714 /* We currently don't display any packets */
1715 cf->displayed_count = 0;
1717 /* Iterate through the list of frames. Call a routine for each frame
1718 to check whether it should be displayed and, if so, add it to
1719 the display list. */
1720 nstime_set_unset(&first_ts);
1721 nstime_set_unset(&prev_dis_ts);
1723 /* Update the progress bar when it gets to this value. */
1724 progbar_nextstep = 0;
1725 /* When we reach the value that triggers a progress bar update,
1726 bump that value by this amount. */
1727 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1728 /* Count of packets at which we've looked. */
1730 /* Progress so far. */
1734 g_get_current_time(&start_time);
1736 row = -1; /* no previous row yet */
1741 preceding_frame = NULL;
1743 following_frame = NULL;
1745 selected_frame_seen = FALSE;
1747 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1748 /* Create the progress bar if necessary.
1749 We check on every iteration of the loop, so that it takes no
1750 longer than the standard time to create it (otherwise, for a
1751 large file, we might take considerably longer than that standard
1752 time in order to get to the next progress bar step). */
1753 if (progbar == NULL)
1754 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1755 &stop_flag, &start_time,
1758 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1759 when we update it, we have to run the GTK+ main loop to get it
1760 to repaint what's pending, and doing so may involve an "ioctl()"
1761 to see if there's any pending input from an X server, and doing
1762 that for every packet can be costly, especially on a big file. */
1763 if (count >= progbar_nextstep) {
1764 /* let's not divide by zero. I should never be started
1765 * with count == 0, so let's assert that
1767 g_assert(cf->count > 0);
1768 progbar_val = (gfloat) count / cf->count;
1770 if (progbar != NULL) {
1771 g_snprintf(status_str, sizeof(status_str),
1772 "%4u of %u frames", count, cf->count);
1773 update_progress_dlg(progbar, progbar_val, status_str);
1776 progbar_nextstep += progbar_quantum;
1780 /* Well, the user decided to abort the filtering. Just stop.
1782 XXX - go back to the previous filter? Users probably just
1783 want not to wait for a filtering operation to finish;
1784 unless we cancel by having no filter, reverting to the
1785 previous filter will probably be even more expensive than
1786 continuing the filtering, as it involves going back to the
1787 beginning and filtering, and even with no filter we currently
1788 have to re-generate the entire clist, which is also expensive.
1790 I'm not sure what Network Monitor does, but it doesn't appear
1791 to give you an unfiltered display if you cancel. */
1798 /* Since all state for the frame was destroyed, mark the frame
1799 * as not visited, free the GSList referring to the state
1800 * data (the per-frame data itself was freed by
1801 * "init_dissection()"), and null out the GSList pointer. */
1802 fdata->flags.visited = 0;
1804 g_slist_free(fdata->pfd);
1809 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1810 cf->pd, fdata->cap_len, &err, &err_info)) {
1811 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1812 cf_read_error_message(err, err_info), cf->filename);
1816 /* If the previous frame is displayed, and we haven't yet seen the
1817 selected frame, remember that frame - it's the closest one we've
1818 yet seen before the selected frame. */
1819 if (prev_row != -1 && !selected_frame_seen) {
1820 preceding_row = prev_row;
1821 preceding_frame = prev_frame;
1823 row = add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1824 tap_flags, &cf->pseudo_header, cf->pd,
1826 add_to_packet_list);
1828 /* If this frame is displayed, and this is the first frame we've
1829 seen displayed after the selected frame, remember this frame -
1830 it's the closest one we've yet seen at or after the selected
1832 if (row != -1 && selected_frame_seen && following_row == -1) {
1833 following_row = row;
1834 following_frame = fdata;
1836 if (fdata == selected_frame) {
1838 selected_frame_seen = TRUE;
1841 /* Remember this row/frame - it'll be the previous row/frame
1842 on the next pass through the loop. */
1847 /* We are done redissecting the packet list. */
1848 cf->redissecting = FALSE;
1850 #ifndef NEW_PACKET_LIST
1851 /* Re-sort the list using the previously selected order */
1852 packet_list_set_sort_column();
1856 /* Clear out what remains of the visited flags and per-frame data
1859 XXX - that may cause various forms of bogosity when dissecting
1860 these frames, as they won't have been seen by this sequential
1861 pass, but the only alternative I see is to keep scanning them
1862 even though the user requested that the scan stop, and that
1863 would leave the user stuck with an Wireshark grinding on
1864 until it finishes. Should we just stick them with that? */
1865 for (; fdata != NULL; fdata = fdata->next) {
1866 fdata->flags.visited = 0;
1868 g_slist_free(fdata->pfd);
1874 /* We're done filtering the packets; destroy the progress bar if it
1876 if (progbar != NULL)
1877 destroy_progress_dlg(progbar);
1879 /* Unfreeze the packet list. */
1880 #ifdef NEW_PACKET_LIST
1881 new_packet_list_thaw();
1886 if (selected_row == -1) {
1887 /* The selected frame didn't pass the filter. */
1888 if (selected_frame == NULL) {
1889 /* That's because there *was* no selected frame. Make the first
1890 displayed frame the current frame. */
1893 /* Find the nearest displayed frame to the selected frame (whether
1894 it's before or after that frame) and make that the current frame.
1895 If the next and previous displayed frames are equidistant from the
1896 selected frame, choose the next one. */
1897 g_assert(following_frame == NULL ||
1898 following_frame->num >= selected_frame->num);
1899 g_assert(preceding_frame == NULL ||
1900 preceding_frame->num <= selected_frame->num);
1901 if (following_frame == NULL) {
1902 /* No frame after the selected frame passed the filter, so we
1903 have to select the last displayed frame before the selected
1905 selected_row = preceding_row;
1906 } else if (preceding_frame == NULL) {
1907 /* No frame before the selected frame passed the filter, so we
1908 have to select the first displayed frame after the selected
1910 selected_row = following_row;
1912 /* Frames before and after the selected frame passed the filter, so
1913 we'll select the previous frame */
1914 selected_row = preceding_row;
1919 if (selected_row == -1) {
1920 /* There are no frames displayed at all. */
1921 cf_unselect_packet(cf);
1923 #ifndef NEW_PACKET_LIST
1924 /* Either the frame that was selected passed the filter, or we've
1925 found the nearest displayed frame to that frame. Select it, make
1926 it the focus row, and make it visible. */
1927 if (selected_row == 0) {
1928 /* Set to invalid to force update of packet list and packet details */
1929 cf->current_row = -1;
1931 packet_list_set_selected_row(selected_row);
1932 #endif /* NEW_PACKET_LIST */
1935 /* Cleanup and release all dfilter resources */
1936 if (dfcode != NULL){
1937 dfilter_free(dfcode);
1941 * Scan trough all frame data and recalculate the ref time
1942 * without rereading the file.
1943 * XXX - do we need a progres bar or is this fast enough?
1945 #ifdef NEW_PACKET_LIST
1947 ref_time_packets(capture_file *cf)
1953 nstime_set_unset(&first_ts);
1954 nstime_set_unset(&prev_dis_ts);
1957 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1959 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1960 /* just add some value here until we know if it is being displayed or not */
1961 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1963 /* If we don't have the time stamp of the first packet in the
1964 capture, it's because this is the first packet. Save the time
1965 stamp of this packet as the time stamp of the first packet. */
1966 if (nstime_is_unset(&first_ts)) {
1967 first_ts = fdata->abs_ts;
1969 /* if this frames is marked as a reference time frame, reset
1970 firstsec and firstusec to this frame */
1971 if(fdata->flags.ref_time){
1972 first_ts = fdata->abs_ts;
1975 /* If we don't have the time stamp of the previous displayed packet,
1976 it's because this is the first displayed packet. Save the time
1977 stamp of this packet as the time stamp of the previous displayed
1979 if (nstime_is_unset(&prev_dis_ts)) {
1980 prev_dis_ts = fdata->abs_ts;
1983 /* Get the time elapsed between the first packet and this packet. */
1984 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
1986 /* If it's greater than the current elapsed time, set the elapsed time
1987 to it (we check for "greater than" so as not to be confused by
1988 time moving backwards). */
1989 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
1990 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
1991 cf->elapsed_time = fdata->rel_ts;
1994 /* Get the time elapsed between the previous displayed packet and
1996 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
1998 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
1999 /* This frame either passed the display filter list or is marked as
2000 a time reference frame. All time reference frames are displayed
2001 even if they dont pass the display filter */
2002 if(fdata->flags.ref_time){
2003 /* if this was a TIME REF frame we should reset the cul bytes field */
2004 cum_bytes = fdata->pkt_len;
2005 fdata->cum_bytes = cum_bytes;
2007 /* increase cum_bytes with this packets length */
2008 cum_bytes += fdata->pkt_len;
2021 process_specified_packets(capture_file *cf, packet_range_t *range,
2022 const char *string1, const char *string2, gboolean terminate_is_stop,
2023 gboolean (*callback)(capture_file *, frame_data *,
2024 union wtap_pseudo_header *, const guint8 *, void *),
2025 void *callback_args)
2030 union wtap_pseudo_header pseudo_header;
2031 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
2032 psp_return_t ret = PSP_FINISHED;
2034 progdlg_t *progbar = NULL;
2037 gboolean progbar_stop_flag;
2038 GTimeVal progbar_start_time;
2039 gchar progbar_status_str[100];
2040 int progbar_nextstep;
2041 int progbar_quantum;
2042 range_process_e process_this;
2044 /* Update the progress bar when it gets to this value. */
2045 progbar_nextstep = 0;
2046 /* When we reach the value that triggers a progress bar update,
2047 bump that value by this amount. */
2048 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2049 /* Count of packets at which we've looked. */
2051 /* Progress so far. */
2054 progbar_stop_flag = FALSE;
2055 g_get_current_time(&progbar_start_time);
2057 packet_range_process_init(range);
2059 /* Iterate through the list of packets, printing the packets that
2060 were selected by the current display filter. */
2061 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2062 /* Create the progress bar if necessary.
2063 We check on every iteration of the loop, so that it takes no
2064 longer than the standard time to create it (otherwise, for a
2065 large file, we might take considerably longer than that standard
2066 time in order to get to the next progress bar step). */
2067 if (progbar == NULL)
2068 progbar = delayed_create_progress_dlg(string1, string2,
2071 &progbar_start_time,
2074 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2075 when we update it, we have to run the GTK+ main loop to get it
2076 to repaint what's pending, and doing so may involve an "ioctl()"
2077 to see if there's any pending input from an X server, and doing
2078 that for every packet can be costly, especially on a big file. */
2079 if (progbar_count >= progbar_nextstep) {
2080 /* let's not divide by zero. I should never be started
2081 * with count == 0, so let's assert that
2083 g_assert(cf->count > 0);
2084 progbar_val = (gfloat) progbar_count / cf->count;
2086 if (progbar != NULL) {
2087 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2088 "%4u of %u packets", progbar_count, cf->count);
2089 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2092 progbar_nextstep += progbar_quantum;
2095 if (progbar_stop_flag) {
2096 /* Well, the user decided to abort the operation. Just stop,
2097 and arrange to return PSP_STOPPED to our caller, so they know
2098 it was stopped explicitly. */
2105 /* do we have to process this packet? */
2106 process_this = packet_range_process_packet(range, fdata);
2107 if (process_this == range_process_next) {
2108 /* this packet uninteresting, continue with next one */
2110 } else if (process_this == range_processing_finished) {
2111 /* all interesting packets processed, stop the loop */
2115 /* Get the packet */
2116 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
2117 pd, fdata->cap_len, &err, &err_info)) {
2118 /* Attempt to get the packet failed. */
2119 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2120 cf_read_error_message(err, err_info), cf->filename);
2124 /* Process the packet */
2125 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
2126 /* Callback failed. We assume it reported the error appropriately. */
2132 /* We're done printing the packets; destroy the progress bar if
2134 if (progbar != NULL)
2135 destroy_progress_dlg(progbar);
2141 gboolean construct_protocol_tree;
2143 } retap_callback_args_t;
2146 retap_packet(capture_file *cf _U_, frame_data *fdata,
2147 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2150 retap_callback_args_t *args = argsp;
2153 epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
2154 tap_queue_init(&edt);
2155 epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
2156 tap_push_tapped_queue(&edt);
2157 epan_dissect_cleanup(&edt);
2163 cf_retap_packets(capture_file *cf)
2165 packet_range_t range;
2166 retap_callback_args_t callback_args;
2167 gboolean filtering_tap_listeners;
2170 /* Do we have any tap listeners with filters? */
2171 filtering_tap_listeners = have_filtering_tap_listeners();
2173 tap_flags = union_of_tap_listener_flags();
2175 /* If any tap listeners have filters, or require the protocol tree,
2176 construct the protocol tree. */
2177 callback_args.construct_protocol_tree = filtering_tap_listeners ||
2178 (tap_flags & TL_REQUIRES_PROTO_TREE);
2180 /* If any tap listeners require the columns, construct them. */
2181 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2183 /* Reset the tap listeners. */
2184 reset_tap_listeners();
2186 /* Iterate through the list of packets, dissecting all packets and
2187 re-running the taps. */
2188 packet_range_init(&range);
2189 packet_range_process_init(&range);
2190 switch (process_specified_packets(cf, &range, "Recalculating statistics on",
2191 "all packets", TRUE, retap_packet,
2194 /* Completed successfully. */
2198 /* Well, the user decided to abort the refiltering.
2199 Return CF_READ_ABORTED so our caller knows they did that. */
2200 return CF_READ_ABORTED;
2203 /* Error while retapping. */
2204 return CF_READ_ERROR;
2207 g_assert_not_reached();
2212 print_args_t *print_args;
2213 gboolean print_header_line;
2214 char *header_line_buf;
2215 int header_line_buf_len;
2216 gboolean print_formfeed;
2217 gboolean print_separator;
2221 } print_callback_args_t;
2224 print_packet(capture_file *cf, frame_data *fdata,
2225 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2228 print_callback_args_t *args = argsp;
2235 gboolean proto_tree_needed;
2236 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2237 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2239 /* Create the protocol tree, and make it visible, if we're printing
2240 the dissection or the hex data.
2241 XXX - do we need it if we're just printing the hex data? */
2243 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2244 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2246 /* Fill in the column information if we're printing the summary
2248 if (args->print_args->print_summary) {
2249 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2250 epan_dissect_fill_in_columns(&edt, TRUE);
2252 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2254 if (args->print_formfeed) {
2255 if (!new_page(args->print_args->stream))
2258 if (args->print_separator) {
2259 if (!print_line(args->print_args->stream, 0, ""))
2265 * We generate bookmarks, if the output format supports them.
2266 * The name is "__frameN__".
2268 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2270 if (args->print_args->print_summary) {
2271 if (args->print_header_line) {
2272 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2274 args->print_header_line = FALSE; /* we might not need to print any more */
2276 cp = &args->line_buf[0];
2278 for (i = 0; i < cf->cinfo.num_cols; i++) {
2279 /* Find the length of the string for this column. */
2280 column_len = (int) strlen(cf->cinfo.col_data[i]);
2281 if (args->col_widths[i] > column_len)
2282 column_len = args->col_widths[i];
2284 /* Make sure there's room in the line buffer for the column; if not,
2285 double its length. */
2286 line_len += column_len + 1; /* "+1" for space */
2287 if (line_len > args->line_buf_len) {
2288 cp_off = (int) (cp - args->line_buf);
2289 args->line_buf_len = 2 * line_len;
2290 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2291 cp = args->line_buf + cp_off;
2294 /* Right-justify the packet number column. */
2295 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2296 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
2298 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
2300 if (i != cf->cinfo.num_cols - 1)
2306 * Generate a bookmark, using the summary line as the title.
2308 if (!print_bookmark(args->print_args->stream, bookmark_name,
2312 if (!print_line(args->print_args->stream, 0, args->line_buf))
2316 * Generate a bookmark, using "Frame N" as the title, as we're not
2317 * printing the summary line.
2319 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2320 if (!print_bookmark(args->print_args->stream, bookmark_name,
2323 } /* if (print_summary) */
2325 if (args->print_args->print_dissections != print_dissections_none) {
2326 if (args->print_args->print_summary) {
2327 /* Separate the summary line from the tree with a blank line. */
2328 if (!print_line(args->print_args->stream, 0, ""))
2332 /* Print the information in that tree. */
2333 if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
2336 /* Print a blank line if we print anything after this (aka more than one packet). */
2337 args->print_separator = TRUE;
2339 /* Print a header line if we print any more packet summaries */
2340 args->print_header_line = TRUE;
2343 if (args->print_args->print_hex) {
2344 /* Print the full packet data as hex. */
2345 if (!print_hex_data(args->print_args->stream, &edt))
2348 /* Print a blank line if we print anything after this (aka more than one packet). */
2349 args->print_separator = TRUE;
2351 /* Print a header line if we print any more packet summaries */
2352 args->print_header_line = TRUE;
2353 } /* if (args->print_args->print_dissections != print_dissections_none) */
2355 epan_dissect_cleanup(&edt);
2357 /* do we want to have a formfeed between each packet from now on? */
2358 if(args->print_args->print_formfeed) {
2359 args->print_formfeed = TRUE;
2365 epan_dissect_cleanup(&edt);
2370 cf_print_packets(capture_file *cf, print_args_t *print_args)
2373 print_callback_args_t callback_args;
2381 callback_args.print_args = print_args;
2382 callback_args.print_header_line = TRUE;
2383 callback_args.header_line_buf = NULL;
2384 callback_args.header_line_buf_len = 256;
2385 callback_args.print_formfeed = FALSE;
2386 callback_args.print_separator = FALSE;
2387 callback_args.line_buf = NULL;
2388 callback_args.line_buf_len = 256;
2389 callback_args.col_widths = NULL;
2391 if (!print_preamble(print_args->stream, cf->filename)) {
2392 destroy_print_stream(print_args->stream);
2393 return CF_PRINT_WRITE_ERROR;
2396 if (print_args->print_summary) {
2397 /* We're printing packet summaries. Allocate the header line buffer
2398 and get the column widths. */
2399 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2401 /* Find the widths for each of the columns - maximum of the
2402 width of the title and the width of the data - and construct
2403 a buffer with a line containing the column titles. */
2404 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2405 cp = &callback_args.header_line_buf[0];
2407 for (i = 0; i < cf->cinfo.num_cols; i++) {
2408 /* Don't pad the last column. */
2409 if (i == cf->cinfo.num_cols - 1)
2410 callback_args.col_widths[i] = 0;
2412 callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
2413 data_width = get_column_char_width(get_column_format(i));
2414 if (data_width > callback_args.col_widths[i])
2415 callback_args.col_widths[i] = data_width;
2418 /* Find the length of the string for this column. */
2419 column_len = (int) strlen(cf->cinfo.col_title[i]);
2420 if (callback_args.col_widths[i] > column_len)
2421 column_len = callback_args.col_widths[i];
2423 /* Make sure there's room in the line buffer for the column; if not,
2424 double its length. */
2425 line_len += column_len + 1; /* "+1" for space */
2426 if (line_len > callback_args.header_line_buf_len) {
2427 cp_off = (int) (cp - callback_args.header_line_buf);
2428 callback_args.header_line_buf_len = 2 * line_len;
2429 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2430 callback_args.header_line_buf_len + 1);
2431 cp = callback_args.header_line_buf + cp_off;
2434 /* Right-justify the packet number column. */
2435 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2436 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2438 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2440 if (i != cf->cinfo.num_cols - 1)
2445 /* Now start out the main line buffer with the same length as the
2446 header line buffer. */
2447 callback_args.line_buf_len = callback_args.header_line_buf_len;
2448 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2449 } /* if (print_summary) */
2451 /* Iterate through the list of packets, printing the packets we were
2453 ret = process_specified_packets(cf, &print_args->range, "Printing",
2454 "selected packets", TRUE, print_packet,
2457 g_free(callback_args.header_line_buf);
2458 g_free(callback_args.line_buf);
2459 g_free(callback_args.col_widths);
2464 /* Completed successfully. */
2468 /* Well, the user decided to abort the printing.
2470 XXX - note that what got generated before they did that
2471 will get printed if we're piping to a print program; we'd
2472 have to write to a file and then hand that to the print
2473 program to make it actually not print anything. */
2477 /* Error while printing.
2479 XXX - note that what got generated before they did that
2480 will get printed if we're piping to a print program; we'd
2481 have to write to a file and then hand that to the print
2482 program to make it actually not print anything. */
2483 destroy_print_stream(print_args->stream);
2484 return CF_PRINT_WRITE_ERROR;
2487 if (!print_finale(print_args->stream)) {
2488 destroy_print_stream(print_args->stream);
2489 return CF_PRINT_WRITE_ERROR;
2492 if (!destroy_print_stream(print_args->stream))
2493 return CF_PRINT_WRITE_ERROR;
2499 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2500 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2506 /* Create the protocol tree, but don't fill in the column information. */
2507 epan_dissect_init(&edt, TRUE, TRUE);
2508 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2510 /* Write out the information in that tree. */
2511 proto_tree_write_pdml(&edt, fh);
2513 epan_dissect_cleanup(&edt);
2519 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2524 fh = ws_fopen(print_args->file, "w");
2526 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2528 write_pdml_preamble(fh);
2531 return CF_PRINT_WRITE_ERROR;
2534 /* Iterate through the list of packets, printing the packets we were
2536 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2537 "selected packets", TRUE,
2538 write_pdml_packet, fh);
2543 /* Completed successfully. */
2547 /* Well, the user decided to abort the printing. */
2551 /* Error while printing. */
2553 return CF_PRINT_WRITE_ERROR;
2556 write_pdml_finale(fh);
2559 return CF_PRINT_WRITE_ERROR;
2562 /* XXX - check for an error */
2569 write_psml_packet(capture_file *cf, frame_data *fdata,
2570 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2575 gboolean proto_tree_needed;
2577 /* Fill in the column information, only create the protocol tree
2578 if having custom columns. */
2579 proto_tree_needed = have_custom_cols(&cf->cinfo);
2580 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2581 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2582 epan_dissect_fill_in_columns(&edt, TRUE);
2584 /* Write out the information in that tree. */
2585 proto_tree_write_psml(&edt, fh);
2587 epan_dissect_cleanup(&edt);
2593 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2598 fh = ws_fopen(print_args->file, "w");
2600 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2602 write_psml_preamble(fh);
2605 return CF_PRINT_WRITE_ERROR;
2608 /* Iterate through the list of packets, printing the packets we were
2610 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2611 "selected packets", TRUE,
2612 write_psml_packet, fh);
2617 /* Completed successfully. */
2621 /* Well, the user decided to abort the printing. */
2625 /* Error while printing. */
2627 return CF_PRINT_WRITE_ERROR;
2630 write_psml_finale(fh);
2633 return CF_PRINT_WRITE_ERROR;
2636 /* XXX - check for an error */
2643 write_csv_packet(capture_file *cf, frame_data *fdata,
2644 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2649 gboolean proto_tree_needed;
2651 /* Fill in the column information, only create the protocol tree
2652 if having custom columns. */
2653 proto_tree_needed = have_custom_cols(&cf->cinfo);
2654 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2655 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2656 epan_dissect_fill_in_columns(&edt, TRUE);
2658 /* Write out the information in that tree. */
2659 proto_tree_write_csv(&edt, fh);
2661 epan_dissect_cleanup(&edt);
2667 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2672 fh = ws_fopen(print_args->file, "w");
2674 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2676 write_csv_preamble(fh);
2679 return CF_PRINT_WRITE_ERROR;
2682 /* Iterate through the list of packets, printing the packets we were
2684 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2685 "selected packets", TRUE,
2686 write_csv_packet, fh);
2691 /* Completed successfully. */
2695 /* Well, the user decided to abort the printing. */
2699 /* Error while printing. */
2701 return CF_PRINT_WRITE_ERROR;
2704 write_csv_finale(fh);
2707 return CF_PRINT_WRITE_ERROR;
2710 /* XXX - check for an error */
2717 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
2718 union wtap_pseudo_header *pseudo_header _U_,
2719 const guint8 *pd, void *argsp)
2723 proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh);
2728 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2733 fh = ws_fopen(print_args->file, "w");
2736 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2738 write_carrays_preamble(fh);
2742 return CF_PRINT_WRITE_ERROR;
2745 /* Iterate through the list of packets, printing the packets we were
2747 ret = process_specified_packets(cf, &print_args->range,
2749 "selected packets", TRUE,
2750 write_carrays_packet, fh);
2753 /* Completed successfully. */
2756 /* Well, the user decided to abort the printing. */
2759 /* Error while printing. */
2761 return CF_PRINT_WRITE_ERROR;
2764 write_carrays_finale(fh);
2768 return CF_PRINT_WRITE_ERROR;
2775 /* Scan through the packet list and change all columns that use the
2776 "command-line-specified" time stamp format to use the current
2777 value of that format. */
2779 cf_change_time_formats(capture_file *cf)
2782 progdlg_t *progbar = NULL;
2788 GTimeVal start_time;
2789 gchar status_str[100];
2790 int progbar_nextstep;
2791 int progbar_quantum;
2792 gboolean sorted_by_frame_column;
2795 /* adjust timestamp precision if auto is selected */
2796 cf_timestamp_auto_precision(cf);
2798 /* Are there any columns with time stamps in the "command-line-specified"
2801 XXX - we have to force the "column is writable" flag on, as it
2802 might be off from the last frame that was dissected. */
2803 col_set_writable(&cf->cinfo, TRUE);
2804 if (!check_col(&cf->cinfo, COL_CLS_TIME) &&
2805 !check_col(&cf->cinfo, COL_ABS_TIME) &&
2806 !check_col(&cf->cinfo, COL_ABS_DATE_TIME) &&
2807 !check_col(&cf->cinfo, COL_REL_TIME) &&
2808 !check_col(&cf->cinfo, COL_DELTA_TIME) &&
2809 !check_col(&cf->cinfo, COL_DELTA_TIME_DIS)) {
2810 /* No, there aren't any columns in that format, so we have no work
2815 /* Freeze the packet list while we redo it, so we don't get any
2816 screen updates while it happens. */
2817 #ifdef NEW_PACKET_LIST
2818 new_packet_list_freeze();
2820 packet_list_freeze();
2823 /* Update the progress bar when it gets to this value. */
2824 progbar_nextstep = 0;
2825 /* When we reach the value that triggers a progress bar update,
2826 bump that value by this amount. */
2827 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2828 /* Count of packets at which we've looked. */
2830 /* Progress so far. */
2833 /* If the rows are currently sorted by the frame column then we know
2834 * the row number of each packet: it's the row number of the previously
2835 * displayed packet + 1.
2837 * Otherwise, if the display is sorted by a different column then we have
2838 * to use the O(N) packet_list_find_row_from_data() (thus making the job
2839 * of changing the time display format O(N**2)).
2841 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
2842 * the row number and walks that many elements down the clist to find
2843 * the appropriate element.)
2845 sorted_by_frame_column = FALSE;
2846 for (i = 0; i < cf->cinfo.num_cols; i++) {
2847 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2849 #ifndef NEW_PACKET_LIST
2850 sorted_by_frame_column = (i == packet_list_get_sort_column());
2857 g_get_current_time(&start_time);
2859 /* Iterate through the list of packets, checking whether the packet
2860 is in a row of the summary list and, if so, whether there are
2861 any columns that show the time in the "command-line-specified"
2862 format and, if so, update that row. */
2863 for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
2864 /* Create the progress bar if necessary.
2865 We check on every iteration of the loop, so that it takes no
2866 longer than the standard time to create it (otherwise, for a
2867 large file, we might take considerably longer than that standard
2868 time in order to get to the next progress bar step). */
2869 if (progbar == NULL)
2870 progbar = delayed_create_progress_dlg("Changing", "time display",
2871 TRUE, &stop_flag, &start_time, progbar_val);
2873 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2874 when we update it, we have to run the GTK+ main loop to get it
2875 to repaint what's pending, and doing so may involve an "ioctl()"
2876 to see if there's any pending input from an X server, and doing
2877 that for every packet can be costly, especially on a big file. */
2878 if (count >= progbar_nextstep) {
2879 /* let's not divide by zero. I should never be started
2880 * with count == 0, so let's assert that
2882 g_assert(cf->count > 0);
2884 progbar_val = (gfloat) count / cf->count;
2886 if (progbar != NULL) {
2887 g_snprintf(status_str, sizeof(status_str),
2888 "%4u of %u packets", count, cf->count);
2889 update_progress_dlg(progbar, progbar_val, status_str);
2892 progbar_nextstep += progbar_quantum;
2896 /* Well, the user decided to abort the redisplay. Just stop.
2898 XXX - this leaves the time field in the old format in
2899 frames we haven't yet processed. So it goes; should we
2900 simply not offer them the option of stopping? */
2906 /* Find what row this packet is in. */
2907 if (!sorted_by_frame_column) {
2908 /* This function is O(N), so we try to avoid using it... */
2909 #ifdef NEW_PACKET_LIST
2910 row = new_packet_list_find_row_from_data(fdata, FALSE);
2912 row = packet_list_find_row_from_data(fdata);
2915 /* ...which we do by maintaining a count of packets that are
2916 being displayed (i.e., that have passed the display filter),
2917 and using the current value of that count as the row number
2918 (which is why we can only do it when the display is sorted
2919 by the frame number). */
2920 if (fdata->flags.passed_dfilter)
2927 /* This packet is in the summary list, on row "row". */
2929 for (i = 0; i < cf->cinfo.num_cols; i++) {
2930 if (col_has_time_fmt(&cf->cinfo, i)) {
2931 /* This is one of the columns that shows the time in
2932 "command-line-specified" format; update it. */
2933 cf->cinfo.col_buf[i][0] = '\0';
2934 col_set_fmt_time(fdata, &cf->cinfo, cf->cinfo.col_fmt[i], i);
2935 #ifdef NEW_PACKET_LIST
2937 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
2944 /* We're done redisplaying the packets; destroy the progress bar if it
2946 if (progbar != NULL)
2947 destroy_progress_dlg(progbar);
2949 /* Set the column widths of those columns that show the time in
2950 "command-line-specified" format. */
2951 for (i = 0; i < cf->cinfo.num_cols; i++) {
2952 if (col_has_time_fmt(&cf->cinfo, i)) {
2953 #ifndef NEW_PACKET_LIST
2954 packet_list_set_time_width(cf->cinfo.col_fmt[i], i);
2959 /* Unfreeze the packet list. */
2960 #ifdef NEW_PACKET_LIST
2961 new_packet_list_thaw();
2971 gboolean frame_matched;
2975 cf_find_packet_protocol_tree(capture_file *cf, const char *string)
2979 mdata.string = string;
2980 mdata.string_len = strlen(string);
2981 return find_packet(cf, match_protocol_tree, &mdata);
2985 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2987 match_data *mdata = criterion;
2990 /* Construct the protocol tree, including the displayed text */
2991 epan_dissect_init(&edt, TRUE, TRUE);
2992 /* We don't need the column information */
2993 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2995 /* Iterate through all the nodes, seeing if they have text that matches. */
2997 mdata->frame_matched = FALSE;
2998 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2999 epan_dissect_cleanup(&edt);
3000 return mdata->frame_matched;
3004 match_subtree_text(proto_node *node, gpointer data)
3006 match_data *mdata = (match_data*) data;
3007 const gchar *string = mdata->string;
3008 size_t string_len = mdata->string_len;
3009 capture_file *cf = mdata->cf;
3010 field_info *fi = PNODE_FINFO(node);
3011 gchar label_str[ITEM_LABEL_LENGTH];
3018 g_assert(fi && "dissection with an invisible proto tree?");
3020 if (mdata->frame_matched) {
3021 /* We already had a match; don't bother doing any more work. */
3025 /* Don't match invisible entries. */
3026 if (PROTO_ITEM_IS_HIDDEN(node))
3029 /* was a free format label produced? */
3031 label_ptr = fi->rep->representation;
3033 /* no, make a generic label */
3034 label_ptr = label_str;
3035 proto_item_fill_label(fi, label_str);
3038 /* Does that label match? */
3039 label_len = strlen(label_ptr);
3040 for (i = 0; i < label_len; i++) {
3041 c_char = label_ptr[i];
3043 c_char = toupper(c_char);
3044 if (c_char == string[c_match]) {
3046 if (c_match == string_len) {
3047 /* No need to look further; we have a match */
3048 mdata->frame_matched = TRUE;
3055 /* Recurse into the subtree, if it exists */
3056 if (node->first_child != NULL)
3057 proto_tree_children_foreach(node, match_subtree_text, mdata);
3061 cf_find_packet_summary_line(capture_file *cf, const char *string)
3065 mdata.string = string;
3066 mdata.string_len = strlen(string);
3067 return find_packet(cf, match_summary_line, &mdata);
3071 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3073 match_data *mdata = criterion;
3074 const gchar *string = mdata->string;
3075 size_t string_len = mdata->string_len;
3077 const char *info_column;
3078 size_t info_column_len;
3079 gboolean frame_matched = FALSE;
3085 /* Don't bother constructing the protocol tree */
3086 epan_dissect_init(&edt, FALSE, FALSE);
3087 /* Get the column information */
3088 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
3090 /* Find the Info column */
3091 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3092 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
3093 /* Found it. See if we match. */
3094 info_column = edt.pi.cinfo->col_data[colx];
3095 info_column_len = strlen(info_column);
3096 for (i = 0; i < info_column_len; i++) {
3097 c_char = info_column[i];
3099 c_char = toupper(c_char);
3100 if (c_char == string[c_match]) {
3102 if (c_match == string_len) {
3103 frame_matched = TRUE;
3112 epan_dissect_cleanup(&edt);
3113 return frame_matched;
3119 } cbs_t; /* "Counted byte string" */
3122 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
3127 info.data_len = string_size;
3129 /* String or hex search? */
3131 /* String search - what type of string? */
3132 switch (cf->scs_type) {
3134 case SCS_ASCII_AND_UNICODE:
3135 return find_packet(cf, match_ascii_and_unicode, &info);
3138 return find_packet(cf, match_ascii, &info);
3141 return find_packet(cf, match_unicode, &info);
3144 g_assert_not_reached();
3148 return find_packet(cf, match_binary, &info);
3152 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3154 cbs_t *info = criterion;
3155 const guint8 *ascii_text = info->data;
3156 size_t textlen = info->data_len;
3157 gboolean frame_matched;
3163 frame_matched = FALSE;
3164 buf_len = fdata->pkt_len;
3165 for (i = 0; i < buf_len; i++) {
3168 c_char = toupper(c_char);
3170 if (c_char == ascii_text[c_match]) {
3172 if (c_match == textlen) {
3173 frame_matched = TRUE;
3174 cf->search_pos = i; /* Save the position of the last character
3175 for highlighting the field. */
3182 return frame_matched;
3186 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
3188 cbs_t *info = criterion;
3189 const guint8 *ascii_text = info->data;
3190 size_t textlen = info->data_len;
3191 gboolean frame_matched;
3197 frame_matched = FALSE;
3198 buf_len = fdata->pkt_len;
3199 for (i = 0; i < buf_len; i++) {
3202 c_char = toupper(c_char);
3203 if (c_char == ascii_text[c_match]) {
3205 if (c_match == textlen) {
3206 frame_matched = TRUE;
3207 cf->search_pos = i; /* Save the position of the last character
3208 for highlighting the field. */
3214 return frame_matched;
3218 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3220 cbs_t *info = criterion;
3221 const guint8 *ascii_text = info->data;
3222 size_t textlen = info->data_len;
3223 gboolean frame_matched;
3229 frame_matched = FALSE;
3230 buf_len = fdata->pkt_len;
3231 for (i = 0; i < buf_len; i++) {
3234 c_char = toupper(c_char);
3235 if (c_char == ascii_text[c_match]) {
3238 if (c_match == textlen) {
3239 frame_matched = TRUE;
3240 cf->search_pos = i; /* Save the position of the last character
3241 for highlighting the field. */
3247 return frame_matched;
3251 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3253 cbs_t *info = criterion;
3254 const guint8 *binary_data = info->data;
3255 size_t datalen = info->data_len;
3256 gboolean frame_matched;
3261 frame_matched = FALSE;
3262 buf_len = fdata->pkt_len;
3263 for (i = 0; i < buf_len; i++) {
3264 if (cf->pd[i] == binary_data[c_match]) {
3266 if (c_match == datalen) {
3267 frame_matched = TRUE;
3268 cf->search_pos = i; /* Save the position of the last character
3269 for highlighting the field. */
3275 return frame_matched;
3279 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
3281 return find_packet(cf, match_dfilter, sfcode);
3285 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3287 dfilter_t *sfcode = criterion;
3289 gboolean frame_matched;
3291 epan_dissect_init(&edt, TRUE, FALSE);
3292 epan_dissect_prime_dfilter(&edt, sfcode);
3293 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3294 frame_matched = dfilter_apply_edt(sfcode, &edt);
3295 epan_dissect_cleanup(&edt);
3296 return frame_matched;
3300 find_packet(capture_file *cf,
3301 gboolean (*match_function)(capture_file *, frame_data *, void *),
3304 frame_data *start_fd;
3306 frame_data *new_fd = NULL;
3307 progdlg_t *progbar = NULL;
3314 GTimeVal start_time;
3315 gchar status_str[100];
3316 int progbar_nextstep;
3317 int progbar_quantum;
3320 start_fd = cf->current_frame;
3321 if (start_fd != NULL) {
3322 /* Iterate through the list of packets, starting at the packet we've
3323 picked, calling a routine to run the filter on the packet, see if
3324 it matches, and stop if so. */
3328 /* Update the progress bar when it gets to this value. */
3329 progbar_nextstep = 0;
3330 /* When we reach the value that triggers a progress bar update,
3331 bump that value by this amount. */
3332 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3333 /* Progress so far. */
3337 g_get_current_time(&start_time);
3340 title = cf->sfilter?cf->sfilter:"";
3342 /* Create the progress bar if necessary.
3343 We check on every iteration of the loop, so that it takes no
3344 longer than the standard time to create it (otherwise, for a
3345 large file, we might take considerably longer than that standard
3346 time in order to get to the next progress bar step). */
3347 if (progbar == NULL)
3348 progbar = delayed_create_progress_dlg("Searching", title,
3349 FALSE, &stop_flag, &start_time, progbar_val);
3351 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3352 when we update it, we have to run the GTK+ main loop to get it
3353 to repaint what's pending, and doing so may involve an "ioctl()"
3354 to see if there's any pending input from an X server, and doing
3355 that for every packet can be costly, especially on a big file. */
3356 if (count >= progbar_nextstep) {
3357 /* let's not divide by zero. I should never be started
3358 * with count == 0, so let's assert that
3360 g_assert(cf->count > 0);
3362 progbar_val = (gfloat) count / cf->count;
3364 if (progbar != NULL) {
3365 g_snprintf(status_str, sizeof(status_str),
3366 "%4u of %u packets", count, cf->count);
3367 update_progress_dlg(progbar, progbar_val, status_str);
3370 progbar_nextstep += progbar_quantum;
3374 /* Well, the user decided to abort the search. Go back to the
3375 frame where we started. */
3380 /* Go past the current frame. */
3381 if (cf->sbackward) {
3382 /* Go on to the previous frame. */
3383 fdata = fdata->prev;
3384 if (fdata == NULL) {
3386 * XXX - other apps have a bit more of a detailed message
3387 * for this, and instead of offering "OK" and "Cancel",
3388 * they offer things such as "Continue" and "Cancel";
3389 * we need an API for popping up alert boxes with
3390 * {Verb} and "Cancel".
3393 if (prefs.gui_find_wrap)
3395 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3396 "%sBeginning of capture exceeded!%s\n\n"
3397 "Search is continued from the end of the capture.",
3398 simple_dialog_primary_start(), simple_dialog_primary_end());
3399 fdata = cf->plist_end; /* wrap around */
3403 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3404 "%sBeginning of capture exceeded!%s\n\n"
3405 "Try searching forwards.",
3406 simple_dialog_primary_start(), simple_dialog_primary_end());
3407 fdata = start_fd; /* stay on previous packet */
3411 /* Go on to the next frame. */
3412 fdata = fdata->next;
3413 if (fdata == NULL) {
3414 if (prefs.gui_find_wrap)
3416 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3417 "%sEnd of capture exceeded!%s\n\n"
3418 "Search is continued from the start of the capture.",
3419 simple_dialog_primary_start(), simple_dialog_primary_end());
3420 fdata = cf->plist; /* wrap around */
3424 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3425 "%sEnd of capture exceeded!%s\n\n"
3426 "Try searching backwards.",
3427 simple_dialog_primary_start(), simple_dialog_primary_end());
3428 fdata = start_fd; /* stay on previous packet */
3435 /* Is this packet in the display? */
3436 if (fdata->flags.passed_dfilter) {
3437 /* Yes. Load its data. */
3438 if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
3439 cf->pd, fdata->cap_len, &err, &err_info)) {
3440 /* Read error. Report the error, and go back to the frame
3441 where we started. */
3442 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3443 cf_read_error_message(err, err_info), cf->filename);
3448 /* Does it match the search criterion? */
3449 if ((*match_function)(cf, fdata, criterion)) {
3451 break; /* found it! */
3455 if (fdata == start_fd) {
3456 /* We're back to the frame we were on originally, and that frame
3457 doesn't match the search filter. The search failed. */
3462 /* We're done scanning the packets; destroy the progress bar if it
3464 if (progbar != NULL)
3465 destroy_progress_dlg(progbar);
3468 if (new_fd != NULL) {
3469 #ifdef NEW_PACKET_LIST
3470 /* Find and select */
3471 row = new_packet_list_find_row_from_data(fdata, TRUE);
3473 /* We found a frame. Find what row it's in. */
3474 row = packet_list_find_row_from_data(new_fd);
3475 #endif /* NEW_PACKET_LIST */
3477 /* We didn't find a row even though we know that a frame
3478 * exists that satifies the search criteria. This means that the
3479 * frame isn't being displayed currently so we can't select it. */
3480 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3481 "%sEnd of capture exceeded!%s\n\n"
3482 "The capture file is probably not fully loaded.",
3483 simple_dialog_primary_start(), simple_dialog_primary_end());
3487 #ifndef NEW_PACKET_LIST
3488 /* Select that row, make it the focus row, and make it visible. */
3489 packet_list_set_selected_row(row);
3490 #endif /* NEW_PACKET_LIST */
3491 return TRUE; /* success */
3493 return FALSE; /* failure */
3497 cf_goto_frame(capture_file *cf, guint fnumber)
3502 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
3505 if (fdata == NULL) {
3506 /* we didn't find a packet with that packet number */
3507 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3508 "There is no packet with the packet number %u.", fnumber);
3509 return FALSE; /* we failed to go to that packet */
3511 if (!fdata->flags.passed_dfilter) {
3512 /* that packet currently isn't displayed */
3513 /* XXX - add it to the set of displayed packets? */
3514 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3515 "The packet number %u isn't currently being displayed.", fnumber);
3516 return FALSE; /* we failed to go to that packet */
3519 #ifdef NEW_PACKET_LIST
3520 row = new_packet_list_find_row_from_data(fdata, TRUE);
3522 /* We found that packet, and it's currently being displayed.
3523 Find what row it's in. */
3524 row = packet_list_find_row_from_data(fdata);
3525 g_assert(row != -1);
3527 /* Select that row, make it the focus row, and make it visible. */
3528 packet_list_set_selected_row(row);
3529 #endif /* NEW_PACKET_LIST */
3530 return TRUE; /* we got to that packet */
3534 cf_goto_top_frame(capture_file *cf _U_)
3536 #ifdef NEW_PACKET_LIST
3537 /* Find and select */
3538 new_packet_list_select_first_row();
3542 frame_data *lowest_fdata = NULL;
3544 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
3545 if (fdata->flags.passed_dfilter) {
3546 lowest_fdata = fdata;
3551 if (lowest_fdata == NULL) {
3555 /* We found that packet, and it's currently being displayed.
3556 Find what row it's in. */
3557 row = packet_list_find_row_from_data(lowest_fdata);
3558 g_assert(row != -1);
3560 /* Select that row, make it the focus row, and make it visible. */
3561 packet_list_set_selected_row(row);
3562 #endif /* NEW_PACKET_LIST */
3563 return TRUE; /* we got to that packet */
3567 cf_goto_bottom_frame(capture_file *cf _U_) /* cf is unused w/ NEW_PACKET_LIST */
3569 #ifdef NEW_PACKET_LIST
3570 /* Find and select */
3571 new_packet_list_select_last_row();
3575 frame_data *highest_fdata = NULL;
3577 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
3578 if (fdata->flags.passed_dfilter) {
3579 highest_fdata = fdata;
3583 if (highest_fdata == NULL) {
3587 /* We found that packet, and it's currently being displayed.
3588 Find what row it's in. */
3589 row = packet_list_find_row_from_data(highest_fdata);
3590 g_assert(row != -1);
3592 /* Select that row, make it the focus row, and make it visible. */
3593 packet_list_set_selected_row(row);
3594 #endif /* NEW_PACKET_LIST */
3595 return TRUE; /* we got to that packet */
3599 * Go to frame specified by currently selected protocol tree item.
3602 cf_goto_framenum(capture_file *cf)
3604 header_field_info *hfinfo;
3607 if (cf->finfo_selected) {
3608 hfinfo = cf->finfo_selected->hfinfo;
3610 if (hfinfo->type == FT_FRAMENUM) {
3611 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3613 return cf_goto_frame(cf, framenum);
3620 /* Select the packet on a given row. */
3622 cf_select_packet(capture_file *cf, int row)
3628 /* Get the frame data struct pointer for this frame */
3629 #ifdef NEW_PACKET_LIST
3630 fdata = new_packet_list_get_row_data(row);
3632 fdata = (frame_data *)packet_list_get_row_data(row);
3635 if (fdata == NULL) {
3636 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3637 the first entry is added to it by "real_insert_row()", that row
3638 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3639 our version and the vanilla GTK+ version).
3641 This means that a "select-row" signal is emitted; this causes
3642 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3645 "cf_select_packet()" fetches, above, the data associated with the
3646 row that was selected; however, as "gtk_clist_append()", which
3647 called "real_insert_row()", hasn't yet returned, we haven't yet
3648 associated any data with that row, so we get back a null pointer.
3650 We can't assume that there's only one frame in the frame list,
3651 either, as we may be filtering the display.
3653 We therefore assume that, if "row" is 0, i.e. the first row
3654 is being selected, and "cf->first_displayed" equals
3655 "cf->last_displayed", i.e. there's only one frame being
3656 displayed, that frame is the frame we want.
3658 This means we have to set "cf->first_displayed" and
3659 "cf->last_displayed" before adding the row to the
3660 GtkCList; see the comment in "add_packet_to_packet_list()". */
3662 if (row == 0 && cf->first_displayed == cf->last_displayed)
3663 fdata = cf->first_displayed;
3666 /* If fdata _still_ isn't set simply give up. */
3667 if (fdata == NULL) {
3671 /* Get the data in that frame. */
3672 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
3673 cf->pd, fdata->cap_len, &err, &err_info)) {
3674 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3675 cf_read_error_message(err, err_info), cf->filename);
3679 /* Record that this frame is the current frame. */
3680 cf->current_frame = fdata;
3681 cf->current_row = row;
3683 /* Create the logical protocol tree. */
3684 if (cf->edt != NULL) {
3685 epan_dissect_free(cf->edt);
3688 /* We don't need the columns here. */
3689 cf->edt = epan_dissect_new(TRUE, TRUE);
3691 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3694 dfilter_macro_build_ftv_cache(cf->edt->tree);
3696 cf_callback_invoke(cf_cb_packet_selected, cf);
3699 /* Unselect the selected packet, if any. */
3701 cf_unselect_packet(capture_file *cf)
3703 /* Destroy the epan_dissect_t for the unselected packet. */
3704 if (cf->edt != NULL) {
3705 epan_dissect_free(cf->edt);
3709 /* No packet is selected. */
3710 cf->current_frame = NULL;
3711 cf->current_row = 0;
3713 cf_callback_invoke(cf_cb_packet_unselected, cf);
3715 /* No protocol tree means no selected field. */
3716 cf_unselect_field(cf);
3719 /* Unset the selected protocol tree field, if any. */
3721 cf_unselect_field(capture_file *cf)
3723 cf->finfo_selected = NULL;
3725 cf_callback_invoke(cf_cb_field_unselected, cf);
3729 * Mark a particular frame.
3732 cf_mark_frame(capture_file *cf, frame_data *frame)
3734 if (! frame->flags.marked) {
3735 frame->flags.marked = TRUE;
3736 if (cf->count > cf->marked_count)
3742 * Unmark a particular frame.
3745 cf_unmark_frame(capture_file *cf, frame_data *frame)
3747 if (frame->flags.marked) {
3748 frame->flags.marked = FALSE;
3749 if (cf->marked_count > 0)
3757 } save_callback_args_t;
3760 * Save a capture to a file, in a particular format, saving either
3761 * all packets, all currently-displayed packets, or all marked packets.
3763 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3764 * up a message box for the failure.
3767 save_packet(capture_file *cf _U_, frame_data *fdata,
3768 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3771 save_callback_args_t *args = argsp;
3772 struct wtap_pkthdr hdr;
3775 /* init the wtap header for saving */
3776 hdr.ts.secs = fdata->abs_ts.secs;
3777 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3778 hdr.caplen = fdata->cap_len;
3779 hdr.len = fdata->pkt_len;
3780 hdr.pkt_encap = fdata->lnk_t;
3782 /* and save the packet */
3783 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3784 cf_write_failure_alert_box(args->fname, err);
3791 * Can this capture file be saved in any format except by copying the raw data?
3794 cf_can_save_as(capture_file *cf)
3798 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
3799 /* To save a file with Wiretap, Wiretap has to handle that format,
3800 and its code to handle that format must be able to write a file
3801 with this file's encapsulation type. */
3802 if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
3803 /* OK, we can write it out in this type. */
3808 /* No, we couldn't save it in any format. */
3813 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3815 gchar *from_filename;
3819 save_callback_args_t callback_args;
3821 cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname);
3823 /* don't write over an existing file. */
3824 /* this should've been already checked by our caller, just to be sure... */
3825 if (file_exists(fname)) {
3826 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3827 "%sCapture file: \"%s\" already exists!%s\n\n"
3828 "Please choose a different filename.",
3829 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3833 packet_range_process_init(range);
3836 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3837 /* We're not filtering packets, and we're saving it in the format
3838 it's already in, so we can just move or copy the raw data. */
3840 if (cf->is_tempfile) {
3841 /* The file being saved is a temporary file from a live
3842 capture, so it doesn't need to stay around under that name;
3843 first, try renaming the capture buffer file to the new name. */
3845 if (ws_rename(cf->filename, fname) == 0) {
3846 /* That succeeded - there's no need to copy the source file. */
3847 from_filename = NULL;
3850 if (errno == EXDEV) {
3851 /* They're on different file systems, so we have to copy the
3854 from_filename = cf->filename;
3856 /* The rename failed, but not because they're on different
3857 file systems - put up an error message. (Or should we
3858 just punt and try to copy? The only reason why I'd
3859 expect the rename to fail and the copy to succeed would
3860 be if we didn't have permission to remove the file from
3861 the temporary directory, and that might be fixable - but
3862 is it worth requiring the user to go off and fix it?) */
3863 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3864 file_rename_error_message(errno), fname);
3870 from_filename = cf->filename;
3873 /* It's a permanent file, so we should copy it, and not remove the
3876 from_filename = cf->filename;
3880 /* Copy the file, if we haven't moved it. */
3881 if (!copy_file_binary_mode(from_filename, fname))
3885 /* Either we're filtering packets, or we're saving in a different
3886 format; we can't do that by copying or moving the capture file,
3887 we have to do it by writing the packets out in Wiretap. */
3888 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3891 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3895 /* XXX - we let the user save a subset of the packets.
3897 If we do that, should we make that file the current file? If so,
3898 it means we can no longer get at the other packets. What does
3901 /* Iterate through the list of packets, processing the packets we were
3904 XXX - we've already called "packet_range_process_init(range)", but
3905 "process_specified_packets()" will do it again. Fortunately,
3906 that's harmless in this case, as we haven't done anything to
3907 "range" since we initialized it. */
3908 callback_args.pdh = pdh;
3909 callback_args.fname = fname;
3910 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3911 TRUE, save_packet, &callback_args)) {
3914 /* Completed successfully. */
3918 /* The user decided to abort the saving.
3919 XXX - remove the output file? */
3923 /* Error while saving. */
3924 wtap_dump_close(pdh, &err);
3928 if (!wtap_dump_close(pdh, &err)) {
3929 cf_close_failure_alert_box(fname, err);
3934 cf_callback_invoke(cf_cb_file_safe_finished, NULL);
3936 if (packet_range_process_all(range)) {
3937 /* We saved the entire capture, not just some packets from it.
3938 Open and read the file we saved it to.
3940 XXX - this is somewhat of a waste; we already have the
3941 packets, all this gets us is updated file type information
3942 (which we could just stuff into "cf"), and having the new
3943 file be the one we have opened and from which we're reading
3944 the data, and it means we have to spend time opening and
3945 reading the file, which could be a significant amount of
3946 time if the file is large. */
3947 cf->user_saved = TRUE;
3949 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3950 /* XXX - report errors if this fails?
3951 What should we return if it fails or is aborted? */
3952 switch (cf_read(cf)) {
3956 /* Just because we got an error, that doesn't mean we were unable
3957 to read any of the file; we handle what we could get from the
3961 case CF_READ_ABORTED:
3962 /* The user bailed out of re-reading the capture file; the
3963 capture file has been closed - just return (without
3964 changing any menu settings; "cf_close()" set them
3965 correctly for the "no capture file open" state). */
3968 cf_callback_invoke(cf_cb_file_safe_reload_finished, NULL);
3974 cf_callback_invoke(cf_cb_file_safe_failed, NULL);
3979 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3980 gboolean for_writing, int file_type)
3983 /* Wiretap error. */
3986 case WTAP_ERR_NOT_REGULAR_FILE:
3987 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3988 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3992 case WTAP_ERR_RANDOM_OPEN_PIPE:
3993 /* Seen only when opening a capture file for reading. */
3994 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3995 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
3999 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
4000 /* Seen only when opening a capture file for reading. */
4001 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4002 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
4006 case WTAP_ERR_UNSUPPORTED:
4007 /* Seen only when opening a capture file for reading. */
4008 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4009 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
4011 filename, err_info);
4015 case WTAP_ERR_CANT_WRITE_TO_PIPE:
4016 /* Seen only when opening a capture file for writing. */
4017 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4018 "The file \"%s\" is a pipe, and %s capture files can't be "
4019 "written to a pipe.",
4020 filename, wtap_file_type_string(file_type));
4023 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
4024 /* Seen only when opening a capture file for writing. */
4025 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4026 "Wireshark doesn't support writing capture files in that format.");
4029 case WTAP_ERR_UNSUPPORTED_ENCAP:
4031 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4032 "Wireshark can't save this capture in that format.");
4034 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4035 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
4037 filename, err_info);
4042 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
4044 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4045 "Wireshark can't save this capture in that format.");
4047 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4048 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
4053 case WTAP_ERR_BAD_RECORD:
4054 /* Seen only when opening a capture file for reading. */
4055 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4056 "The file \"%s\" appears to be damaged or corrupt.\n"
4058 filename, err_info);
4062 case WTAP_ERR_CANT_OPEN:
4064 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4065 "The file \"%s\" could not be created for some unknown reason.",
4068 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4069 "The file \"%s\" could not be opened for some unknown reason.",
4074 case WTAP_ERR_SHORT_READ:
4075 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4076 "The file \"%s\" appears to have been cut short"
4077 " in the middle of a packet or other data.",
4081 case WTAP_ERR_SHORT_WRITE:
4082 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4083 "A full header couldn't be written to the file \"%s\".",
4087 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4088 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4089 "Gzip compression not supported by this file type.");
4093 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4094 "The file \"%s\" could not be %s: %s.",
4096 for_writing ? "created" : "opened",
4097 wtap_strerror(err));
4102 open_failure_alert_box(filename, err, for_writing);
4107 file_rename_error_message(int err)
4110 static char errmsg_errno[1024+1];
4115 errmsg = "The path to the file \"%s\" doesn't exist.";
4119 errmsg = "You don't have permission to move the capture file to \"%s\".";
4123 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4124 "The file \"%%s\" could not be moved: %s.",
4125 wtap_strerror(err));
4126 errmsg = errmsg_errno;
4133 cf_read_error_message(int err, gchar *err_info)
4135 static char errmsg_errno[1024+1];
4139 case WTAP_ERR_UNSUPPORTED_ENCAP:
4140 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4141 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
4146 case WTAP_ERR_BAD_RECORD:
4147 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4148 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
4149 wtap_strerror(err), err_info);
4154 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4155 "An error occurred while reading from the file \"%%s\": %s.",
4156 wtap_strerror(err));
4159 return errmsg_errno;
4163 cf_write_failure_alert_box(const char *filename, int err)
4166 /* Wiretap error. */
4167 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4168 "An error occurred while writing to the file \"%s\": %s.",
4169 filename, wtap_strerror(err));
4172 write_failure_alert_box(filename, err);
4176 /* Check for write errors - if the file is being written to an NFS server,
4177 a write error may not show up until the file is closed, as NFS clients
4178 might not send writes to the server until the "write()" call finishes,
4179 so that the write may fail on the server but the "write()" may succeed. */
4181 cf_close_failure_alert_box(const char *filename, int err)
4184 /* Wiretap error. */
4187 case WTAP_ERR_CANT_CLOSE:
4188 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4189 "The file \"%s\" couldn't be closed for some unknown reason.",
4193 case WTAP_ERR_SHORT_WRITE:
4194 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4195 "Not all the packets could be written to the file \"%s\".",
4200 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4201 "An error occurred while closing the file \"%s\": %s.",
4202 filename, wtap_strerror(err));
4207 We assume that a close error from the OS is really a write error. */
4208 write_failure_alert_box(filename, err);
4212 /* Reload the current capture file. */
4214 cf_reload(capture_file *cf) {
4216 gboolean is_tempfile;
4219 /* If the file could be opened, "cf_open()" calls "cf_close()"
4220 to get rid of state for the old capture file before filling in state
4221 for the new capture file. "cf_close()" will remove the file if
4222 it's a temporary file; we don't want that to happen (for one thing,
4223 it'd prevent subsequent reopens from working). Remember whether it's
4224 a temporary file, mark it as not being a temporary file, and then
4225 reopen it as the type of file it was.
4227 Also, "cf_close()" will free "cf->filename", so we must make
4228 a copy of it first. */
4229 filename = g_strdup(cf->filename);
4230 is_tempfile = cf->is_tempfile;
4231 cf->is_tempfile = FALSE;
4232 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4233 switch (cf_read(cf)) {
4237 /* Just because we got an error, that doesn't mean we were unable
4238 to read any of the file; we handle what we could get from the
4242 case CF_READ_ABORTED:
4243 /* The user bailed out of re-reading the capture file; the
4244 capture file has been closed - just free the capture file name
4245 string and return (without changing the last containing
4251 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4252 Instead, the file was left open, so we should restore "cf->is_tempfile"
4255 XXX - change the menu? Presumably "cf_open()" will do that;
4256 make sure it does! */
4257 cf->is_tempfile = is_tempfile;
4259 /* "cf_open()" made a copy of the file name we handed it, so
4260 we should free up our copy. */