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
124 /* We read around 200k/100ms domt update the progress bar more often than that */
125 #define MIN_QUANTUM 200000
126 #define MIN_NUMBER_OF_PACKET 1500
128 /* Number of "frame_data" structures per memory chunk.
129 XXX - is this the right number? */
130 #define FRAME_DATA_CHUNK_SIZE 1024
133 /* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
135 cf_callback_t cb_fct;
137 } cf_callback_data_t;
139 static GList *cf_callbacks = NULL;
142 cf_callback_invoke(int event, gpointer data)
144 cf_callback_data_t *cb;
145 GList *cb_item = cf_callbacks;
147 /* there should be at least one interested */
148 g_assert(cb_item != NULL);
150 while(cb_item != NULL) {
152 cb->cb_fct(event, data, cb->user_data);
153 cb_item = g_list_next(cb_item);
159 cf_callback_add(cf_callback_t func, gpointer user_data)
161 cf_callback_data_t *cb;
163 cb = g_malloc(sizeof(cf_callback_data_t));
165 cb->user_data = user_data;
167 cf_callbacks = g_list_append(cf_callbacks, cb);
171 cf_callback_remove(cf_callback_t func)
173 cf_callback_data_t *cb;
174 GList *cb_item = cf_callbacks;
176 while(cb_item != NULL) {
178 if(cb->cb_fct == func) {
179 cf_callbacks = g_list_remove(cf_callbacks, cb);
183 cb_item = g_list_next(cb_item);
186 g_assert_not_reached();
190 cf_timestamp_auto_precision(capture_file *cf)
192 int prec = timestamp_get_precision();
195 /* don't try to get the file's precision if none is opened */
196 if(cf->state == FILE_CLOSED) {
200 /* if we are in auto mode, set precision of current file */
201 if(prec == TS_PREC_AUTO ||
202 prec == TS_PREC_AUTO_SEC ||
203 prec == TS_PREC_AUTO_DSEC ||
204 prec == TS_PREC_AUTO_CSEC ||
205 prec == TS_PREC_AUTO_MSEC ||
206 prec == TS_PREC_AUTO_USEC ||
207 prec == TS_PREC_AUTO_NSEC)
209 switch(wtap_file_tsprecision(cf->wth)) {
210 case(WTAP_FILE_TSPREC_SEC):
211 timestamp_set_precision(TS_PREC_AUTO_SEC);
213 case(WTAP_FILE_TSPREC_DSEC):
214 timestamp_set_precision(TS_PREC_AUTO_DSEC);
216 case(WTAP_FILE_TSPREC_CSEC):
217 timestamp_set_precision(TS_PREC_AUTO_CSEC);
219 case(WTAP_FILE_TSPREC_MSEC):
220 timestamp_set_precision(TS_PREC_AUTO_MSEC);
222 case(WTAP_FILE_TSPREC_USEC):
223 timestamp_set_precision(TS_PREC_AUTO_USEC);
225 case(WTAP_FILE_TSPREC_NSEC):
226 timestamp_set_precision(TS_PREC_AUTO_NSEC);
229 g_assert_not_reached();
236 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
241 wth = wtap_open_offline(fname, err, &err_info, TRUE);
245 /* The open succeeded. Close whatever capture file we had open,
246 and fill in the information for this file. */
249 /* Initialize all data structures used for dissection. */
252 /* We're about to start reading the file. */
253 cf->state = FILE_READ_IN_PROGRESS;
258 /* Set the file name because we need it to set the follow stream filter.
259 XXX - is that still true? We need it for other reasons, though,
261 cf->filename = g_strdup(fname);
263 /* Indicate whether it's a permanent or temporary file. */
264 cf->is_tempfile = is_tempfile;
266 /* If it's a temporary capture buffer file, mark it as not saved. */
267 cf->user_saved = !is_tempfile;
269 cf->cd_t = wtap_file_type(cf->wth);
271 cf->displayed_count = 0;
272 cf->marked_count = 0;
273 cf->drops_known = FALSE;
275 cf->snap = wtap_snapshot_length(cf->wth);
277 /* Snapshot length not known. */
278 cf->has_snap = FALSE;
279 cf->snap = WTAP_MAX_PACKET_SIZE;
282 nstime_set_zero(&cf->elapsed_time);
283 nstime_set_unset(&first_ts);
284 nstime_set_unset(&prev_dis_ts);
286 #if GLIB_CHECK_VERSION(2,10,0)
288 /* memory chunks have been deprecated in favor of the slice allocator,
289 * which has been added in 2.10
291 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
293 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
295 g_assert(cf->plist_chunk);
297 /* change the time formats now, as we might have a new precision */
298 cf_change_time_formats(cf);
300 fileset_file_opened(fname);
302 if(cf->cd_t == WTAP_FILE_BER) {
303 /* tell the BER dissector the file name */
304 ber_set_filename(cf->filename);
310 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
316 * Reset the state for the currently closed file, but don't do the
317 * UI callbacks; this is for use in "cf_open()", where we don't
318 * want the UI to go from "file open" to "file closed" back to
319 * "file open", we want it to go from "old file open" to "new file
320 * open and being read".
323 cf_reset_state(capture_file *cf)
325 /* Die if we're in the middle of reading a file. */
326 g_assert(cf->state != FILE_READ_IN_PROGRESS);
332 /* We have no file open... */
333 if (cf->filename != NULL) {
334 /* If it's a temporary file, remove it. */
336 ws_unlink(cf->filename);
337 g_free(cf->filename);
340 /* ...which means we have nothing to save. */
341 cf->user_saved = FALSE;
343 #if GLIB_CHECK_VERSION(2,10,0)
344 if (cf->plist != NULL)
345 g_slice_free_chain(frame_data, cf->plist, next);
347 /* memory chunks have been deprecated in favor of the slice allocator,
348 * which has been added in 2.10
350 if (cf->plist_chunk != NULL) {
351 g_mem_chunk_destroy(cf->plist_chunk);
352 cf->plist_chunk = NULL;
355 if (cf->rfcode != NULL) {
356 dfilter_free(cf->rfcode);
360 cf->plist_end = NULL;
361 cf_unselect_packet(cf); /* nothing to select */
362 cf->first_displayed = NULL;
363 cf->last_displayed = NULL;
365 /* No frame selected, no field in that frame selected. */
366 cf->current_frame = NULL;
368 cf->finfo_selected = NULL;
370 /* Clear the packet list. */
371 #ifdef NEW_PACKET_LIST
372 new_packet_list_freeze();
373 new_packet_list_clear();
374 new_packet_list_thaw();
376 packet_list_freeze();
383 nstime_set_zero(&cf->elapsed_time);
385 reset_tap_listeners();
387 /* We have no file open. */
388 cf->state = FILE_CLOSED;
390 fileset_file_closed();
393 /* Reset everything to a pristine state */
395 cf_close(capture_file *cf)
397 /* do GUI things even if file is already closed,
398 * e.g. to cleanup things if a capture couldn't be started */
399 cf_callback_invoke(cf_cb_file_closing, cf);
401 /* close things, if not already closed before */
402 if(cf->state != FILE_CLOSED) {
403 color_filters_cleanup();
405 cleanup_dissection();
408 cf_callback_invoke(cf_cb_file_closed, cf);
411 /* an out of memory exception occured, wait for a user button press to exit */
412 void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
418 cf_get_computed_elapsed(void){
419 return computed_elapsed;
421 static void compute_elapsed(GTimeVal *start_time)
426 g_get_current_time(&time_now);
428 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
429 time_now.tv_usec - start_time->tv_usec;
431 computed_elapsed = (gulong) (delta_time / 1000); /* ms*/
434 static float calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos){
438 progbar_val = (gfloat) file_pos / (gfloat) size;
439 if (progbar_val > 1.0) {
440 /* The file probably grew while we were reading it.
441 Update file size, and try again. */
442 size = wtap_file_size(cf->wth, NULL);
444 progbar_val = (gfloat) file_pos / (gfloat) size;
445 /* If it's still > 1, either "wtap_file_size()" failed (in which
446 case there's not much we can do about it), or the file
447 *shrank* (in which case there's not much we can do about
448 it); just clip the progress value at 1.0. */
449 if (progbar_val > 1.0f)
456 cf_read(capture_file *cf)
460 const gchar *name_ptr;
462 char errmsg_errno[1024+1];
464 progdlg_t *volatile progbar = NULL;
466 volatile gint64 size;
467 volatile float progbar_val;
469 gchar status_str[100];
470 volatile gint64 progbar_nextstep;
471 volatile gint64 progbar_quantum;
473 gboolean filtering_tap_listeners;
475 volatile int count = 0;
477 volatile int displayed_once = 0;
480 /* Compile the current display filter.
481 * We assume this will not fail since cf->dfilter is only set in
482 * cf_filter IFF the filter was valid.
486 dfilter_compile(cf->dfilter, &dfcode);
489 /* Do we have any tap listeners with filters? */
490 filtering_tap_listeners = have_filtering_tap_listeners();
492 /* Get the union of the flags for all tap listeners. */
493 tap_flags = union_of_tap_listener_flags();
497 reset_tap_listeners();
499 cf_callback_invoke(cf_cb_file_read_start, cf);
501 name_ptr = get_basename(cf->filename);
503 /* Find the size of the file. */
504 size = wtap_file_size(cf->wth, NULL);
506 /* Update the progress bar when it gets to this value. */
507 progbar_nextstep = 0;
508 /* When we reach the value that triggers a progress bar update,
509 bump that value by this amount. */
511 progbar_quantum = size/N_PROGBAR_UPDATES;
512 if (progbar_quantum < MIN_QUANTUM)
513 progbar_quantum = MIN_QUANTUM;
516 /* Progress so far. */
519 #ifdef NEW_PACKET_LIST
520 new_packet_list_freeze();
522 packet_list_freeze();
526 g_get_current_time(&start_time);
528 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
531 /* Create the progress bar if necessary.
532 * Check wether it should be created or not every MIN_NUMBER_OF_PACKET
534 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
535 progbar_val = calc_progbar_val( cf, size, data_offset);
536 progbar = delayed_create_progress_dlg("Loading", name_ptr,
537 TRUE, &stop_flag, &start_time, progbar_val);
540 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
541 when we update it, we have to run the GTK+ main loop to get it
542 to repaint what's pending, and doing so may involve an "ioctl()"
543 to see if there's any pending input from an X server, and doing
544 that for every packet can be costly, especially on a big file. */
545 if (data_offset >= progbar_nextstep) {
546 if (progbar != NULL) {
547 progbar_val = calc_progbar_val( cf, size, data_offset);
548 /* update the packet lists content on the first run or frequently on very large files */
549 /* (on smaller files the display update takes longer than reading the file) */
551 if (progbar_quantum > 500000 || displayed_once == 0) {
552 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
554 #ifdef NEW_PACKET_LIST
555 new_packet_list_thaw();
556 if (auto_scroll_live)
557 new_packet_list_moveto_end();
558 new_packet_list_freeze();
561 if (auto_scroll_live)
562 packet_list_moveto_end();
563 packet_list_freeze();
564 #endif /* NEW_PACKET_LIST */
567 #endif /* HAVE_LIBPCAP */
568 g_snprintf(status_str, sizeof(status_str),
569 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
570 data_offset / 1024, size / 1024);
571 update_progress_dlg(progbar, progbar_val, status_str);
573 progbar_nextstep += progbar_quantum;
578 /* Well, the user decided to abort the read. He/She will be warned and
579 it might be enough for him/her to work with the already loaded
581 This is especially true for very large capture files, where you don't
582 want to wait loading the whole file (which may last minutes or even
583 hours even on fast machines) just to see that it was the wrong file. */
587 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
589 CATCH(OutOfMemoryError) {
592 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
593 "%sOut Of Memory!%s\n"
595 "Sorry, but Wireshark has to terminate now!\n"
597 "Some infos / workarounds can be found at:\n"
598 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
599 simple_dialog_primary_start(), simple_dialog_primary_end());
600 /* we have to terminate, as we cannot recover from the memory error */
601 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
603 main_window_update();
604 /* XXX - how to avoid a busy wait? */
612 /* Cleanup and release all dfilter resources */
614 dfilter_free(dfcode);
617 /* We're done reading the file; destroy the progress bar if it was created. */
619 destroy_progress_dlg(progbar);
621 /* We're done reading sequentially through the file. */
622 cf->state = FILE_READ_DONE;
624 /* Close the sequential I/O side, to free up memory it requires. */
625 wtap_sequential_close(cf->wth);
627 /* Allow the protocol dissectors to free up memory that they
628 * don't need after the sequential run-through of the packets. */
629 postseq_cleanup_all_protocols();
631 /* compute the time it took to load the file */
632 compute_elapsed(&start_time);
634 /* Set the file encapsulation type now; we don't know what it is until
635 we've looked at all the packets, as we don't know until then whether
636 there's more than one type (and thus whether it's
637 WTAP_ENCAP_PER_PACKET). */
638 cf->lnk_t = wtap_file_encap(cf->wth);
640 cf->current_frame = cf->first_displayed;
643 #ifdef NEW_PACKET_LIST
644 new_packet_list_thaw();
649 cf_callback_invoke(cf_cb_file_read_finished, cf);
651 /* If we have any displayed packets to select, select the first of those
652 packets by making the first row the selected row. */
653 if (cf->first_displayed != NULL){
654 #ifdef NEW_PACKET_LIST
655 new_packet_list_select_first_row();
657 packet_list_select_row(0);
658 #endif /* NEW_PACKET_LIST */
662 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
663 "%sFile loading was cancelled!%s\n"
665 "The remaining packets in the file were discarded.\n"
667 "As a lot of packets from the original file will be missing,\n"
668 "remember to be careful when saving the current content to a file.\n",
669 simple_dialog_primary_start(), simple_dialog_primary_end());
670 return CF_READ_ERROR;
674 /* Put up a message box noting that the read failed somewhere along
675 the line. Don't throw out the stuff we managed to read, though,
679 case WTAP_ERR_UNSUPPORTED_ENCAP:
680 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
681 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
684 errmsg = errmsg_errno;
687 case WTAP_ERR_CANT_READ:
688 errmsg = "An attempt to read from the capture file failed for"
689 " some unknown reason.";
692 case WTAP_ERR_SHORT_READ:
693 errmsg = "The capture file appears to have been cut short"
694 " in the middle of a packet.";
697 case WTAP_ERR_BAD_RECORD:
698 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
699 "The capture file appears to be damaged or corrupt.\n(%s)",
702 errmsg = errmsg_errno;
706 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
707 "An error occurred while reading the"
708 " capture file: %s.", wtap_strerror(err));
709 errmsg = errmsg_errno;
712 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
713 return CF_READ_ERROR;
720 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
722 cf_status_t cf_status;
724 cf_status = cf_open(cf, fname, is_tempfile, err);
729 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
731 gint64 data_offset = 0;
733 volatile int newly_displayed_packets = 0;
735 gboolean filtering_tap_listeners;
738 /* Compile the current display filter.
739 * We assume this will not fail since cf->dfilter is only set in
740 * cf_filter IFF the filter was valid.
744 dfilter_compile(cf->dfilter, &dfcode);
747 /* Do we have any tap listeners with filters? */
748 filtering_tap_listeners = have_filtering_tap_listeners();
750 /* Get the union of the flags for all tap listeners. */
751 tap_flags = union_of_tap_listener_flags();
755 #ifdef NEW_PACKET_LIST
756 new_packet_list_freeze();
758 packet_list_check_end();
759 packet_list_freeze();
762 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
764 while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
765 if (cf->state == FILE_READ_ABORTED) {
766 /* Well, the user decided to exit Wireshark. Break out of the
767 loop, and let the code below (which is called even if there
768 aren't any packets left to read) exit. */
772 if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
773 data_offset) != -1) {
774 newly_displayed_packets++;
777 CATCH(OutOfMemoryError) {
780 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
781 "%sOut Of Memory!%s\n"
783 "Sorry, but Wireshark has to terminate now!\n"
785 "The capture file is not lost, it can be found at:\n"
788 "Some infos / workarounds can be found at:\n"
789 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
790 simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
791 /* we have to terminate, as we cannot recover from the memory error */
792 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
794 main_window_update();
795 /* XXX - how to avoid a busy wait? */
798 #ifdef NEW_PACKET_LIST
799 new_packet_list_thaw();
803 return CF_READ_ABORTED;
809 /* Cleanup and release all dfilter resources */
811 dfilter_free(dfcode);
814 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
815 cf->count, cf->state, *err);*/
817 #ifdef NEW_PACKET_LIST
818 new_packet_list_thaw();
820 /* XXX - this causes "flickering" of the list */
824 /* moving to the end of the packet list - if the user requested so and
825 we have some new packets. */
826 if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL)
827 #ifdef NEW_PACKET_LIST
828 new_packet_list_moveto_end();
830 /* this doesn't seem to work well with a frozen GTK_Clist, so do this after
831 packet_list_thaw() is done, see bugzilla 1188 */
832 /* XXX - this cheats and looks inside the packet list to find the final
834 packet_list_moveto_end();
835 #endif /* NEW_PACKET_LIST */
837 if (cf->state == FILE_READ_ABORTED) {
838 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
839 so that our caller can kill off the capture child process;
840 this will cause an EOF on the pipe from the child, so
841 "cf_finish_tail()" will be called, and it will clean up
843 return CF_READ_ABORTED;
844 } else if (*err != 0) {
845 /* We got an error reading the capture file.
846 XXX - pop up a dialog box instead? */
847 g_warning("Error \"%s\" while reading: \"%s\"\n",
848 wtap_strerror(*err), cf->filename);
850 return CF_READ_ERROR;
856 cf_finish_tail(capture_file *cf, int *err)
861 gboolean filtering_tap_listeners;
864 /* Compile the current display filter.
865 * We assume this will not fail since cf->dfilter is only set in
866 * cf_filter IFF the filter was valid.
870 dfilter_compile(cf->dfilter, &dfcode);
873 /* Do we have any tap listeners with filters? */
874 filtering_tap_listeners = have_filtering_tap_listeners();
876 /* Get the union of the flags for all tap listeners. */
877 tap_flags = union_of_tap_listener_flags();
879 if(cf->wth == NULL) {
881 return CF_READ_ERROR;
884 #ifdef NEW_PACKET_LIST
885 new_packet_list_freeze();
887 packet_list_check_end();
888 packet_list_freeze();
891 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
892 if (cf->state == FILE_READ_ABORTED) {
893 /* Well, the user decided to abort the read. Break out of the
894 loop, and let the code below (which is called even if there
895 aren't any packets left to read) exit. */
898 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
901 /* Cleanup and release all dfilter resources */
903 dfilter_free(dfcode);
906 #ifdef NEW_PACKET_LIST
907 new_packet_list_thaw();
912 if (cf->state == FILE_READ_ABORTED) {
913 /* Well, the user decided to abort the read. We're only called
914 when the child capture process closes the pipe to us (meaning
915 it's probably exited), so we can just close the capture
916 file; we return CF_READ_ABORTED so our caller can do whatever
917 is appropriate when that happens. */
919 return CF_READ_ABORTED;
922 if (auto_scroll_live && cf->plist_end != NULL)
923 #ifdef NEW_PACKET_LIST
924 new_packet_list_moveto_end();
926 /* XXX - this cheats and looks inside the packet list to find the final
928 packet_list_moveto_end();
931 /* We're done reading sequentially through the file. */
932 cf->state = FILE_READ_DONE;
934 /* We're done reading sequentially through the file; close the
935 sequential I/O side, to free up memory it requires. */
936 wtap_sequential_close(cf->wth);
938 /* Allow the protocol dissectors to free up memory that they
939 * don't need after the sequential run-through of the packets. */
940 postseq_cleanup_all_protocols();
942 /* Set the file encapsulation type now; we don't know what it is until
943 we've looked at all the packets, as we don't know until then whether
944 there's more than one type (and thus whether it's
945 WTAP_ENCAP_PER_PACKET). */
946 cf->lnk_t = wtap_file_encap(cf->wth);
949 /* We got an error reading the capture file.
950 XXX - pop up a dialog box? */
951 return CF_READ_ERROR;
956 #endif /* HAVE_LIBPCAP */
959 cf_get_display_name(capture_file *cf)
961 const gchar *displayname;
963 /* Return a name to use in displays */
964 if (!cf->is_tempfile) {
965 /* Get the last component of the file name, and use that. */
967 displayname = get_basename(cf->filename);
969 displayname="(No file)";
972 /* The file we read is a temporary file from a live capture;
973 we don't mention its name. */
974 displayname = "(Untitled)";
979 /* XXX - use a macro instead? */
981 cf_get_packet_count(capture_file *cf)
986 /* XXX - use a macro instead? */
988 cf_set_packet_count(capture_file *cf, int packet_count)
990 cf->count = packet_count;
993 /* XXX - use a macro instead? */
995 cf_is_tempfile(capture_file *cf)
997 return cf->is_tempfile;
1000 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1002 cf->is_tempfile = is_tempfile;
1006 /* XXX - use a macro instead? */
1007 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1009 cf->drops_known = drops_known;
1012 /* XXX - use a macro instead? */
1013 void cf_set_drops(capture_file *cf, guint32 drops)
1018 /* XXX - use a macro instead? */
1019 gboolean cf_get_drops_known(capture_file *cf)
1021 return cf->drops_known;
1024 /* XXX - use a macro instead? */
1025 guint32 cf_get_drops(capture_file *cf)
1030 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1032 cf->rfcode = rfcode;
1036 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1037 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1039 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1041 #ifdef NEW_PACKET_LIST
1042 gboolean add_to_packet_list)
1044 gboolean add_to_packet_list _U_)
1047 gboolean create_proto_tree = FALSE;
1052 #ifdef NEW_PACKET_LIST
1053 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1058 /* just add some value here until we know if it is being displayed or not */
1059 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1061 /* If we don't have the time stamp of the first packet in the
1062 capture, it's because this is the first packet. Save the time
1063 stamp of this packet as the time stamp of the first packet. */
1064 if (nstime_is_unset(&first_ts)) {
1065 first_ts = fdata->abs_ts;
1067 /* if this frames is marked as a reference time frame, reset
1068 firstsec and firstusec to this frame */
1069 if(fdata->flags.ref_time){
1070 first_ts = fdata->abs_ts;
1073 /* If we don't have the time stamp of the previous displayed packet,
1074 it's because this is the first displayed packet. Save the time
1075 stamp of this packet as the time stamp of the previous displayed
1077 if (nstime_is_unset(&prev_dis_ts)) {
1078 prev_dis_ts = fdata->abs_ts;
1081 /* Get the time elapsed between the first packet and this packet. */
1082 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
1084 /* If it's greater than the current elapsed time, set the elapsed time
1085 to it (we check for "greater than" so as not to be confused by
1086 time moving backwards). */
1087 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
1088 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
1089 cf->elapsed_time = fdata->rel_ts;
1092 /* Get the time elapsed between the previous displayed packet and
1094 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
1098 we have a display filter and are re-applying it;
1100 we have a list of color filters;
1102 we have tap listeners with filters;
1104 we have tap listeners that require a protocol tree;
1106 we have custom columns;
1108 allocate a protocol tree root node, so that we'll construct
1109 a protocol tree against which a filter expression can be
1111 if ((dfcode != NULL && refilter) ||
1112 #ifndef NEW_PACKET_LIST
1113 color_filters_used() ||
1114 have_custom_cols(cinfo) ||
1116 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1117 create_proto_tree = TRUE;
1119 /* Dissect the frame. */
1120 epan_dissect_init(&edt, create_proto_tree, FALSE);
1122 if (dfcode != NULL && refilter) {
1123 epan_dissect_prime_dfilter(&edt, dfcode);
1126 /* prepare color filters */
1127 #ifndef NEW_PACKET_LIST
1128 color_filters_prime_edt(&edt);
1129 col_custom_prime_edt(&edt, cinfo);
1132 tap_queue_init(&edt);
1133 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1134 tap_push_tapped_queue(&edt);
1136 /* If we have a display filter, apply it if we're refiltering, otherwise
1137 leave the "passed_dfilter" flag alone.
1139 If we don't have a display filter, set "passed_dfilter" to 1. */
1140 if (dfcode != NULL) {
1142 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1145 fdata->flags.passed_dfilter = 1;
1147 #ifdef NEW_PACKET_LIST
1148 if (add_to_packet_list) {
1149 /* We fill the needed columns from new_packet_list */
1150 row = new_packet_list_append(cinfo, fdata, &edt.pi);
1154 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) )
1156 /* This frame either passed the display filter list or is marked as
1157 a time reference frame. All time reference frames are displayed
1158 even if they dont pass the display filter */
1159 if(fdata->flags.ref_time){
1160 /* if this was a TIME REF frame we should reset the cul bytes field */
1161 cum_bytes = fdata->pkt_len;
1162 fdata->cum_bytes = cum_bytes;
1164 /* increase cum_bytes with this packets length */
1165 cum_bytes += fdata->pkt_len;
1168 #ifndef NEW_PACKET_LIST
1169 epan_dissect_fill_in_columns(&edt, TRUE);
1172 /* If we haven't yet seen the first frame, this is it.
1174 XXX - we must do this before we add the row to the display,
1175 as, if the display's GtkCList's selection mode is
1176 GTK_SELECTION_BROWSE, when the first entry is added to it,
1177 "cf_select_packet()" will be called, and it will fetch the row
1178 data for the 0th row, and will get a null pointer rather than
1179 "fdata", as "gtk_clist_append()" won't yet have returned and
1180 thus "gtk_clist_set_row_data()" won't yet have been called.
1182 We thus need to leave behind bread crumbs so that
1183 "cf_select_packet()" can find this frame. See the comment
1184 in "cf_select_packet()". */
1185 if (cf->first_displayed == NULL)
1186 cf->first_displayed = fdata;
1188 /* This is the last frame we've seen so far. */
1189 cf->last_displayed = fdata;
1191 #ifndef NEW_PACKET_LIST
1192 row = packet_list_append(cinfo->col_data, fdata);
1194 /* colorize packet: first apply color filters
1195 * then if packet is marked, use preferences to overwrite color
1196 * we do both to make sure that when a packet gets un-marked, the
1197 * color will be correctly set (fixes bug 2038)
1199 fdata->color_filter = color_filters_colorize_packet(row, &edt);
1200 if (fdata->flags.marked) {
1201 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
1203 #endif /* NEW_PACKET_LIST */
1205 /* Set the time of the previous displayed frame to the time of this
1207 prev_dis_ts = fdata->abs_ts;
1209 cf->displayed_count++;
1212 epan_dissect_cleanup(&edt);
1216 /* read in a new packet */
1217 /* returns the row of the new packet in the packet list or -1 if not displayed */
1219 read_packet(capture_file *cf, dfilter_t *dfcode,
1220 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1222 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1223 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1224 const guchar *buf = wtap_buf_ptr(cf->wth);
1227 frame_data *plist_end;
1230 /* Allocate the next list entry, and add it to the list.
1231 * memory chunks have been deprecated in favor of the slice allocator,
1232 * which has been added in 2.10
1234 #if GLIB_CHECK_VERSION(2,10,0)
1235 fdata = g_slice_new(frame_data);
1237 fdata = g_mem_chunk_alloc(cf->plist_chunk);
1243 fdata->pkt_len = phdr->len;
1244 fdata->cap_len = phdr->caplen;
1245 fdata->file_off = offset;
1246 fdata->lnk_t = phdr->pkt_encap;
1247 fdata->flags.encoding = CHAR_ASCII;
1248 fdata->flags.visited = 0;
1249 fdata->flags.marked = 0;
1250 fdata->flags.ref_time = 0;
1251 fdata->color_filter = NULL;
1252 fdata->col_text = NULL;
1254 fdata->abs_ts.secs = phdr->ts.secs;
1255 fdata->abs_ts.nsecs = phdr->ts.nsecs;
1257 if (cf->plist_end != NULL)
1258 nstime_delta(&fdata->del_cap_ts, &fdata->abs_ts, &cf->plist_end->abs_ts);
1260 nstime_set_zero(&fdata->del_cap_ts);
1265 epan_dissect_init(&edt, TRUE, FALSE);
1266 epan_dissect_prime_dfilter(&edt, cf->rfcode);
1267 epan_dissect_run(&edt, pseudo_header, buf, fdata, NULL);
1268 passed = dfilter_apply_edt(cf->rfcode, &edt);
1269 epan_dissect_cleanup(&edt);
1272 plist_end = cf->plist_end;
1273 fdata->prev = plist_end;
1274 if (plist_end != NULL)
1275 plist_end->next = fdata;
1278 cf->plist_end = fdata;
1281 cf->f_datalen = offset + phdr->caplen;
1282 fdata->num = cf->count;
1283 if (!cf->redissecting) {
1284 row = add_packet_to_packet_list(fdata, cf, dfcode,
1285 filtering_tap_listeners, tap_flags,
1286 pseudo_header, buf, TRUE, TRUE);
1289 /* XXX - if we didn't have read filters, or if we could avoid
1290 allocating the "frame_data" structure until we knew whether
1291 the frame passed the read filter, we could use a G_ALLOC_ONLY
1294 ...but, at least in one test I did, where I just made the chunk
1295 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
1296 seem to save a noticeable amount of time or space. */
1297 #if GLIB_CHECK_VERSION(2,10,0)
1298 /* memory chunks have been deprecated in favor of the slice allocator,
1299 * which has been added in 2.10
1301 g_slice_free(frame_data,fdata);
1303 g_mem_chunk_free(cf->plist_chunk, fdata);
1311 cf_merge_files(char **out_filenamep, int in_file_count,
1312 char *const *in_filenames, int file_type, gboolean do_append)
1314 merge_in_file_t *in_files;
1320 int open_err, read_err, write_err, close_err;
1324 char errmsg_errno[1024+1];
1326 gboolean got_read_error = FALSE, got_write_error = FALSE;
1328 progdlg_t *progbar = NULL;
1330 gint64 f_len, file_pos;
1332 GTimeVal start_time;
1333 gchar status_str[100];
1334 gint64 progbar_nextstep;
1335 gint64 progbar_quantum;
1337 /* open the input files */
1338 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1339 &open_err, &err_info, &err_fileno)) {
1341 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1346 if (*out_filenamep != NULL) {
1347 out_filename = *out_filenamep;
1348 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1352 out_fd = create_tempfile(&tmpname, "wireshark");
1355 out_filename = g_strdup(tmpname);
1356 *out_filenamep = out_filename;
1360 merge_close_in_files(in_file_count, in_files);
1362 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1366 pdh = wtap_dump_fdopen(out_fd, file_type,
1367 merge_select_frame_type(in_file_count, in_files),
1368 merge_max_snapshot_length(in_file_count, in_files),
1369 FALSE /* compressed */, &open_err);
1372 merge_close_in_files(in_file_count, in_files);
1374 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1379 /* Get the sum of the sizes of all the files. */
1381 for (i = 0; i < in_file_count; i++)
1382 f_len += in_files[i].size;
1384 /* Update the progress bar when it gets to this value. */
1385 progbar_nextstep = 0;
1386 /* When we reach the value that triggers a progress bar update,
1387 bump that value by this amount. */
1388 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1389 /* Progress so far. */
1393 g_get_current_time(&start_time);
1395 /* do the merge (or append) */
1398 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1401 wth = merge_read_packet(in_file_count, in_files, &read_err,
1405 got_read_error = TRUE;
1409 /* Get the sum of the data offsets in all of the files. */
1411 for (i = 0; i < in_file_count; i++)
1412 data_offset += in_files[i].data_offset;
1414 /* Create the progress bar if necessary.
1415 We check on every iteration of the loop, so that it takes no
1416 longer than the standard time to create it (otherwise, for a
1417 large file, we might take considerably longer than that standard
1418 time in order to get to the next progress bar step). */
1419 if (progbar == NULL) {
1420 progbar = delayed_create_progress_dlg("Merging", "files",
1421 FALSE, &stop_flag, &start_time, progbar_val);
1424 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1425 when we update it, we have to run the GTK+ main loop to get it
1426 to repaint what's pending, and doing so may involve an "ioctl()"
1427 to see if there's any pending input from an X server, and doing
1428 that for every packet can be costly, especially on a big file. */
1429 if (data_offset >= progbar_nextstep) {
1430 /* Get the sum of the seek positions in all of the files. */
1432 for (i = 0; i < in_file_count; i++)
1433 file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1434 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1435 if (progbar_val > 1.0f) {
1436 /* Some file probably grew while we were reading it.
1437 That "shouldn't happen", so we'll just clip the progress
1441 if (progbar != NULL) {
1442 g_snprintf(status_str, sizeof(status_str),
1443 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1444 file_pos / 1024, f_len / 1024);
1445 update_progress_dlg(progbar, progbar_val, status_str);
1447 progbar_nextstep += progbar_quantum;
1451 /* Well, the user decided to abort the merge. */
1455 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1456 wtap_buf_ptr(wth), &write_err)) {
1457 got_write_error = TRUE;
1462 /* We're done merging the files; destroy the progress bar if it was created. */
1463 if (progbar != NULL)
1464 destroy_progress_dlg(progbar);
1466 merge_close_in_files(in_file_count, in_files);
1467 if (!got_read_error && !got_write_error) {
1468 if (!wtap_dump_close(pdh, &write_err))
1469 got_write_error = TRUE;
1471 wtap_dump_close(pdh, &close_err);
1473 if (got_read_error) {
1475 * Find the file on which we got the error, and report the error.
1477 for (i = 0; i < in_file_count; i++) {
1478 if (in_files[i].state == GOT_ERROR) {
1479 /* Put up a message box noting that a read failed somewhere along
1483 case WTAP_ERR_UNSUPPORTED_ENCAP:
1484 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1485 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1488 errmsg = errmsg_errno;
1491 case WTAP_ERR_CANT_READ:
1492 errmsg = "An attempt to read from the capture file %s failed for"
1493 " some unknown reason.";
1496 case WTAP_ERR_SHORT_READ:
1497 errmsg = "The capture file %s appears to have been cut short"
1498 " in the middle of a packet.";
1501 case WTAP_ERR_BAD_RECORD:
1502 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1503 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1506 errmsg = errmsg_errno;
1510 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1511 "An error occurred while reading the"
1512 " capture file %%s: %s.", wtap_strerror(read_err));
1513 errmsg = errmsg_errno;
1516 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
1521 if (got_write_error) {
1522 /* Put up an alert box for the write error. */
1523 cf_write_failure_alert_box(out_filename, write_err);
1526 if (got_read_error || got_write_error || stop_flag) {
1527 /* Callers aren't expected to treat an error or an explicit abort
1528 differently - we put up error dialogs ourselves, so they don't
1536 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1538 const char *filter_new = dftext ? dftext : "";
1539 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1542 /* if new filter equals old one, do nothing unless told to do so */
1543 if (!force && strcmp(filter_new, filter_old) == 0) {
1549 if (dftext == NULL) {
1550 /* The new filter is an empty filter (i.e., display all packets).
1551 * so leave dfcode==NULL
1555 * We have a filter; make a copy of it (as we'll be saving it),
1556 * and try to compile it.
1558 dftext = g_strdup(dftext);
1559 if (!dfilter_compile(dftext, &dfcode)) {
1560 /* The attempt failed; report an error. */
1561 gchar *safe_dftext = simple_dialog_format_message(dftext);
1562 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1564 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1567 "The following display filter isn't a valid display filter:\n%s\n"
1568 "See the help for a description of the display filter syntax.",
1569 simple_dialog_primary_start(), safe_dfilter_error_msg,
1570 simple_dialog_primary_end(), safe_dftext);
1571 g_free(safe_dfilter_error_msg);
1572 g_free(safe_dftext);
1578 if (dfcode == NULL) {
1579 /* Yes - free the filter text, and set it to null. */
1585 /* We have a valid filter. Replace the current filter. */
1586 g_free(cf->dfilter);
1587 cf->dfilter = dftext;
1589 /* Now rescan the packet list, applying the new filter, but not
1590 throwing away information constructed on a previous pass. */
1591 if (dftext == NULL) {
1592 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1594 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1597 /* Cleanup and release all dfilter resources */
1598 if (dfcode != NULL){
1599 dfilter_free(dfcode);
1605 cf_colorize_packets(capture_file *cf)
1607 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1611 cf_reftime_packets(capture_file *cf)
1614 #ifdef NEW_PACKET_LIST
1615 ref_time_packets(cf);
1617 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1622 cf_redissect_packets(capture_file *cf)
1624 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1627 /* Rescan the list of packets, reconstructing the CList.
1629 "action" describes why we're doing this; it's used in the progress
1632 "action_item" describes what we're doing; it's used in the progress
1635 "refilter" is TRUE if we need to re-evaluate the filter expression.
1637 "redissect" is TRUE if we need to make the dissectors reconstruct
1638 any state information they have (because a preference that affects
1639 some dissector has changed, meaning some dissector might construct
1640 its state differently from the way it was constructed the last time). */
1642 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1643 gboolean refilter, gboolean redissect)
1646 progdlg_t *progbar = NULL;
1651 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1652 int selected_row, prev_row, preceding_row, following_row;
1653 gboolean selected_frame_seen;
1656 GTimeVal start_time;
1657 gchar status_str[100];
1658 int progbar_nextstep;
1659 int progbar_quantum;
1661 gboolean filtering_tap_listeners;
1663 #ifdef NEW_PACKET_LIST
1664 gboolean add_to_packet_list = FALSE;
1666 gboolean add_to_packet_list = TRUE;
1669 /* Compile the current display filter.
1670 * We assume this will not fail since cf->dfilter is only set in
1671 * cf_filter IFF the filter was valid.
1675 dfilter_compile(cf->dfilter, &dfcode);
1678 /* Do we have any tap listeners with filters? */
1679 filtering_tap_listeners = have_filtering_tap_listeners();
1681 /* Get the union of the flags for all tap listeners. */
1682 tap_flags = union_of_tap_listener_flags();
1685 reset_tap_listeners();
1686 /* Which frame, if any, is the currently selected frame?
1687 XXX - should the selected frame or the focus frame be the "current"
1688 frame, that frame being the one from which "Find Frame" searches
1690 selected_frame = cf->current_frame;
1692 /* We don't yet know what row that frame will be on, if any, after we
1693 rebuild the clist, however. */
1696 /* Freeze the packet list while we redo it, so we don't get any
1697 screen updates while it happens. */
1698 #ifdef NEW_PACKET_LIST
1699 new_packet_list_freeze();
1701 packet_list_freeze();
1704 packet_list_clear();
1708 /* We need to re-initialize all the state information that protocols
1709 keep, because some preference that controls a dissector has changed,
1710 which might cause the state information to be constructed differently
1711 by that dissector. */
1713 /* We might receive new packets while redissecting, and we don't
1714 want to dissect those before their time. */
1715 cf->redissecting = TRUE;
1717 /* Initialize all data structures used for dissection. */
1720 #ifdef NEW_PACKET_LIST
1721 /* We need to redissect the packets so we have to discard our old
1722 * packet list store. */
1723 new_packet_list_clear();
1724 add_to_packet_list = TRUE;
1728 /* We don't yet know which will be the first and last frames displayed. */
1729 cf->first_displayed = NULL;
1730 cf->last_displayed = NULL;
1732 /* We currently don't display any packets */
1733 cf->displayed_count = 0;
1735 /* Iterate through the list of frames. Call a routine for each frame
1736 to check whether it should be displayed and, if so, add it to
1737 the display list. */
1738 nstime_set_unset(&first_ts);
1739 nstime_set_unset(&prev_dis_ts);
1741 /* Update the progress bar when it gets to this value. */
1742 progbar_nextstep = 0;
1743 /* When we reach the value that triggers a progress bar update,
1744 bump that value by this amount. */
1745 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1746 /* Count of packets at which we've looked. */
1748 /* Progress so far. */
1752 g_get_current_time(&start_time);
1754 row = -1; /* no previous row yet */
1759 preceding_frame = NULL;
1761 following_frame = NULL;
1763 selected_frame_seen = FALSE;
1765 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1766 /* Create the progress bar if necessary.
1767 We check on every iteration of the loop, so that it takes no
1768 longer than the standard time to create it (otherwise, for a
1769 large file, we might take considerably longer than that standard
1770 time in order to get to the next progress bar step). */
1771 if (progbar == NULL)
1772 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1773 &stop_flag, &start_time,
1776 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1777 when we update it, we have to run the GTK+ main loop to get it
1778 to repaint what's pending, and doing so may involve an "ioctl()"
1779 to see if there's any pending input from an X server, and doing
1780 that for every packet can be costly, especially on a big file. */
1781 if (count >= progbar_nextstep) {
1782 /* let's not divide by zero. I should never be started
1783 * with count == 0, so let's assert that
1785 g_assert(cf->count > 0);
1786 progbar_val = (gfloat) count / cf->count;
1788 if (progbar != NULL) {
1789 g_snprintf(status_str, sizeof(status_str),
1790 "%4u of %u frames", count, cf->count);
1791 update_progress_dlg(progbar, progbar_val, status_str);
1794 progbar_nextstep += progbar_quantum;
1798 /* Well, the user decided to abort the filtering. Just stop.
1800 XXX - go back to the previous filter? Users probably just
1801 want not to wait for a filtering operation to finish;
1802 unless we cancel by having no filter, reverting to the
1803 previous filter will probably be even more expensive than
1804 continuing the filtering, as it involves going back to the
1805 beginning and filtering, and even with no filter we currently
1806 have to re-generate the entire clist, which is also expensive.
1808 I'm not sure what Network Monitor does, but it doesn't appear
1809 to give you an unfiltered display if you cancel. */
1816 /* Since all state for the frame was destroyed, mark the frame
1817 * as not visited, free the GSList referring to the state
1818 * data (the per-frame data itself was freed by
1819 * "init_dissection()"), and null out the GSList pointer. */
1820 fdata->flags.visited = 0;
1822 g_slist_free(fdata->pfd);
1827 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1828 cf->pd, fdata->cap_len, &err, &err_info)) {
1829 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1830 cf_read_error_message(err, err_info), cf->filename);
1834 /* If the previous frame is displayed, and we haven't yet seen the
1835 selected frame, remember that frame - it's the closest one we've
1836 yet seen before the selected frame. */
1837 if (prev_row != -1 && !selected_frame_seen) {
1838 preceding_row = prev_row;
1839 preceding_frame = prev_frame;
1841 row = add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1842 tap_flags, &cf->pseudo_header, cf->pd,
1844 add_to_packet_list);
1846 /* If this frame is displayed, and this is the first frame we've
1847 seen displayed after the selected frame, remember this frame -
1848 it's the closest one we've yet seen at or after the selected
1850 if (row != -1 && selected_frame_seen && following_row == -1) {
1851 following_row = row;
1852 following_frame = fdata;
1854 if (fdata == selected_frame) {
1856 selected_frame_seen = TRUE;
1859 /* Remember this row/frame - it'll be the previous row/frame
1860 on the next pass through the loop. */
1865 /* We are done redissecting the packet list. */
1866 cf->redissecting = FALSE;
1868 #ifndef NEW_PACKET_LIST
1869 /* Re-sort the list using the previously selected order */
1870 packet_list_set_sort_column();
1874 /* Clear out what remains of the visited flags and per-frame data
1877 XXX - that may cause various forms of bogosity when dissecting
1878 these frames, as they won't have been seen by this sequential
1879 pass, but the only alternative I see is to keep scanning them
1880 even though the user requested that the scan stop, and that
1881 would leave the user stuck with an Wireshark grinding on
1882 until it finishes. Should we just stick them with that? */
1883 for (; fdata != NULL; fdata = fdata->next) {
1884 fdata->flags.visited = 0;
1886 g_slist_free(fdata->pfd);
1892 /* We're done filtering the packets; destroy the progress bar if it
1894 if (progbar != NULL)
1895 destroy_progress_dlg(progbar);
1897 /* Unfreeze the packet list. */
1898 #ifdef NEW_PACKET_LIST
1899 new_packet_list_thaw();
1904 if (selected_row == -1) {
1905 /* The selected frame didn't pass the filter. */
1906 if (selected_frame == NULL) {
1907 /* That's because there *was* no selected frame. Make the first
1908 displayed frame the current frame. */
1911 /* Find the nearest displayed frame to the selected frame (whether
1912 it's before or after that frame) and make that the current frame.
1913 If the next and previous displayed frames are equidistant from the
1914 selected frame, choose the next one. */
1915 g_assert(following_frame == NULL ||
1916 following_frame->num >= selected_frame->num);
1917 g_assert(preceding_frame == NULL ||
1918 preceding_frame->num <= selected_frame->num);
1919 if (following_frame == NULL) {
1920 /* No frame after the selected frame passed the filter, so we
1921 have to select the last displayed frame before the selected
1923 selected_row = preceding_row;
1924 } else if (preceding_frame == NULL) {
1925 /* No frame before the selected frame passed the filter, so we
1926 have to select the first displayed frame after the selected
1928 selected_row = following_row;
1930 /* Frames before and after the selected frame passed the filter, so
1931 we'll select the previous frame */
1932 selected_row = preceding_row;
1937 if (selected_row == -1) {
1938 /* There are no frames displayed at all. */
1939 cf_unselect_packet(cf);
1941 #ifndef NEW_PACKET_LIST
1942 /* Either the frame that was selected passed the filter, or we've
1943 found the nearest displayed frame to that frame. Select it, make
1944 it the focus row, and make it visible. */
1945 if (selected_row == 0) {
1946 /* Set to invalid to force update of packet list and packet details */
1947 cf->current_row = -1;
1949 packet_list_set_selected_row(selected_row);
1950 #endif /* NEW_PACKET_LIST */
1953 /* Cleanup and release all dfilter resources */
1954 if (dfcode != NULL){
1955 dfilter_free(dfcode);
1959 * Scan trough all frame data and recalculate the ref time
1960 * without rereading the file.
1961 * XXX - do we need a progres bar or is this fast enough?
1963 #ifdef NEW_PACKET_LIST
1965 ref_time_packets(capture_file *cf)
1971 nstime_set_unset(&first_ts);
1972 nstime_set_unset(&prev_dis_ts);
1975 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1977 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1978 /* just add some value here until we know if it is being displayed or not */
1979 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1981 /* If we don't have the time stamp of the first packet in the
1982 capture, it's because this is the first packet. Save the time
1983 stamp of this packet as the time stamp of the first packet. */
1984 if (nstime_is_unset(&first_ts)) {
1985 first_ts = fdata->abs_ts;
1987 /* if this frames is marked as a reference time frame, reset
1988 firstsec and firstusec to this frame */
1989 if(fdata->flags.ref_time){
1990 first_ts = fdata->abs_ts;
1993 /* If we don't have the time stamp of the previous displayed packet,
1994 it's because this is the first displayed packet. Save the time
1995 stamp of this packet as the time stamp of the previous displayed
1997 if (nstime_is_unset(&prev_dis_ts)) {
1998 prev_dis_ts = fdata->abs_ts;
2001 /* Get the time elapsed between the first packet and this packet. */
2002 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
2004 /* If it's greater than the current elapsed time, set the elapsed time
2005 to it (we check for "greater than" so as not to be confused by
2006 time moving backwards). */
2007 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
2008 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
2009 cf->elapsed_time = fdata->rel_ts;
2012 /* Get the time elapsed between the previous displayed packet and
2014 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
2016 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
2017 /* This frame either passed the display filter list or is marked as
2018 a time reference frame. All time reference frames are displayed
2019 even if they dont pass the display filter */
2020 if(fdata->flags.ref_time){
2021 /* if this was a TIME REF frame we should reset the cul bytes field */
2022 cum_bytes = fdata->pkt_len;
2023 fdata->cum_bytes = cum_bytes;
2025 /* increase cum_bytes with this packets length */
2026 cum_bytes += fdata->pkt_len;
2039 process_specified_packets(capture_file *cf, packet_range_t *range,
2040 const char *string1, const char *string2, gboolean terminate_is_stop,
2041 gboolean (*callback)(capture_file *, frame_data *,
2042 union wtap_pseudo_header *, const guint8 *, void *),
2043 void *callback_args)
2048 union wtap_pseudo_header pseudo_header;
2049 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
2050 psp_return_t ret = PSP_FINISHED;
2052 progdlg_t *progbar = NULL;
2055 gboolean progbar_stop_flag;
2056 GTimeVal progbar_start_time;
2057 gchar progbar_status_str[100];
2058 int progbar_nextstep;
2059 int progbar_quantum;
2060 range_process_e process_this;
2062 /* Update the progress bar when it gets to this value. */
2063 progbar_nextstep = 0;
2064 /* When we reach the value that triggers a progress bar update,
2065 bump that value by this amount. */
2066 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2067 /* Count of packets at which we've looked. */
2069 /* Progress so far. */
2072 progbar_stop_flag = FALSE;
2073 g_get_current_time(&progbar_start_time);
2075 packet_range_process_init(range);
2077 /* Iterate through the list of packets, printing the packets that
2078 were selected by the current display filter. */
2079 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2080 /* Create the progress bar if necessary.
2081 We check on every iteration of the loop, so that it takes no
2082 longer than the standard time to create it (otherwise, for a
2083 large file, we might take considerably longer than that standard
2084 time in order to get to the next progress bar step). */
2085 if (progbar == NULL)
2086 progbar = delayed_create_progress_dlg(string1, string2,
2089 &progbar_start_time,
2092 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2093 when we update it, we have to run the GTK+ main loop to get it
2094 to repaint what's pending, and doing so may involve an "ioctl()"
2095 to see if there's any pending input from an X server, and doing
2096 that for every packet can be costly, especially on a big file. */
2097 if (progbar_count >= progbar_nextstep) {
2098 /* let's not divide by zero. I should never be started
2099 * with count == 0, so let's assert that
2101 g_assert(cf->count > 0);
2102 progbar_val = (gfloat) progbar_count / cf->count;
2104 if (progbar != NULL) {
2105 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2106 "%4u of %u packets", progbar_count, cf->count);
2107 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2110 progbar_nextstep += progbar_quantum;
2113 if (progbar_stop_flag) {
2114 /* Well, the user decided to abort the operation. Just stop,
2115 and arrange to return PSP_STOPPED to our caller, so they know
2116 it was stopped explicitly. */
2123 /* do we have to process this packet? */
2124 process_this = packet_range_process_packet(range, fdata);
2125 if (process_this == range_process_next) {
2126 /* this packet uninteresting, continue with next one */
2128 } else if (process_this == range_processing_finished) {
2129 /* all interesting packets processed, stop the loop */
2133 /* Get the packet */
2134 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
2135 pd, fdata->cap_len, &err, &err_info)) {
2136 /* Attempt to get the packet failed. */
2137 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2138 cf_read_error_message(err, err_info), cf->filename);
2142 /* Process the packet */
2143 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
2144 /* Callback failed. We assume it reported the error appropriately. */
2150 /* We're done printing the packets; destroy the progress bar if
2152 if (progbar != NULL)
2153 destroy_progress_dlg(progbar);
2159 gboolean construct_protocol_tree;
2161 } retap_callback_args_t;
2164 retap_packet(capture_file *cf _U_, frame_data *fdata,
2165 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2168 retap_callback_args_t *args = argsp;
2171 epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
2172 tap_queue_init(&edt);
2173 epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
2174 tap_push_tapped_queue(&edt);
2175 epan_dissect_cleanup(&edt);
2181 cf_retap_packets(capture_file *cf)
2183 packet_range_t range;
2184 retap_callback_args_t callback_args;
2185 gboolean filtering_tap_listeners;
2188 /* Do we have any tap listeners with filters? */
2189 filtering_tap_listeners = have_filtering_tap_listeners();
2191 tap_flags = union_of_tap_listener_flags();
2193 /* If any tap listeners have filters, or require the protocol tree,
2194 construct the protocol tree. */
2195 callback_args.construct_protocol_tree = filtering_tap_listeners ||
2196 (tap_flags & TL_REQUIRES_PROTO_TREE);
2198 /* If any tap listeners require the columns, construct them. */
2199 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2201 /* Reset the tap listeners. */
2202 reset_tap_listeners();
2204 /* Iterate through the list of packets, dissecting all packets and
2205 re-running the taps. */
2206 packet_range_init(&range);
2207 packet_range_process_init(&range);
2208 switch (process_specified_packets(cf, &range, "Recalculating statistics on",
2209 "all packets", TRUE, retap_packet,
2212 /* Completed successfully. */
2216 /* Well, the user decided to abort the refiltering.
2217 Return CF_READ_ABORTED so our caller knows they did that. */
2218 return CF_READ_ABORTED;
2221 /* Error while retapping. */
2222 return CF_READ_ERROR;
2225 g_assert_not_reached();
2230 print_args_t *print_args;
2231 gboolean print_header_line;
2232 char *header_line_buf;
2233 int header_line_buf_len;
2234 gboolean print_formfeed;
2235 gboolean print_separator;
2239 } print_callback_args_t;
2242 print_packet(capture_file *cf, frame_data *fdata,
2243 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2246 print_callback_args_t *args = argsp;
2253 gboolean proto_tree_needed;
2254 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2255 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2257 /* Create the protocol tree, and make it visible, if we're printing
2258 the dissection or the hex data.
2259 XXX - do we need it if we're just printing the hex data? */
2261 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2262 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2264 /* Fill in the column information if we're printing the summary
2266 if (args->print_args->print_summary) {
2267 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2268 epan_dissect_fill_in_columns(&edt, TRUE);
2270 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2272 if (args->print_formfeed) {
2273 if (!new_page(args->print_args->stream))
2276 if (args->print_separator) {
2277 if (!print_line(args->print_args->stream, 0, ""))
2283 * We generate bookmarks, if the output format supports them.
2284 * The name is "__frameN__".
2286 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2288 if (args->print_args->print_summary) {
2289 if (args->print_header_line) {
2290 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2292 args->print_header_line = FALSE; /* we might not need to print any more */
2294 cp = &args->line_buf[0];
2296 for (i = 0; i < cf->cinfo.num_cols; i++) {
2297 /* Find the length of the string for this column. */
2298 column_len = (int) strlen(cf->cinfo.col_data[i]);
2299 if (args->col_widths[i] > column_len)
2300 column_len = args->col_widths[i];
2302 /* Make sure there's room in the line buffer for the column; if not,
2303 double its length. */
2304 line_len += column_len + 1; /* "+1" for space */
2305 if (line_len > args->line_buf_len) {
2306 cp_off = (int) (cp - args->line_buf);
2307 args->line_buf_len = 2 * line_len;
2308 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2309 cp = args->line_buf + cp_off;
2312 /* Right-justify the packet number column. */
2313 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2314 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
2316 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
2318 if (i != cf->cinfo.num_cols - 1)
2324 * Generate a bookmark, using the summary line as the title.
2326 if (!print_bookmark(args->print_args->stream, bookmark_name,
2330 if (!print_line(args->print_args->stream, 0, args->line_buf))
2334 * Generate a bookmark, using "Frame N" as the title, as we're not
2335 * printing the summary line.
2337 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2338 if (!print_bookmark(args->print_args->stream, bookmark_name,
2341 } /* if (print_summary) */
2343 if (args->print_args->print_dissections != print_dissections_none) {
2344 if (args->print_args->print_summary) {
2345 /* Separate the summary line from the tree with a blank line. */
2346 if (!print_line(args->print_args->stream, 0, ""))
2350 /* Print the information in that tree. */
2351 if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
2354 /* Print a blank line if we print anything after this (aka more than one packet). */
2355 args->print_separator = TRUE;
2357 /* Print a header line if we print any more packet summaries */
2358 args->print_header_line = TRUE;
2361 if (args->print_args->print_hex) {
2362 /* Print the full packet data as hex. */
2363 if (!print_hex_data(args->print_args->stream, &edt))
2366 /* Print a blank line if we print anything after this (aka more than one packet). */
2367 args->print_separator = TRUE;
2369 /* Print a header line if we print any more packet summaries */
2370 args->print_header_line = TRUE;
2371 } /* if (args->print_args->print_dissections != print_dissections_none) */
2373 epan_dissect_cleanup(&edt);
2375 /* do we want to have a formfeed between each packet from now on? */
2376 if(args->print_args->print_formfeed) {
2377 args->print_formfeed = TRUE;
2383 epan_dissect_cleanup(&edt);
2388 cf_print_packets(capture_file *cf, print_args_t *print_args)
2391 print_callback_args_t callback_args;
2399 callback_args.print_args = print_args;
2400 callback_args.print_header_line = TRUE;
2401 callback_args.header_line_buf = NULL;
2402 callback_args.header_line_buf_len = 256;
2403 callback_args.print_formfeed = FALSE;
2404 callback_args.print_separator = FALSE;
2405 callback_args.line_buf = NULL;
2406 callback_args.line_buf_len = 256;
2407 callback_args.col_widths = NULL;
2409 if (!print_preamble(print_args->stream, cf->filename)) {
2410 destroy_print_stream(print_args->stream);
2411 return CF_PRINT_WRITE_ERROR;
2414 if (print_args->print_summary) {
2415 /* We're printing packet summaries. Allocate the header line buffer
2416 and get the column widths. */
2417 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2419 /* Find the widths for each of the columns - maximum of the
2420 width of the title and the width of the data - and construct
2421 a buffer with a line containing the column titles. */
2422 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2423 cp = &callback_args.header_line_buf[0];
2425 for (i = 0; i < cf->cinfo.num_cols; i++) {
2426 /* Don't pad the last column. */
2427 if (i == cf->cinfo.num_cols - 1)
2428 callback_args.col_widths[i] = 0;
2430 callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
2431 data_width = get_column_char_width(get_column_format(i));
2432 if (data_width > callback_args.col_widths[i])
2433 callback_args.col_widths[i] = data_width;
2436 /* Find the length of the string for this column. */
2437 column_len = (int) strlen(cf->cinfo.col_title[i]);
2438 if (callback_args.col_widths[i] > column_len)
2439 column_len = callback_args.col_widths[i];
2441 /* Make sure there's room in the line buffer for the column; if not,
2442 double its length. */
2443 line_len += column_len + 1; /* "+1" for space */
2444 if (line_len > callback_args.header_line_buf_len) {
2445 cp_off = (int) (cp - callback_args.header_line_buf);
2446 callback_args.header_line_buf_len = 2 * line_len;
2447 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2448 callback_args.header_line_buf_len + 1);
2449 cp = callback_args.header_line_buf + cp_off;
2452 /* Right-justify the packet number column. */
2453 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2454 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2456 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2458 if (i != cf->cinfo.num_cols - 1)
2463 /* Now start out the main line buffer with the same length as the
2464 header line buffer. */
2465 callback_args.line_buf_len = callback_args.header_line_buf_len;
2466 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2467 } /* if (print_summary) */
2469 /* Iterate through the list of packets, printing the packets we were
2471 ret = process_specified_packets(cf, &print_args->range, "Printing",
2472 "selected packets", TRUE, print_packet,
2475 g_free(callback_args.header_line_buf);
2476 g_free(callback_args.line_buf);
2477 g_free(callback_args.col_widths);
2482 /* Completed successfully. */
2486 /* Well, the user decided to abort the printing.
2488 XXX - note that what got generated before they did that
2489 will get printed if we're piping to a print program; we'd
2490 have to write to a file and then hand that to the print
2491 program to make it actually not print anything. */
2495 /* Error while printing.
2497 XXX - note that what got generated before they did that
2498 will get printed if we're piping to a print program; we'd
2499 have to write to a file and then hand that to the print
2500 program to make it actually not print anything. */
2501 destroy_print_stream(print_args->stream);
2502 return CF_PRINT_WRITE_ERROR;
2505 if (!print_finale(print_args->stream)) {
2506 destroy_print_stream(print_args->stream);
2507 return CF_PRINT_WRITE_ERROR;
2510 if (!destroy_print_stream(print_args->stream))
2511 return CF_PRINT_WRITE_ERROR;
2517 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2518 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2524 /* Create the protocol tree, but don't fill in the column information. */
2525 epan_dissect_init(&edt, TRUE, TRUE);
2526 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2528 /* Write out the information in that tree. */
2529 proto_tree_write_pdml(&edt, fh);
2531 epan_dissect_cleanup(&edt);
2537 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2542 fh = ws_fopen(print_args->file, "w");
2544 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2546 write_pdml_preamble(fh);
2549 return CF_PRINT_WRITE_ERROR;
2552 /* Iterate through the list of packets, printing the packets we were
2554 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2555 "selected packets", TRUE,
2556 write_pdml_packet, fh);
2561 /* Completed successfully. */
2565 /* Well, the user decided to abort the printing. */
2569 /* Error while printing. */
2571 return CF_PRINT_WRITE_ERROR;
2574 write_pdml_finale(fh);
2577 return CF_PRINT_WRITE_ERROR;
2580 /* XXX - check for an error */
2587 write_psml_packet(capture_file *cf, frame_data *fdata,
2588 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2593 gboolean proto_tree_needed;
2595 /* Fill in the column information, only create the protocol tree
2596 if having custom columns. */
2597 proto_tree_needed = have_custom_cols(&cf->cinfo);
2598 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2599 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2600 epan_dissect_fill_in_columns(&edt, TRUE);
2602 /* Write out the information in that tree. */
2603 proto_tree_write_psml(&edt, fh);
2605 epan_dissect_cleanup(&edt);
2611 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2616 fh = ws_fopen(print_args->file, "w");
2618 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2620 write_psml_preamble(fh);
2623 return CF_PRINT_WRITE_ERROR;
2626 /* Iterate through the list of packets, printing the packets we were
2628 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2629 "selected packets", TRUE,
2630 write_psml_packet, fh);
2635 /* Completed successfully. */
2639 /* Well, the user decided to abort the printing. */
2643 /* Error while printing. */
2645 return CF_PRINT_WRITE_ERROR;
2648 write_psml_finale(fh);
2651 return CF_PRINT_WRITE_ERROR;
2654 /* XXX - check for an error */
2661 write_csv_packet(capture_file *cf, frame_data *fdata,
2662 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2667 gboolean proto_tree_needed;
2669 /* Fill in the column information, only create the protocol tree
2670 if having custom columns. */
2671 proto_tree_needed = have_custom_cols(&cf->cinfo);
2672 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2673 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2674 epan_dissect_fill_in_columns(&edt, TRUE);
2676 /* Write out the information in that tree. */
2677 proto_tree_write_csv(&edt, fh);
2679 epan_dissect_cleanup(&edt);
2685 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2690 fh = ws_fopen(print_args->file, "w");
2692 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2694 write_csv_preamble(fh);
2697 return CF_PRINT_WRITE_ERROR;
2700 /* Iterate through the list of packets, printing the packets we were
2702 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2703 "selected packets", TRUE,
2704 write_csv_packet, fh);
2709 /* Completed successfully. */
2713 /* Well, the user decided to abort the printing. */
2717 /* Error while printing. */
2719 return CF_PRINT_WRITE_ERROR;
2722 write_csv_finale(fh);
2725 return CF_PRINT_WRITE_ERROR;
2728 /* XXX - check for an error */
2735 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
2736 union wtap_pseudo_header *pseudo_header _U_,
2737 const guint8 *pd, void *argsp)
2741 proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh);
2746 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2751 fh = ws_fopen(print_args->file, "w");
2754 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2756 write_carrays_preamble(fh);
2760 return CF_PRINT_WRITE_ERROR;
2763 /* Iterate through the list of packets, printing the packets we were
2765 ret = process_specified_packets(cf, &print_args->range,
2767 "selected packets", TRUE,
2768 write_carrays_packet, fh);
2771 /* Completed successfully. */
2774 /* Well, the user decided to abort the printing. */
2777 /* Error while printing. */
2779 return CF_PRINT_WRITE_ERROR;
2782 write_carrays_finale(fh);
2786 return CF_PRINT_WRITE_ERROR;
2793 /* Scan through the packet list and change all columns that use the
2794 "command-line-specified" time stamp format to use the current
2795 value of that format. */
2797 cf_change_time_formats(capture_file *cf)
2800 progdlg_t *progbar = NULL;
2806 GTimeVal start_time;
2807 gchar status_str[100];
2808 int progbar_nextstep;
2809 int progbar_quantum;
2810 gboolean sorted_by_frame_column;
2813 /* adjust timestamp precision if auto is selected */
2814 cf_timestamp_auto_precision(cf);
2816 /* Are there any columns with time stamps in the "command-line-specified"
2819 XXX - we have to force the "column is writable" flag on, as it
2820 might be off from the last frame that was dissected. */
2821 col_set_writable(&cf->cinfo, TRUE);
2822 if (!check_col(&cf->cinfo, COL_CLS_TIME) &&
2823 !check_col(&cf->cinfo, COL_ABS_TIME) &&
2824 !check_col(&cf->cinfo, COL_ABS_DATE_TIME) &&
2825 !check_col(&cf->cinfo, COL_REL_TIME) &&
2826 !check_col(&cf->cinfo, COL_DELTA_TIME) &&
2827 !check_col(&cf->cinfo, COL_DELTA_TIME_DIS)) {
2828 /* No, there aren't any columns in that format, so we have no work
2833 /* Freeze the packet list while we redo it, so we don't get any
2834 screen updates while it happens. */
2835 #ifdef NEW_PACKET_LIST
2836 new_packet_list_freeze();
2838 packet_list_freeze();
2841 /* Update the progress bar when it gets to this value. */
2842 progbar_nextstep = 0;
2843 /* When we reach the value that triggers a progress bar update,
2844 bump that value by this amount. */
2845 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2846 /* Count of packets at which we've looked. */
2848 /* Progress so far. */
2851 /* If the rows are currently sorted by the frame column then we know
2852 * the row number of each packet: it's the row number of the previously
2853 * displayed packet + 1.
2855 * Otherwise, if the display is sorted by a different column then we have
2856 * to use the O(N) packet_list_find_row_from_data() (thus making the job
2857 * of changing the time display format O(N**2)).
2859 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
2860 * the row number and walks that many elements down the clist to find
2861 * the appropriate element.)
2863 sorted_by_frame_column = FALSE;
2864 for (i = 0; i < cf->cinfo.num_cols; i++) {
2865 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2867 #ifndef NEW_PACKET_LIST
2868 sorted_by_frame_column = (i == packet_list_get_sort_column());
2875 g_get_current_time(&start_time);
2877 /* Iterate through the list of packets, checking whether the packet
2878 is in a row of the summary list and, if so, whether there are
2879 any columns that show the time in the "command-line-specified"
2880 format and, if so, update that row. */
2881 for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
2882 /* Create the progress bar if necessary.
2883 We check on every iteration of the loop, so that it takes no
2884 longer than the standard time to create it (otherwise, for a
2885 large file, we might take considerably longer than that standard
2886 time in order to get to the next progress bar step). */
2887 if (progbar == NULL)
2888 progbar = delayed_create_progress_dlg("Changing", "time display",
2889 TRUE, &stop_flag, &start_time, progbar_val);
2891 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2892 when we update it, we have to run the GTK+ main loop to get it
2893 to repaint what's pending, and doing so may involve an "ioctl()"
2894 to see if there's any pending input from an X server, and doing
2895 that for every packet can be costly, especially on a big file. */
2896 if (count >= progbar_nextstep) {
2897 /* let's not divide by zero. I should never be started
2898 * with count == 0, so let's assert that
2900 g_assert(cf->count > 0);
2902 progbar_val = (gfloat) count / cf->count;
2904 if (progbar != NULL) {
2905 g_snprintf(status_str, sizeof(status_str),
2906 "%4u of %u packets", count, cf->count);
2907 update_progress_dlg(progbar, progbar_val, status_str);
2910 progbar_nextstep += progbar_quantum;
2914 /* Well, the user decided to abort the redisplay. Just stop.
2916 XXX - this leaves the time field in the old format in
2917 frames we haven't yet processed. So it goes; should we
2918 simply not offer them the option of stopping? */
2924 /* Find what row this packet is in. */
2925 if (!sorted_by_frame_column) {
2926 /* This function is O(N), so we try to avoid using it... */
2927 #ifdef NEW_PACKET_LIST
2928 row = new_packet_list_find_row_from_data(fdata, FALSE);
2930 row = packet_list_find_row_from_data(fdata);
2933 /* ...which we do by maintaining a count of packets that are
2934 being displayed (i.e., that have passed the display filter),
2935 and using the current value of that count as the row number
2936 (which is why we can only do it when the display is sorted
2937 by the frame number). */
2938 if (fdata->flags.passed_dfilter)
2945 /* This packet is in the summary list, on row "row". */
2947 for (i = 0; i < cf->cinfo.num_cols; i++) {
2948 if (col_has_time_fmt(&cf->cinfo, i)) {
2949 /* This is one of the columns that shows the time in
2950 "command-line-specified" format; update it. */
2951 cf->cinfo.col_buf[i][0] = '\0';
2952 col_set_fmt_time(fdata, &cf->cinfo, cf->cinfo.col_fmt[i], i);
2953 #ifdef NEW_PACKET_LIST
2955 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
2962 /* We're done redisplaying the packets; destroy the progress bar if it
2964 if (progbar != NULL)
2965 destroy_progress_dlg(progbar);
2967 /* Set the column widths of those columns that show the time in
2968 "command-line-specified" format. */
2969 for (i = 0; i < cf->cinfo.num_cols; i++) {
2970 if (col_has_time_fmt(&cf->cinfo, i)) {
2971 #ifndef NEW_PACKET_LIST
2972 packet_list_set_time_width(cf->cinfo.col_fmt[i], i);
2977 /* Unfreeze the packet list. */
2978 #ifdef NEW_PACKET_LIST
2979 new_packet_list_thaw();
2989 gboolean frame_matched;
2993 cf_find_packet_protocol_tree(capture_file *cf, const char *string)
2997 mdata.string = string;
2998 mdata.string_len = strlen(string);
2999 return find_packet(cf, match_protocol_tree, &mdata);
3003 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
3005 match_data *mdata = criterion;
3008 /* Construct the protocol tree, including the displayed text */
3009 epan_dissect_init(&edt, TRUE, TRUE);
3010 /* We don't need the column information */
3011 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3013 /* Iterate through all the nodes, seeing if they have text that matches. */
3015 mdata->frame_matched = FALSE;
3016 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
3017 epan_dissect_cleanup(&edt);
3018 return mdata->frame_matched;
3022 match_subtree_text(proto_node *node, gpointer data)
3024 match_data *mdata = (match_data*) data;
3025 const gchar *string = mdata->string;
3026 size_t string_len = mdata->string_len;
3027 capture_file *cf = mdata->cf;
3028 field_info *fi = PNODE_FINFO(node);
3029 gchar label_str[ITEM_LABEL_LENGTH];
3036 g_assert(fi && "dissection with an invisible proto tree?");
3038 if (mdata->frame_matched) {
3039 /* We already had a match; don't bother doing any more work. */
3043 /* Don't match invisible entries. */
3044 if (PROTO_ITEM_IS_HIDDEN(node))
3047 /* was a free format label produced? */
3049 label_ptr = fi->rep->representation;
3051 /* no, make a generic label */
3052 label_ptr = label_str;
3053 proto_item_fill_label(fi, label_str);
3056 /* Does that label match? */
3057 label_len = strlen(label_ptr);
3058 for (i = 0; i < label_len; i++) {
3059 c_char = label_ptr[i];
3061 c_char = toupper(c_char);
3062 if (c_char == string[c_match]) {
3064 if (c_match == string_len) {
3065 /* No need to look further; we have a match */
3066 mdata->frame_matched = TRUE;
3073 /* Recurse into the subtree, if it exists */
3074 if (node->first_child != NULL)
3075 proto_tree_children_foreach(node, match_subtree_text, mdata);
3079 cf_find_packet_summary_line(capture_file *cf, const char *string)
3083 mdata.string = string;
3084 mdata.string_len = strlen(string);
3085 return find_packet(cf, match_summary_line, &mdata);
3089 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3091 match_data *mdata = criterion;
3092 const gchar *string = mdata->string;
3093 size_t string_len = mdata->string_len;
3095 const char *info_column;
3096 size_t info_column_len;
3097 gboolean frame_matched = FALSE;
3103 /* Don't bother constructing the protocol tree */
3104 epan_dissect_init(&edt, FALSE, FALSE);
3105 /* Get the column information */
3106 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
3108 /* Find the Info column */
3109 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3110 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
3111 /* Found it. See if we match. */
3112 info_column = edt.pi.cinfo->col_data[colx];
3113 info_column_len = strlen(info_column);
3114 for (i = 0; i < info_column_len; i++) {
3115 c_char = info_column[i];
3117 c_char = toupper(c_char);
3118 if (c_char == string[c_match]) {
3120 if (c_match == string_len) {
3121 frame_matched = TRUE;
3130 epan_dissect_cleanup(&edt);
3131 return frame_matched;
3137 } cbs_t; /* "Counted byte string" */
3140 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
3145 info.data_len = string_size;
3147 /* String or hex search? */
3149 /* String search - what type of string? */
3150 switch (cf->scs_type) {
3152 case SCS_ASCII_AND_UNICODE:
3153 return find_packet(cf, match_ascii_and_unicode, &info);
3156 return find_packet(cf, match_ascii, &info);
3159 return find_packet(cf, match_unicode, &info);
3162 g_assert_not_reached();
3166 return find_packet(cf, match_binary, &info);
3170 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3172 cbs_t *info = criterion;
3173 const guint8 *ascii_text = info->data;
3174 size_t textlen = info->data_len;
3175 gboolean frame_matched;
3181 frame_matched = FALSE;
3182 buf_len = fdata->pkt_len;
3183 for (i = 0; i < buf_len; i++) {
3186 c_char = toupper(c_char);
3188 if (c_char == ascii_text[c_match]) {
3190 if (c_match == textlen) {
3191 frame_matched = TRUE;
3192 cf->search_pos = i; /* Save the position of the last character
3193 for highlighting the field. */
3200 return frame_matched;
3204 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
3206 cbs_t *info = criterion;
3207 const guint8 *ascii_text = info->data;
3208 size_t textlen = info->data_len;
3209 gboolean frame_matched;
3215 frame_matched = FALSE;
3216 buf_len = fdata->pkt_len;
3217 for (i = 0; i < buf_len; i++) {
3220 c_char = toupper(c_char);
3221 if (c_char == ascii_text[c_match]) {
3223 if (c_match == textlen) {
3224 frame_matched = TRUE;
3225 cf->search_pos = i; /* Save the position of the last character
3226 for highlighting the field. */
3232 return frame_matched;
3236 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3238 cbs_t *info = criterion;
3239 const guint8 *ascii_text = info->data;
3240 size_t textlen = info->data_len;
3241 gboolean frame_matched;
3247 frame_matched = FALSE;
3248 buf_len = fdata->pkt_len;
3249 for (i = 0; i < buf_len; i++) {
3252 c_char = toupper(c_char);
3253 if (c_char == ascii_text[c_match]) {
3256 if (c_match == textlen) {
3257 frame_matched = TRUE;
3258 cf->search_pos = i; /* Save the position of the last character
3259 for highlighting the field. */
3265 return frame_matched;
3269 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3271 cbs_t *info = criterion;
3272 const guint8 *binary_data = info->data;
3273 size_t datalen = info->data_len;
3274 gboolean frame_matched;
3279 frame_matched = FALSE;
3280 buf_len = fdata->pkt_len;
3281 for (i = 0; i < buf_len; i++) {
3282 if (cf->pd[i] == binary_data[c_match]) {
3284 if (c_match == datalen) {
3285 frame_matched = TRUE;
3286 cf->search_pos = i; /* Save the position of the last character
3287 for highlighting the field. */
3293 return frame_matched;
3297 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
3299 return find_packet(cf, match_dfilter, sfcode);
3303 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3305 dfilter_t *sfcode = criterion;
3307 gboolean frame_matched;
3309 epan_dissect_init(&edt, TRUE, FALSE);
3310 epan_dissect_prime_dfilter(&edt, sfcode);
3311 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3312 frame_matched = dfilter_apply_edt(sfcode, &edt);
3313 epan_dissect_cleanup(&edt);
3314 return frame_matched;
3318 find_packet(capture_file *cf,
3319 gboolean (*match_function)(capture_file *, frame_data *, void *),
3322 frame_data *start_fd;
3324 frame_data *new_fd = NULL;
3325 progdlg_t *progbar = NULL;
3332 GTimeVal start_time;
3333 gchar status_str[100];
3334 int progbar_nextstep;
3335 int progbar_quantum;
3338 start_fd = cf->current_frame;
3339 if (start_fd != NULL) {
3340 /* Iterate through the list of packets, starting at the packet we've
3341 picked, calling a routine to run the filter on the packet, see if
3342 it matches, and stop if so. */
3346 /* Update the progress bar when it gets to this value. */
3347 progbar_nextstep = 0;
3348 /* When we reach the value that triggers a progress bar update,
3349 bump that value by this amount. */
3350 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3351 /* Progress so far. */
3355 g_get_current_time(&start_time);
3358 title = cf->sfilter?cf->sfilter:"";
3360 /* Create the progress bar if necessary.
3361 We check on every iteration of the loop, so that it takes no
3362 longer than the standard time to create it (otherwise, for a
3363 large file, we might take considerably longer than that standard
3364 time in order to get to the next progress bar step). */
3365 if (progbar == NULL)
3366 progbar = delayed_create_progress_dlg("Searching", title,
3367 FALSE, &stop_flag, &start_time, progbar_val);
3369 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3370 when we update it, we have to run the GTK+ main loop to get it
3371 to repaint what's pending, and doing so may involve an "ioctl()"
3372 to see if there's any pending input from an X server, and doing
3373 that for every packet can be costly, especially on a big file. */
3374 if (count >= progbar_nextstep) {
3375 /* let's not divide by zero. I should never be started
3376 * with count == 0, so let's assert that
3378 g_assert(cf->count > 0);
3380 progbar_val = (gfloat) count / cf->count;
3382 if (progbar != NULL) {
3383 g_snprintf(status_str, sizeof(status_str),
3384 "%4u of %u packets", count, cf->count);
3385 update_progress_dlg(progbar, progbar_val, status_str);
3388 progbar_nextstep += progbar_quantum;
3392 /* Well, the user decided to abort the search. Go back to the
3393 frame where we started. */
3398 /* Go past the current frame. */
3399 if (cf->sbackward) {
3400 /* Go on to the previous frame. */
3401 fdata = fdata->prev;
3402 if (fdata == NULL) {
3404 * XXX - other apps have a bit more of a detailed message
3405 * for this, and instead of offering "OK" and "Cancel",
3406 * they offer things such as "Continue" and "Cancel";
3407 * we need an API for popping up alert boxes with
3408 * {Verb} and "Cancel".
3411 if (prefs.gui_find_wrap)
3413 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3414 "%sBeginning of capture exceeded!%s\n\n"
3415 "Search is continued from the end of the capture.",
3416 simple_dialog_primary_start(), simple_dialog_primary_end());
3417 fdata = cf->plist_end; /* wrap around */
3421 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3422 "%sBeginning of capture exceeded!%s\n\n"
3423 "Try searching forwards.",
3424 simple_dialog_primary_start(), simple_dialog_primary_end());
3425 fdata = start_fd; /* stay on previous packet */
3429 /* Go on to the next frame. */
3430 fdata = fdata->next;
3431 if (fdata == NULL) {
3432 if (prefs.gui_find_wrap)
3434 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3435 "%sEnd of capture exceeded!%s\n\n"
3436 "Search is continued from the start of the capture.",
3437 simple_dialog_primary_start(), simple_dialog_primary_end());
3438 fdata = cf->plist; /* wrap around */
3442 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3443 "%sEnd of capture exceeded!%s\n\n"
3444 "Try searching backwards.",
3445 simple_dialog_primary_start(), simple_dialog_primary_end());
3446 fdata = start_fd; /* stay on previous packet */
3453 /* Is this packet in the display? */
3454 if (fdata->flags.passed_dfilter) {
3455 /* Yes. Load its data. */
3456 if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
3457 cf->pd, fdata->cap_len, &err, &err_info)) {
3458 /* Read error. Report the error, and go back to the frame
3459 where we started. */
3460 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3461 cf_read_error_message(err, err_info), cf->filename);
3466 /* Does it match the search criterion? */
3467 if ((*match_function)(cf, fdata, criterion)) {
3469 break; /* found it! */
3473 if (fdata == start_fd) {
3474 /* We're back to the frame we were on originally, and that frame
3475 doesn't match the search filter. The search failed. */
3480 /* We're done scanning the packets; destroy the progress bar if it
3482 if (progbar != NULL)
3483 destroy_progress_dlg(progbar);
3486 if (new_fd != NULL) {
3487 #ifdef NEW_PACKET_LIST
3488 /* Find and select */
3489 row = new_packet_list_find_row_from_data(fdata, TRUE);
3491 /* We found a frame. Find what row it's in. */
3492 row = packet_list_find_row_from_data(new_fd);
3493 #endif /* NEW_PACKET_LIST */
3495 /* We didn't find a row even though we know that a frame
3496 * exists that satifies the search criteria. This means that the
3497 * frame isn't being displayed currently so we can't select it. */
3498 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3499 "%sEnd of capture exceeded!%s\n\n"
3500 "The capture file is probably not fully loaded.",
3501 simple_dialog_primary_start(), simple_dialog_primary_end());
3505 #ifndef NEW_PACKET_LIST
3506 /* Select that row, make it the focus row, and make it visible. */
3507 packet_list_set_selected_row(row);
3508 #endif /* NEW_PACKET_LIST */
3509 return TRUE; /* success */
3511 return FALSE; /* failure */
3515 cf_goto_frame(capture_file *cf, guint fnumber)
3520 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
3523 if (fdata == NULL) {
3524 /* we didn't find a packet with that packet number */
3525 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3526 "There is no packet with the packet number %u.", fnumber);
3527 return FALSE; /* we failed to go to that packet */
3529 if (!fdata->flags.passed_dfilter) {
3530 /* that packet currently isn't displayed */
3531 /* XXX - add it to the set of displayed packets? */
3532 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3533 "The packet number %u isn't currently being displayed.", fnumber);
3534 return FALSE; /* we failed to go to that packet */
3537 #ifdef NEW_PACKET_LIST
3538 row = new_packet_list_find_row_from_data(fdata, TRUE);
3540 /* We found that packet, and it's currently being displayed.
3541 Find what row it's in. */
3542 row = packet_list_find_row_from_data(fdata);
3543 g_assert(row != -1);
3545 /* Select that row, make it the focus row, and make it visible. */
3546 packet_list_set_selected_row(row);
3547 #endif /* NEW_PACKET_LIST */
3548 return TRUE; /* we got to that packet */
3552 cf_goto_top_frame(capture_file *cf _U_)
3554 #ifdef NEW_PACKET_LIST
3555 /* Find and select */
3556 new_packet_list_select_first_row();
3560 frame_data *lowest_fdata = NULL;
3562 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
3563 if (fdata->flags.passed_dfilter) {
3564 lowest_fdata = fdata;
3569 if (lowest_fdata == NULL) {
3573 /* We found that packet, and it's currently being displayed.
3574 Find what row it's in. */
3575 row = packet_list_find_row_from_data(lowest_fdata);
3576 g_assert(row != -1);
3578 /* Select that row, make it the focus row, and make it visible. */
3579 packet_list_set_selected_row(row);
3580 #endif /* NEW_PACKET_LIST */
3581 return TRUE; /* we got to that packet */
3585 cf_goto_bottom_frame(capture_file *cf _U_) /* cf is unused w/ NEW_PACKET_LIST */
3587 #ifdef NEW_PACKET_LIST
3588 /* Find and select */
3589 new_packet_list_select_last_row();
3593 frame_data *highest_fdata = NULL;
3595 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
3596 if (fdata->flags.passed_dfilter) {
3597 highest_fdata = fdata;
3601 if (highest_fdata == NULL) {
3605 /* We found that packet, and it's currently being displayed.
3606 Find what row it's in. */
3607 row = packet_list_find_row_from_data(highest_fdata);
3608 g_assert(row != -1);
3610 /* Select that row, make it the focus row, and make it visible. */
3611 packet_list_set_selected_row(row);
3612 #endif /* NEW_PACKET_LIST */
3613 return TRUE; /* we got to that packet */
3617 * Go to frame specified by currently selected protocol tree item.
3620 cf_goto_framenum(capture_file *cf)
3622 header_field_info *hfinfo;
3625 if (cf->finfo_selected) {
3626 hfinfo = cf->finfo_selected->hfinfo;
3628 if (hfinfo->type == FT_FRAMENUM) {
3629 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3631 return cf_goto_frame(cf, framenum);
3638 /* Select the packet on a given row. */
3640 cf_select_packet(capture_file *cf, int row)
3646 /* Get the frame data struct pointer for this frame */
3647 #ifdef NEW_PACKET_LIST
3648 fdata = new_packet_list_get_row_data(row);
3650 fdata = (frame_data *)packet_list_get_row_data(row);
3653 if (fdata == NULL) {
3654 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3655 the first entry is added to it by "real_insert_row()", that row
3656 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3657 our version and the vanilla GTK+ version).
3659 This means that a "select-row" signal is emitted; this causes
3660 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3663 "cf_select_packet()" fetches, above, the data associated with the
3664 row that was selected; however, as "gtk_clist_append()", which
3665 called "real_insert_row()", hasn't yet returned, we haven't yet
3666 associated any data with that row, so we get back a null pointer.
3668 We can't assume that there's only one frame in the frame list,
3669 either, as we may be filtering the display.
3671 We therefore assume that, if "row" is 0, i.e. the first row
3672 is being selected, and "cf->first_displayed" equals
3673 "cf->last_displayed", i.e. there's only one frame being
3674 displayed, that frame is the frame we want.
3676 This means we have to set "cf->first_displayed" and
3677 "cf->last_displayed" before adding the row to the
3678 GtkCList; see the comment in "add_packet_to_packet_list()". */
3680 if (row == 0 && cf->first_displayed == cf->last_displayed)
3681 fdata = cf->first_displayed;
3684 /* If fdata _still_ isn't set simply give up. */
3685 if (fdata == NULL) {
3689 /* Get the data in that frame. */
3690 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
3691 cf->pd, fdata->cap_len, &err, &err_info)) {
3692 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3693 cf_read_error_message(err, err_info), cf->filename);
3697 /* Record that this frame is the current frame. */
3698 cf->current_frame = fdata;
3699 cf->current_row = row;
3701 /* Create the logical protocol tree. */
3702 if (cf->edt != NULL) {
3703 epan_dissect_free(cf->edt);
3706 /* We don't need the columns here. */
3707 cf->edt = epan_dissect_new(TRUE, TRUE);
3709 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3712 dfilter_macro_build_ftv_cache(cf->edt->tree);
3714 cf_callback_invoke(cf_cb_packet_selected, cf);
3717 /* Unselect the selected packet, if any. */
3719 cf_unselect_packet(capture_file *cf)
3721 /* Destroy the epan_dissect_t for the unselected packet. */
3722 if (cf->edt != NULL) {
3723 epan_dissect_free(cf->edt);
3727 /* No packet is selected. */
3728 cf->current_frame = NULL;
3729 cf->current_row = 0;
3731 cf_callback_invoke(cf_cb_packet_unselected, cf);
3733 /* No protocol tree means no selected field. */
3734 cf_unselect_field(cf);
3737 /* Unset the selected protocol tree field, if any. */
3739 cf_unselect_field(capture_file *cf)
3741 cf->finfo_selected = NULL;
3743 cf_callback_invoke(cf_cb_field_unselected, cf);
3747 * Mark a particular frame.
3750 cf_mark_frame(capture_file *cf, frame_data *frame)
3752 if (! frame->flags.marked) {
3753 frame->flags.marked = TRUE;
3754 if (cf->count > cf->marked_count)
3760 * Unmark a particular frame.
3763 cf_unmark_frame(capture_file *cf, frame_data *frame)
3765 if (frame->flags.marked) {
3766 frame->flags.marked = FALSE;
3767 if (cf->marked_count > 0)
3775 } save_callback_args_t;
3778 * Save a capture to a file, in a particular format, saving either
3779 * all packets, all currently-displayed packets, or all marked packets.
3781 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3782 * up a message box for the failure.
3785 save_packet(capture_file *cf _U_, frame_data *fdata,
3786 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3789 save_callback_args_t *args = argsp;
3790 struct wtap_pkthdr hdr;
3793 /* init the wtap header for saving */
3794 hdr.ts.secs = fdata->abs_ts.secs;
3795 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3796 hdr.caplen = fdata->cap_len;
3797 hdr.len = fdata->pkt_len;
3798 hdr.pkt_encap = fdata->lnk_t;
3800 /* and save the packet */
3801 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3802 cf_write_failure_alert_box(args->fname, err);
3809 * Can this capture file be saved in any format except by copying the raw data?
3812 cf_can_save_as(capture_file *cf)
3816 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
3817 /* To save a file with Wiretap, Wiretap has to handle that format,
3818 and its code to handle that format must be able to write a file
3819 with this file's encapsulation type. */
3820 if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
3821 /* OK, we can write it out in this type. */
3826 /* No, we couldn't save it in any format. */
3831 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3833 gchar *from_filename;
3837 save_callback_args_t callback_args;
3839 cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname);
3841 /* don't write over an existing file. */
3842 /* this should've been already checked by our caller, just to be sure... */
3843 if (file_exists(fname)) {
3844 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3845 "%sCapture file: \"%s\" already exists!%s\n\n"
3846 "Please choose a different filename.",
3847 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3851 packet_range_process_init(range);
3854 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3855 /* We're not filtering packets, and we're saving it in the format
3856 it's already in, so we can just move or copy the raw data. */
3858 if (cf->is_tempfile) {
3859 /* The file being saved is a temporary file from a live
3860 capture, so it doesn't need to stay around under that name;
3861 first, try renaming the capture buffer file to the new name. */
3863 if (ws_rename(cf->filename, fname) == 0) {
3864 /* That succeeded - there's no need to copy the source file. */
3865 from_filename = NULL;
3868 if (errno == EXDEV) {
3869 /* They're on different file systems, so we have to copy the
3872 from_filename = cf->filename;
3874 /* The rename failed, but not because they're on different
3875 file systems - put up an error message. (Or should we
3876 just punt and try to copy? The only reason why I'd
3877 expect the rename to fail and the copy to succeed would
3878 be if we didn't have permission to remove the file from
3879 the temporary directory, and that might be fixable - but
3880 is it worth requiring the user to go off and fix it?) */
3881 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3882 file_rename_error_message(errno), fname);
3888 from_filename = cf->filename;
3891 /* It's a permanent file, so we should copy it, and not remove the
3894 from_filename = cf->filename;
3898 /* Copy the file, if we haven't moved it. */
3899 if (!copy_file_binary_mode(from_filename, fname))
3903 /* Either we're filtering packets, or we're saving in a different
3904 format; we can't do that by copying or moving the capture file,
3905 we have to do it by writing the packets out in Wiretap. */
3906 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3909 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3913 /* XXX - we let the user save a subset of the packets.
3915 If we do that, should we make that file the current file? If so,
3916 it means we can no longer get at the other packets. What does
3919 /* Iterate through the list of packets, processing the packets we were
3922 XXX - we've already called "packet_range_process_init(range)", but
3923 "process_specified_packets()" will do it again. Fortunately,
3924 that's harmless in this case, as we haven't done anything to
3925 "range" since we initialized it. */
3926 callback_args.pdh = pdh;
3927 callback_args.fname = fname;
3928 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3929 TRUE, save_packet, &callback_args)) {
3932 /* Completed successfully. */
3936 /* The user decided to abort the saving.
3937 XXX - remove the output file? */
3941 /* Error while saving. */
3942 wtap_dump_close(pdh, &err);
3946 if (!wtap_dump_close(pdh, &err)) {
3947 cf_close_failure_alert_box(fname, err);
3952 cf_callback_invoke(cf_cb_file_safe_finished, NULL);
3954 if (packet_range_process_all(range)) {
3955 /* We saved the entire capture, not just some packets from it.
3956 Open and read the file we saved it to.
3958 XXX - this is somewhat of a waste; we already have the
3959 packets, all this gets us is updated file type information
3960 (which we could just stuff into "cf"), and having the new
3961 file be the one we have opened and from which we're reading
3962 the data, and it means we have to spend time opening and
3963 reading the file, which could be a significant amount of
3964 time if the file is large. */
3965 cf->user_saved = TRUE;
3967 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3968 /* XXX - report errors if this fails?
3969 What should we return if it fails or is aborted? */
3970 switch (cf_read(cf)) {
3974 /* Just because we got an error, that doesn't mean we were unable
3975 to read any of the file; we handle what we could get from the
3979 case CF_READ_ABORTED:
3980 /* The user bailed out of re-reading the capture file; the
3981 capture file has been closed - just return (without
3982 changing any menu settings; "cf_close()" set them
3983 correctly for the "no capture file open" state). */
3986 cf_callback_invoke(cf_cb_file_safe_reload_finished, NULL);
3992 cf_callback_invoke(cf_cb_file_safe_failed, NULL);
3997 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3998 gboolean for_writing, int file_type)
4001 /* Wiretap error. */
4004 case WTAP_ERR_NOT_REGULAR_FILE:
4005 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4006 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4010 case WTAP_ERR_RANDOM_OPEN_PIPE:
4011 /* Seen only when opening a capture file for reading. */
4012 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4013 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
4017 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
4018 /* Seen only when opening a capture file for reading. */
4019 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4020 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
4024 case WTAP_ERR_UNSUPPORTED:
4025 /* Seen only when opening a capture file for reading. */
4026 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4027 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
4029 filename, err_info);
4033 case WTAP_ERR_CANT_WRITE_TO_PIPE:
4034 /* Seen only when opening a capture file for writing. */
4035 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4036 "The file \"%s\" is a pipe, and %s capture files can't be "
4037 "written to a pipe.",
4038 filename, wtap_file_type_string(file_type));
4041 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
4042 /* Seen only when opening a capture file for writing. */
4043 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4044 "Wireshark doesn't support writing capture files in that format.");
4047 case WTAP_ERR_UNSUPPORTED_ENCAP:
4049 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4050 "Wireshark can't save this capture in that format.");
4052 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4053 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
4055 filename, err_info);
4060 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
4062 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4063 "Wireshark can't save this capture in that format.");
4065 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4066 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
4071 case WTAP_ERR_BAD_RECORD:
4072 /* Seen only when opening a capture file for reading. */
4073 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4074 "The file \"%s\" appears to be damaged or corrupt.\n"
4076 filename, err_info);
4080 case WTAP_ERR_CANT_OPEN:
4082 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4083 "The file \"%s\" could not be created for some unknown reason.",
4086 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4087 "The file \"%s\" could not be opened for some unknown reason.",
4092 case WTAP_ERR_SHORT_READ:
4093 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4094 "The file \"%s\" appears to have been cut short"
4095 " in the middle of a packet or other data.",
4099 case WTAP_ERR_SHORT_WRITE:
4100 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4101 "A full header couldn't be written to the file \"%s\".",
4105 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4106 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4107 "Gzip compression not supported by this file type.");
4111 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4112 "The file \"%s\" could not be %s: %s.",
4114 for_writing ? "created" : "opened",
4115 wtap_strerror(err));
4120 open_failure_alert_box(filename, err, for_writing);
4125 file_rename_error_message(int err)
4128 static char errmsg_errno[1024+1];
4133 errmsg = "The path to the file \"%s\" doesn't exist.";
4137 errmsg = "You don't have permission to move the capture file to \"%s\".";
4141 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4142 "The file \"%%s\" could not be moved: %s.",
4143 wtap_strerror(err));
4144 errmsg = errmsg_errno;
4151 cf_read_error_message(int err, gchar *err_info)
4153 static char errmsg_errno[1024+1];
4157 case WTAP_ERR_UNSUPPORTED_ENCAP:
4158 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4159 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
4164 case WTAP_ERR_BAD_RECORD:
4165 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4166 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
4167 wtap_strerror(err), err_info);
4172 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4173 "An error occurred while reading from the file \"%%s\": %s.",
4174 wtap_strerror(err));
4177 return errmsg_errno;
4181 cf_write_failure_alert_box(const char *filename, int err)
4184 /* Wiretap error. */
4185 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4186 "An error occurred while writing to the file \"%s\": %s.",
4187 filename, wtap_strerror(err));
4190 write_failure_alert_box(filename, err);
4194 /* Check for write errors - if the file is being written to an NFS server,
4195 a write error may not show up until the file is closed, as NFS clients
4196 might not send writes to the server until the "write()" call finishes,
4197 so that the write may fail on the server but the "write()" may succeed. */
4199 cf_close_failure_alert_box(const char *filename, int err)
4202 /* Wiretap error. */
4205 case WTAP_ERR_CANT_CLOSE:
4206 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4207 "The file \"%s\" couldn't be closed for some unknown reason.",
4211 case WTAP_ERR_SHORT_WRITE:
4212 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4213 "Not all the packets could be written to the file \"%s\".",
4218 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4219 "An error occurred while closing the file \"%s\": %s.",
4220 filename, wtap_strerror(err));
4225 We assume that a close error from the OS is really a write error. */
4226 write_failure_alert_box(filename, err);
4230 /* Reload the current capture file. */
4232 cf_reload(capture_file *cf) {
4234 gboolean is_tempfile;
4237 /* If the file could be opened, "cf_open()" calls "cf_close()"
4238 to get rid of state for the old capture file before filling in state
4239 for the new capture file. "cf_close()" will remove the file if
4240 it's a temporary file; we don't want that to happen (for one thing,
4241 it'd prevent subsequent reopens from working). Remember whether it's
4242 a temporary file, mark it as not being a temporary file, and then
4243 reopen it as the type of file it was.
4245 Also, "cf_close()" will free "cf->filename", so we must make
4246 a copy of it first. */
4247 filename = g_strdup(cf->filename);
4248 is_tempfile = cf->is_tempfile;
4249 cf->is_tempfile = FALSE;
4250 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4251 switch (cf_read(cf)) {
4255 /* Just because we got an error, that doesn't mean we were unable
4256 to read any of the file; we handle what we could get from the
4260 case CF_READ_ABORTED:
4261 /* The user bailed out of re-reading the capture file; the
4262 capture file has been closed - just free the capture file name
4263 string and return (without changing the last containing
4269 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4270 Instead, the file was left open, so we should restore "cf->is_tempfile"
4273 XXX - change the menu? Presumably "cf_open()" will do that;
4274 make sure it does! */
4275 cf->is_tempfile = is_tempfile;
4277 /* "cf_open()" made a copy of the file name we handed it, so
4278 we should free up our copy. */