6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #include <epan/epan.h>
47 #include <epan/filesystem.h>
50 #include "color_filters.h"
52 #include <epan/column.h>
53 #include <epan/packet.h>
54 #include <epan/column-utils.h>
55 #include "packet-range.h"
61 #include "alert_box.h"
62 #include "simple_dialog.h"
63 #include "main_statusbar.h"
64 #include "progress_dlg.h"
66 #include <epan/prefs.h>
67 #include <epan/dfilter/dfilter.h>
68 #include <epan/epan_dissect.h>
70 #include <epan/dissectors/packet-data.h>
71 #include <epan/dissectors/packet-ber.h>
72 #include <epan/timestamp.h>
73 #include <epan/dfilter/dfilter-macro.h>
74 #include <wsutil/file_util.h>
75 #include <epan/strutil.h>
76 #include <epan/addr_resolv.h>
79 gboolean auto_scroll_live;
82 static guint32 cum_bytes;
83 static nstime_t first_ts;
84 static nstime_t prev_dis_ts;
85 static nstime_t prev_cap_ts;
87 static gulong computed_elapsed;
89 static void cf_reset_state(capture_file *cf);
91 static int read_packet(capture_file *cf, dfilter_t *dfcode,
92 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset);
94 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
95 gboolean refilter, gboolean redissect);
102 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
104 static void match_subtree_text(proto_node *node, gpointer data);
105 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
107 static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
109 static match_result match_ascii(capture_file *cf, frame_data *fdata,
111 static match_result match_unicode(capture_file *cf, frame_data *fdata,
113 static match_result match_binary(capture_file *cf, frame_data *fdata,
115 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
117 static match_result match_marked(capture_file *cf, frame_data *fdata,
119 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
121 static gboolean find_packet(capture_file *cf,
122 match_result (*match_function)(capture_file *, frame_data *, void *),
123 void *criterion, search_direction dir);
125 static void cf_open_failure_alert_box(const char *filename, int err,
126 gchar *err_info, gboolean for_writing,
128 static const char *file_rename_error_message(int err);
129 static void cf_write_failure_alert_box(const char *filename, int err);
130 static void cf_close_failure_alert_box(const char *filename, int err);
131 static void ref_time_packets(capture_file *cf);
132 /* Update the progress bar this many times when reading a file. */
133 #define N_PROGBAR_UPDATES 100
134 /* We read around 200k/100ms don't update the progress bar more often than that */
135 #define MIN_QUANTUM 200000
136 #define MIN_NUMBER_OF_PACKET 1500
138 /* Number of "frame_data" structures per memory chunk.
139 XXX - is this the right number? */
140 #define FRAME_DATA_CHUNK_SIZE 1024
144 * We could probably use g_signal_...() instead of the callbacks below but that
145 * would require linking our CLI programs to libgobject and creating an object
146 * instance for the signals.
149 cf_callback_t cb_fct;
151 } cf_callback_data_t;
153 static GList *cf_callbacks = NULL;
156 cf_callback_invoke(int event, gpointer data)
158 cf_callback_data_t *cb;
159 GList *cb_item = cf_callbacks;
161 /* there should be at least one interested */
162 g_assert(cb_item != NULL);
164 while(cb_item != NULL) {
166 cb->cb_fct(event, data, cb->user_data);
167 cb_item = g_list_next(cb_item);
173 cf_callback_add(cf_callback_t func, gpointer user_data)
175 cf_callback_data_t *cb;
177 cb = g_malloc(sizeof(cf_callback_data_t));
179 cb->user_data = user_data;
181 cf_callbacks = g_list_append(cf_callbacks, cb);
185 cf_callback_remove(cf_callback_t func)
187 cf_callback_data_t *cb;
188 GList *cb_item = cf_callbacks;
190 while(cb_item != NULL) {
192 if(cb->cb_fct == func) {
193 cf_callbacks = g_list_remove(cf_callbacks, cb);
197 cb_item = g_list_next(cb_item);
200 g_assert_not_reached();
204 cf_timestamp_auto_precision(capture_file *cf)
207 int prec = timestamp_get_precision();
210 /* don't try to get the file's precision if none is opened */
211 if(cf->state == FILE_CLOSED) {
215 /* if we are in auto mode, set precision of current file */
216 if(prec == TS_PREC_AUTO ||
217 prec == TS_PREC_AUTO_SEC ||
218 prec == TS_PREC_AUTO_DSEC ||
219 prec == TS_PREC_AUTO_CSEC ||
220 prec == TS_PREC_AUTO_MSEC ||
221 prec == TS_PREC_AUTO_USEC ||
222 prec == TS_PREC_AUTO_NSEC)
224 switch(wtap_file_tsprecision(cf->wth)) {
225 case(WTAP_FILE_TSPREC_SEC):
226 timestamp_set_precision(TS_PREC_AUTO_SEC);
228 case(WTAP_FILE_TSPREC_DSEC):
229 timestamp_set_precision(TS_PREC_AUTO_DSEC);
231 case(WTAP_FILE_TSPREC_CSEC):
232 timestamp_set_precision(TS_PREC_AUTO_CSEC);
234 case(WTAP_FILE_TSPREC_MSEC):
235 timestamp_set_precision(TS_PREC_AUTO_MSEC);
237 case(WTAP_FILE_TSPREC_USEC):
238 timestamp_set_precision(TS_PREC_AUTO_USEC);
240 case(WTAP_FILE_TSPREC_NSEC):
241 timestamp_set_precision(TS_PREC_AUTO_NSEC);
244 g_assert_not_reached();
247 /* Set the column widths of those columns that show the time in
248 "command-line-specified" format. */
249 for (i = 0; i < cf->cinfo.num_cols; i++) {
250 if (col_has_time_fmt(&cf->cinfo, i)) {
251 new_packet_list_resize_column(i);
257 cf_get_computed_elapsed(void)
259 return computed_elapsed;
262 static void reset_elapsed(void)
264 computed_elapsed = 0;
267 static void compute_elapsed(GTimeVal *start_time)
272 g_get_current_time(&time_now);
274 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
275 time_now.tv_usec - start_time->tv_usec;
277 computed_elapsed = (gulong) (delta_time / 1000); /* ms*/
281 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
286 wth = wtap_open_offline(fname, err, &err_info, TRUE);
290 /* The open succeeded. Close whatever capture file we had open,
291 and fill in the information for this file. */
294 /* Cleanup all data structures used for dissection. */
295 cleanup_dissection();
296 /* Initialize all data structures used for dissection. */
299 /* We're about to start reading the file. */
300 cf->state = FILE_READ_IN_PROGRESS;
305 /* Set the file name because we need it to set the follow stream filter.
306 XXX - is that still true? We need it for other reasons, though,
308 cf->filename = g_strdup(fname);
310 /* Indicate whether it's a permanent or temporary file. */
311 cf->is_tempfile = is_tempfile;
313 /* If it's a temporary capture buffer file, mark it as not saved. */
314 cf->user_saved = !is_tempfile;
318 cf->cd_t = wtap_file_type(cf->wth);
320 cf->displayed_count = 0;
321 cf->marked_count = 0;
322 cf->ignored_count = 0;
323 cf->ref_time_count = 0;
324 cf->drops_known = FALSE;
326 cf->snap = wtap_snapshot_length(cf->wth);
328 /* Snapshot length not known. */
329 cf->has_snap = FALSE;
330 cf->snap = WTAP_MAX_PACKET_SIZE;
334 /* Allocate a frame_data_sequence for the frames in this file */
335 cf->frames = new_frame_data_sequence();
337 nstime_set_zero(&cf->elapsed_time);
338 nstime_set_unset(&first_ts);
339 nstime_set_unset(&prev_dis_ts);
340 nstime_set_unset(&prev_cap_ts);
343 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
344 cf_timestamp_auto_precision(cf);
346 new_packet_list_queue_draw();
347 fileset_file_opened(fname);
349 if(cf->cd_t == WTAP_FILE_BER) {
350 /* tell the BER dissector the file name */
351 ber_set_filename(cf->filename);
354 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
355 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
360 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
366 * Reset the state for the currently closed file, but don't do the
367 * UI callbacks; this is for use in "cf_open()", where we don't
368 * want the UI to go from "file open" to "file closed" back to
369 * "file open", we want it to go from "old file open" to "new file
370 * open and being read".
373 cf_reset_state(capture_file *cf)
375 /* Die if we're in the middle of reading a file. */
376 g_assert(cf->state != FILE_READ_IN_PROGRESS);
382 /* We have no file open... */
383 if (cf->filename != NULL) {
384 /* If it's a temporary file, remove it. */
386 ws_unlink(cf->filename);
387 g_free(cf->filename);
390 /* ...which means we have nothing to save. */
391 cf->user_saved = FALSE;
393 dfilter_free(cf->rfcode);
395 free_frame_data_sequence(cf->frames);
397 cf_unselect_packet(cf); /* nothing to select */
398 cf->first_displayed = 0;
399 cf->last_displayed = 0;
401 /* No frame selected, no field in that frame selected. */
402 cf->current_frame = 0;
404 cf->finfo_selected = NULL;
406 /* Clear the packet list. */
407 new_packet_list_freeze();
408 new_packet_list_clear();
409 new_packet_list_thaw();
412 nstime_set_zero(&cf->elapsed_time);
414 reset_tap_listeners();
416 /* We have no file open. */
417 cf->state = FILE_CLOSED;
419 fileset_file_closed();
422 /* Reset everything to a pristine state */
424 cf_close(capture_file *cf)
426 /* do GUI things even if file is already closed,
427 * e.g. to cleanup things if a capture couldn't be started */
428 cf_callback_invoke(cf_cb_file_closing, cf);
430 /* close things, if not already closed before */
431 if(cf->state != FILE_CLOSED) {
432 color_filters_cleanup();
434 cleanup_dissection();
437 cf_callback_invoke(cf_cb_file_closed, cf);
440 /* an out of memory exception occured, wait for a user button press to exit */
441 static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
447 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
451 progbar_val = (gfloat) file_pos / (gfloat) size;
452 if (progbar_val > 1.0) {
454 /* The file probably grew while we were reading it.
455 * Update file size, and try again.
457 size = wtap_file_size(cf->wth, NULL);
459 /* Another possibility is that we're reading a compressed file and we've
460 * read more (uncompressed) data from the file than exists in the
461 * (compressed) file. So check how much data we've actually read.
463 * This is inside this "if val > 1.0" check to avoid the lseek() when
464 * reading uncompressed files. Testing has (thus far) shown no progress
465 * bar weirdness resulting from switching from the data offset (when
466 * reading the first part of the file) to the real file position.
468 file_pos = wtap_read_so_far(cf->wth, NULL);
471 progbar_val = (gfloat) file_pos / (gfloat) size;
473 /* If it's still > 1, either "wtap_file_size()" failed (in which
474 * case there's not much we can do about it), or the file
475 * *shrank* (in which case there's not much we can do about
476 * it); just clip the progress value at 1.0.
478 if (progbar_val > 1.0f)
482 g_snprintf(status_str, status_size,
483 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
484 file_pos / 1024, size / 1024);
490 cf_read(capture_file *cf, gboolean from_save)
494 const gchar *name_ptr;
496 char errmsg_errno[1024+1];
498 progdlg_t *volatile progbar = NULL;
500 volatile gint64 size;
501 volatile float progbar_val;
503 gchar status_str[100];
504 volatile gint64 progbar_nextstep;
505 volatile gint64 progbar_quantum;
507 gboolean filtering_tap_listeners;
509 volatile int count = 0;
512 /* Compile the current display filter.
513 * We assume this will not fail since cf->dfilter is only set in
514 * cf_filter IFF the filter was valid.
516 compiled = dfilter_compile(cf->dfilter, &dfcode);
517 g_assert(!cf->dfilter || (compiled && dfcode));
519 /* Do we have any tap listeners with filters? */
520 filtering_tap_listeners = have_filtering_tap_listeners();
522 /* Get the union of the flags for all tap listeners. */
523 tap_flags = union_of_tap_listener_flags();
525 reset_tap_listeners();
527 name_ptr = get_basename(cf->filename);
529 if (from_save == FALSE)
530 cf_callback_invoke(cf_cb_file_read_started, cf);
532 cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr);
534 /* Find the size of the file. */
535 size = wtap_file_size(cf->wth, NULL);
537 /* Update the progress bar when it gets to this value. */
538 progbar_nextstep = 0;
539 /* When we reach the value that triggers a progress bar update,
540 bump that value by this amount. */
542 progbar_quantum = size/N_PROGBAR_UPDATES;
543 if (progbar_quantum < MIN_QUANTUM)
544 progbar_quantum = MIN_QUANTUM;
547 /* Progress so far. */
550 /* The packet list window will be empty untill the file is completly loaded */
551 new_packet_list_freeze();
554 g_get_current_time(&start_time);
556 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
559 /* Create the progress bar if necessary.
560 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
562 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
563 progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str));
564 if (from_save == FALSE)
565 progbar = delayed_create_progress_dlg("Loading", name_ptr,
566 TRUE, &stop_flag, &start_time, progbar_val);
568 progbar = delayed_create_progress_dlg("Saving", name_ptr,
569 TRUE, &stop_flag, &start_time, progbar_val);
572 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
573 when we update it, we have to run the GTK+ main loop to get it
574 to repaint what's pending, and doing so may involve an "ioctl()"
575 to see if there's any pending input from an X server, and doing
576 that for every packet can be costly, especially on a big file. */
577 if (data_offset >= progbar_nextstep) {
578 if (progbar != NULL) {
579 progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str));
580 update_progress_dlg(progbar, progbar_val, status_str);
582 progbar_nextstep += progbar_quantum;
587 /* Well, the user decided to abort the read. He/She will be warned and
588 it might be enough for him/her to work with the already loaded
590 This is especially true for very large capture files, where you don't
591 want to wait loading the whole file (which may last minutes or even
592 hours even on fast machines) just to see that it was the wrong file. */
596 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
598 CATCH(OutOfMemoryError) {
601 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
602 "%sOut Of Memory!%s\n"
604 "Sorry, but Wireshark has to terminate now!\n"
606 "Some infos / workarounds can be found at:\n"
607 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
608 simple_dialog_primary_start(), simple_dialog_primary_end());
609 /* we have to terminate, as we cannot recover from the memory error */
610 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
612 main_window_update();
613 /* XXX - how to avoid a busy wait? */
621 /* Cleanup and release all dfilter resources */
623 dfilter_free(dfcode);
626 /* We're done reading the file; destroy the progress bar if it was created. */
628 destroy_progress_dlg(progbar);
630 /* We're done reading sequentially through the file. */
631 cf->state = FILE_READ_DONE;
633 /* Close the sequential I/O side, to free up memory it requires. */
634 wtap_sequential_close(cf->wth);
636 /* Allow the protocol dissectors to free up memory that they
637 * don't need after the sequential run-through of the packets. */
638 postseq_cleanup_all_protocols();
640 /* compute the time it took to load the file */
641 compute_elapsed(&start_time);
643 /* Set the file encapsulation type now; we don't know what it is until
644 we've looked at all the packets, as we don't know until then whether
645 there's more than one type (and thus whether it's
646 WTAP_ENCAP_PER_PACKET). */
647 cf->lnk_t = wtap_file_encap(cf->wth);
649 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
652 new_packet_list_thaw();
653 if (from_save == FALSE)
654 cf_callback_invoke(cf_cb_file_read_finished, cf);
656 cf_callback_invoke(cf_cb_file_save_finished, cf);
658 /* If we have any displayed packets to select, select the first of those
659 packets by making the first row the selected row. */
660 if (cf->first_displayed != 0){
661 new_packet_list_select_first_row();
665 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
666 "%sFile loading was cancelled!%s\n"
668 "The remaining packets in the file were discarded.\n"
670 "As a lot of packets from the original file will be missing,\n"
671 "remember to be careful when saving the current content to a file.\n",
672 simple_dialog_primary_start(), simple_dialog_primary_end());
673 return CF_READ_ERROR;
677 /* Put up a message box noting that the read failed somewhere along
678 the line. Don't throw out the stuff we managed to read, though,
682 case WTAP_ERR_UNSUPPORTED_ENCAP:
683 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
684 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
687 errmsg = errmsg_errno;
690 case WTAP_ERR_CANT_READ:
691 errmsg = "An attempt to read from the capture file failed for"
692 " some unknown reason.";
695 case WTAP_ERR_SHORT_READ:
696 errmsg = "The capture file appears to have been cut short"
697 " in the middle of a packet.";
700 case WTAP_ERR_BAD_RECORD:
701 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
702 "The capture file appears to be damaged or corrupt.\n(%s)",
705 errmsg = errmsg_errno;
708 case WTAP_ERR_DECOMPRESS:
709 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
710 "The compressed capture file appears to be damaged or corrupt.\n"
713 errmsg = errmsg_errno;
717 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
718 "An error occurred while reading the"
719 " capture file: %s.", wtap_strerror(err));
720 errmsg = errmsg_errno;
723 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
724 return CF_READ_ERROR;
731 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
733 cf_status_t cf_status;
735 cf_status = cf_open(cf, fname, is_tempfile, err);
740 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
742 gint64 data_offset = 0;
744 volatile int newly_displayed_packets = 0;
746 gboolean filtering_tap_listeners;
750 /* Compile the current display filter.
751 * We assume this will not fail since cf->dfilter is only set in
752 * cf_filter IFF the filter was valid.
754 compiled = dfilter_compile(cf->dfilter, &dfcode);
755 g_assert(!cf->dfilter || (compiled && dfcode));
757 /* Do we have any tap listeners with filters? */
758 filtering_tap_listeners = have_filtering_tap_listeners();
760 /* Get the union of the flags for all tap listeners. */
761 tap_flags = union_of_tap_listener_flags();
765 new_packet_list_check_end();
766 /* Don't freeze/thaw the list when doing live capture */
767 /*new_packet_list_freeze();*/
769 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
771 while (to_read != 0) {
772 wtap_cleareof(cf->wth);
773 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
776 if (cf->state == FILE_READ_ABORTED) {
777 /* Well, the user decided to exit Wireshark. Break out of the
778 loop, and let the code below (which is called even if there
779 aren't any packets left to read) exit. */
783 if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
784 data_offset) != -1) {
785 newly_displayed_packets++;
788 CATCH(OutOfMemoryError) {
791 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
792 "%sOut Of Memory!%s\n"
794 "Sorry, but Wireshark has to terminate now!\n"
796 "The capture file is not lost, it can be found at:\n"
799 "Some infos / workarounds can be found at:\n"
800 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
801 simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
802 /* we have to terminate, as we cannot recover from the memory error */
803 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
805 main_window_update();
806 /* XXX - how to avoid a busy wait? */
809 /* Don't freeze/thaw the list when doing live capture */
810 /*new_packet_list_thaw();*/
811 return CF_READ_ABORTED;
817 /* Cleanup and release all dfilter resources */
819 dfilter_free(dfcode);
822 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
823 cf->count, cf->state, *err);*/
825 /* Don't freeze/thaw the list when doing live capture */
826 /*new_packet_list_thaw();*/
827 /* With the new packet list the first packet
828 * isn't automatically selected.
830 if(!cf->current_frame)
831 new_packet_list_select_first_row();
833 /* moving to the end of the packet list - if the user requested so and
834 we have some new packets. */
835 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
836 new_packet_list_moveto_end();
838 if (cf->state == FILE_READ_ABORTED) {
839 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
840 so that our caller can kill off the capture child process;
841 this will cause an EOF on the pipe from the child, so
842 "cf_finish_tail()" will be called, and it will clean up
844 return CF_READ_ABORTED;
845 } else if (*err != 0) {
846 /* We got an error reading the capture file.
847 XXX - pop up a dialog box instead? */
848 g_warning("Error \"%s\" while reading: \"%s\"\n",
849 wtap_strerror(*err), cf->filename);
851 return CF_READ_ERROR;
857 cf_fake_continue_tail(capture_file *cf) {
858 cf->state = FILE_READ_DONE;
862 cf_finish_tail(capture_file *cf, int *err)
867 gboolean filtering_tap_listeners;
871 /* Compile the current display filter.
872 * We assume this will not fail since cf->dfilter is only set in
873 * cf_filter IFF the filter was valid.
875 compiled = dfilter_compile(cf->dfilter, &dfcode);
876 g_assert(!cf->dfilter || (compiled && dfcode));
878 /* Do we have any tap listeners with filters? */
879 filtering_tap_listeners = have_filtering_tap_listeners();
881 /* Get the union of the flags for all tap listeners. */
882 tap_flags = union_of_tap_listener_flags();
884 if(cf->wth == NULL) {
886 return CF_READ_ERROR;
889 new_packet_list_check_end();
890 /* Don't freeze/thaw the list when doing live capture */
891 /*new_packet_list_freeze();*/
893 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
894 if (cf->state == FILE_READ_ABORTED) {
895 /* Well, the user decided to abort the read. Break out of the
896 loop, and let the code below (which is called even if there
897 aren't any packets left to read) exit. */
900 read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
903 /* Cleanup and release all dfilter resources */
905 dfilter_free(dfcode);
908 /* Don't freeze/thaw the list when doing live capture */
909 /*new_packet_list_thaw();*/
911 if (cf->state == FILE_READ_ABORTED) {
912 /* Well, the user decided to abort the read. We're only called
913 when the child capture process closes the pipe to us (meaning
914 it's probably exited), so we can just close the capture
915 file; we return CF_READ_ABORTED so our caller can do whatever
916 is appropriate when that happens. */
918 return CF_READ_ABORTED;
921 if (auto_scroll_live && cf->count != 0)
922 new_packet_list_moveto_end();
924 /* We're done reading sequentially through the file. */
925 cf->state = FILE_READ_DONE;
927 /* We're done reading sequentially through the file; close the
928 sequential I/O side, to free up memory it requires. */
929 wtap_sequential_close(cf->wth);
931 /* Allow the protocol dissectors to free up memory that they
932 * don't need after the sequential run-through of the packets. */
933 postseq_cleanup_all_protocols();
935 /* Set the file encapsulation type now; we don't know what it is until
936 we've looked at all the packets, as we don't know until then whether
937 there's more than one type (and thus whether it's
938 WTAP_ENCAP_PER_PACKET). */
939 cf->lnk_t = wtap_file_encap(cf->wth);
942 /* We got an error reading the capture file.
943 XXX - pop up a dialog box? */
944 return CF_READ_ERROR;
949 #endif /* HAVE_LIBPCAP */
952 cf_get_display_name(capture_file *cf)
954 const gchar *displayname;
956 /* Return a name to use in displays */
957 if (!cf->is_tempfile) {
958 /* Get the last component of the file name, and use that. */
960 displayname = get_basename(cf->filename);
962 displayname="(No file)";
965 /* The file we read is a temporary file from a live capture;
966 we don't mention its name. */
968 displayname = cf->source;
970 displayname = "(Untitled)";
976 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
982 cf->source = g_strdup(source);
984 cf->source = g_strdup("");
988 const gchar *cf_get_tempfile_source(capture_file *cf) {
996 /* XXX - use a macro instead? */
998 cf_get_packet_count(capture_file *cf)
1003 /* XXX - use a macro instead? */
1005 cf_set_packet_count(capture_file *cf, int packet_count)
1007 cf->count = packet_count;
1010 /* XXX - use a macro instead? */
1012 cf_is_tempfile(capture_file *cf)
1014 return cf->is_tempfile;
1017 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1019 cf->is_tempfile = is_tempfile;
1023 /* XXX - use a macro instead? */
1024 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1026 cf->drops_known = drops_known;
1029 /* XXX - use a macro instead? */
1030 void cf_set_drops(capture_file *cf, guint32 drops)
1035 /* XXX - use a macro instead? */
1036 gboolean cf_get_drops_known(capture_file *cf)
1038 return cf->drops_known;
1041 /* XXX - use a macro instead? */
1042 guint32 cf_get_drops(capture_file *cf)
1047 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1049 cf->rfcode = rfcode;
1053 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1054 dfilter_t *dfcode, gboolean filtering_tap_listeners,
1056 union wtap_pseudo_header *pseudo_header, const guchar *buf,
1058 gboolean add_to_packet_list)
1060 gboolean create_proto_tree = FALSE;
1065 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1067 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1068 &first_ts, &prev_dis_ts, &prev_cap_ts);
1071 + we have a display filter and are re-applying it;
1072 + we have tap listeners with filters;
1073 + we have tap listeners that require a protocol tree;
1075 allocate a protocol tree root node, so that we'll construct
1076 a protocol tree against which a filter expression can be
1078 if ((dfcode != NULL && refilter) ||
1079 filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1080 create_proto_tree = TRUE;
1082 /* Dissect the frame. */
1083 epan_dissect_init(&edt, create_proto_tree, FALSE);
1085 if (dfcode != NULL && refilter) {
1086 epan_dissect_prime_dfilter(&edt, dfcode);
1089 tap_queue_init(&edt);
1090 epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1091 tap_push_tapped_queue(&edt);
1093 /* If we have a display filter, apply it if we're refiltering, otherwise
1094 leave the "passed_dfilter" flag alone.
1096 If we don't have a display filter, set "passed_dfilter" to 1. */
1097 if (dfcode != NULL) {
1099 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1102 fdata->flags.passed_dfilter = 1;
1104 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1105 cf->displayed_count++;
1107 if (add_to_packet_list) {
1108 /* We fill the needed columns from new_packet_list */
1109 row = new_packet_list_append(cinfo, fdata, &edt.pi);
1112 if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1114 frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1116 /* If we haven't yet seen the first frame, this is it.
1118 XXX - we must do this before we add the row to the display,
1119 as, if the display's GtkCList's selection mode is
1120 GTK_SELECTION_BROWSE, when the first entry is added to it,
1121 "cf_select_packet()" will be called, and it will fetch the row
1122 data for the 0th row, and will get a null pointer rather than
1123 "fdata", as "gtk_clist_append()" won't yet have returned and
1124 thus "gtk_clist_set_row_data()" won't yet have been called.
1126 We thus need to leave behind bread crumbs so that
1127 "cf_select_packet()" can find this frame. See the comment
1128 in "cf_select_packet()". */
1129 if (cf->first_displayed == 0)
1130 cf->first_displayed = fdata->num;
1132 /* This is the last frame we've seen so far. */
1133 cf->last_displayed = fdata->num;
1136 epan_dissect_cleanup(&edt);
1141 * Initialize the col_text and col_text_len arrays.
1144 init_col_text(frame_data *fdata, gint num_cols)
1146 fdata->col_text_len = se_alloc0(sizeof(*fdata->col_text_len) * num_cols);
1147 fdata->col_text = se_alloc0(sizeof(*fdata->col_text) * num_cols);
1150 /* read in a new packet */
1151 /* returns the row of the new packet in the packet list or -1 if not displayed */
1153 read_packet(capture_file *cf, dfilter_t *dfcode,
1154 gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1156 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1157 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1158 const guchar *buf = wtap_buf_ptr(cf->wth);
1165 /* The frame number of this packet is one more than the count of
1166 frames in this packet. */
1167 framenum = cf->count + 1;
1169 frame_data_init(&fdlocal, framenum, phdr, offset, cum_bytes);
1170 /* Note - if the packet doesn't pass the read filter, and is thus
1171 not added to the capture_file's collection of packets, the
1172 column text arrays aren't free; they're alocated with
1173 se_alloc0(), so they eventually get freed when we close the
1175 init_col_text(&fdlocal, cf->cinfo.num_cols);
1180 epan_dissect_init(&edt, TRUE, FALSE);
1181 epan_dissect_prime_dfilter(&edt, cf->rfcode);
1182 epan_dissect_run(&edt, pseudo_header, buf, &fdlocal, NULL);
1183 passed = dfilter_apply_edt(cf->rfcode, &edt);
1184 epan_dissect_cleanup(&edt);
1188 /* This does a shallow copy of fdlocal, which is good enough. */
1189 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1192 cf->f_datalen = offset + fdlocal.cap_len;
1194 if (!cf->redissecting) {
1195 row = add_packet_to_packet_list(fdata, cf, dfcode,
1196 filtering_tap_listeners, tap_flags,
1197 pseudo_header, buf, TRUE, TRUE);
1205 cf_merge_files(char **out_filenamep, int in_file_count,
1206 char *const *in_filenames, int file_type, gboolean do_append)
1208 merge_in_file_t *in_files;
1214 int open_err, read_err, write_err, close_err;
1218 char errmsg_errno[1024+1];
1220 gboolean got_read_error = FALSE, got_write_error = FALSE;
1222 progdlg_t *progbar = NULL;
1224 gint64 f_len, file_pos;
1226 GTimeVal start_time;
1227 gchar status_str[100];
1228 gint64 progbar_nextstep;
1229 gint64 progbar_quantum;
1231 /* open the input files */
1232 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1233 &open_err, &err_info, &err_fileno)) {
1235 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1240 if (*out_filenamep != NULL) {
1241 out_filename = *out_filenamep;
1242 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1246 out_fd = create_tempfile(&tmpname, "wireshark");
1249 out_filename = g_strdup(tmpname);
1250 *out_filenamep = out_filename;
1254 merge_close_in_files(in_file_count, in_files);
1256 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1260 pdh = wtap_dump_fdopen(out_fd, file_type,
1261 merge_select_frame_type(in_file_count, in_files),
1262 merge_max_snapshot_length(in_file_count, in_files),
1263 FALSE /* compressed */, &open_err);
1266 merge_close_in_files(in_file_count, in_files);
1268 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1273 /* Get the sum of the sizes of all the files. */
1275 for (i = 0; i < in_file_count; i++)
1276 f_len += in_files[i].size;
1278 /* Update the progress bar when it gets to this value. */
1279 progbar_nextstep = 0;
1280 /* When we reach the value that triggers a progress bar update,
1281 bump that value by this amount. */
1282 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1283 /* Progress so far. */
1287 g_get_current_time(&start_time);
1289 /* do the merge (or append) */
1292 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1295 wth = merge_read_packet(in_file_count, in_files, &read_err,
1299 got_read_error = TRUE;
1303 /* Get the sum of the data offsets in all of the files. */
1305 for (i = 0; i < in_file_count; i++)
1306 data_offset += in_files[i].data_offset;
1308 /* Create the progress bar if necessary.
1309 We check on every iteration of the loop, so that it takes no
1310 longer than the standard time to create it (otherwise, for a
1311 large file, we might take considerably longer than that standard
1312 time in order to get to the next progress bar step). */
1313 if (progbar == NULL) {
1314 progbar = delayed_create_progress_dlg("Merging", "files",
1315 FALSE, &stop_flag, &start_time, progbar_val);
1318 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1319 when we update it, we have to run the GTK+ main loop to get it
1320 to repaint what's pending, and doing so may involve an "ioctl()"
1321 to see if there's any pending input from an X server, and doing
1322 that for every packet can be costly, especially on a big file. */
1323 if (data_offset >= progbar_nextstep) {
1324 /* Get the sum of the seek positions in all of the files. */
1326 for (i = 0; i < in_file_count; i++)
1327 file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1328 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1329 if (progbar_val > 1.0f) {
1330 /* Some file probably grew while we were reading it.
1331 That "shouldn't happen", so we'll just clip the progress
1335 if (progbar != NULL) {
1336 g_snprintf(status_str, sizeof(status_str),
1337 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1338 file_pos / 1024, f_len / 1024);
1339 update_progress_dlg(progbar, progbar_val, status_str);
1341 progbar_nextstep += progbar_quantum;
1345 /* Well, the user decided to abort the merge. */
1349 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1350 wtap_buf_ptr(wth), &write_err)) {
1351 got_write_error = TRUE;
1356 /* We're done merging the files; destroy the progress bar if it was created. */
1357 if (progbar != NULL)
1358 destroy_progress_dlg(progbar);
1360 merge_close_in_files(in_file_count, in_files);
1361 if (!got_read_error && !got_write_error) {
1362 if (!wtap_dump_close(pdh, &write_err))
1363 got_write_error = TRUE;
1365 wtap_dump_close(pdh, &close_err);
1367 if (got_read_error) {
1369 * Find the file on which we got the error, and report the error.
1371 for (i = 0; i < in_file_count; i++) {
1372 if (in_files[i].state == GOT_ERROR) {
1373 /* Put up a message box noting that a read failed somewhere along
1377 case WTAP_ERR_UNSUPPORTED_ENCAP:
1378 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1379 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1382 errmsg = errmsg_errno;
1385 case WTAP_ERR_CANT_READ:
1386 errmsg = "An attempt to read from the capture file %s failed for"
1387 " some unknown reason.";
1390 case WTAP_ERR_SHORT_READ:
1391 errmsg = "The capture file %s appears to have been cut short"
1392 " in the middle of a packet.";
1395 case WTAP_ERR_BAD_RECORD:
1396 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1397 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1400 errmsg = errmsg_errno;
1403 case WTAP_ERR_DECOMPRESS:
1404 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1405 "The compressed capture file %%s appears to be damaged or corrupt.\n"
1408 errmsg = errmsg_errno;
1412 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1413 "An error occurred while reading the"
1414 " capture file %%s: %s.", wtap_strerror(read_err));
1415 errmsg = errmsg_errno;
1418 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
1423 if (got_write_error) {
1424 /* Put up an alert box for the write error. */
1425 cf_write_failure_alert_box(out_filename, write_err);
1428 if (got_read_error || got_write_error || stop_flag) {
1429 /* Callers aren't expected to treat an error or an explicit abort
1430 differently - we put up error dialogs ourselves, so they don't
1438 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1440 const char *filter_new = dftext ? dftext : "";
1441 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1443 GTimeVal start_time;
1445 /* if new filter equals old one, do nothing unless told to do so */
1446 if (!force && strcmp(filter_new, filter_old) == 0) {
1452 if (dftext == NULL) {
1453 /* The new filter is an empty filter (i.e., display all packets).
1454 * so leave dfcode==NULL
1458 * We have a filter; make a copy of it (as we'll be saving it),
1459 * and try to compile it.
1461 dftext = g_strdup(dftext);
1462 if (!dfilter_compile(dftext, &dfcode)) {
1463 /* The attempt failed; report an error. */
1464 gchar *safe_dftext = simple_dialog_format_message(dftext);
1465 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1467 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1470 "The following display filter isn't a valid display filter:\n%s\n"
1471 "See the help for a description of the display filter syntax.",
1472 simple_dialog_primary_start(), safe_dfilter_error_msg,
1473 simple_dialog_primary_end(), safe_dftext);
1474 g_free(safe_dfilter_error_msg);
1475 g_free(safe_dftext);
1481 if (dfcode == NULL) {
1482 /* Yes - free the filter text, and set it to null. */
1488 /* We have a valid filter. Replace the current filter. */
1489 g_free(cf->dfilter);
1490 cf->dfilter = dftext;
1491 g_get_current_time(&start_time);
1494 /* Now rescan the packet list, applying the new filter, but not
1495 throwing away information constructed on a previous pass. */
1496 if (dftext == NULL) {
1497 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1499 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1502 /* Cleanup and release all dfilter resources */
1503 dfilter_free(dfcode);
1509 cf_reftime_packets(capture_file *cf)
1512 ref_time_packets(cf);
1516 cf_redissect_packets(capture_file *cf)
1518 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1522 cf_read_frame_r(capture_file *cf, frame_data *fdata,
1523 union wtap_pseudo_header *pseudo_header, guint8 *pd)
1527 char errmsg_errno[1024+1];
1529 if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
1530 fdata->cap_len, &err, &err_info)) {
1533 case WTAP_ERR_UNSUPPORTED_ENCAP:
1534 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1535 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1540 case WTAP_ERR_BAD_RECORD:
1541 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1542 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
1543 wtap_strerror(err), err_info);
1548 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1549 "An error occurred while reading from the file \"%%s\": %s.",
1550 wtap_strerror(err));
1553 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg_errno, cf->filename);
1560 cf_read_frame(capture_file *cf, frame_data *fdata)
1562 return cf_read_frame_r(cf, fdata, &cf->pseudo_header, cf->pd);
1565 /* Rescan the list of packets, reconstructing the CList.
1567 "action" describes why we're doing this; it's used in the progress
1570 "action_item" describes what we're doing; it's used in the progress
1573 "refilter" is TRUE if we need to re-evaluate the filter expression.
1575 "redissect" is TRUE if we need to make the dissectors reconstruct
1576 any state information they have (because a preference that affects
1577 some dissector has changed, meaning some dissector might construct
1578 its state differently from the way it was constructed the last time). */
1580 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1581 gboolean refilter, gboolean redissect)
1583 /* Rescan packets new packet list */
1586 progdlg_t *progbar = NULL;
1589 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1590 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1591 gboolean selected_frame_seen;
1593 GTimeVal start_time;
1594 gchar status_str[100];
1595 int progbar_nextstep;
1596 int progbar_quantum;
1598 gboolean filtering_tap_listeners;
1600 gboolean add_to_packet_list = FALSE;
1603 /* Compile the current display filter.
1604 * We assume this will not fail since cf->dfilter is only set in
1605 * cf_filter IFF the filter was valid.
1607 compiled = dfilter_compile(cf->dfilter, &dfcode);
1608 g_assert(!cf->dfilter || (compiled && dfcode));
1610 /* Do we have any tap listeners with filters? */
1611 filtering_tap_listeners = have_filtering_tap_listeners();
1613 /* Get the union of the flags for all tap listeners. */
1614 tap_flags = union_of_tap_listener_flags();
1616 reset_tap_listeners();
1617 /* Which frame, if any, is the currently selected frame?
1618 XXX - should the selected frame or the focus frame be the "current"
1619 frame, that frame being the one from which "Find Frame" searches
1621 selected_frame = cf->current_frame;
1623 /* Mark frame num as not found */
1624 selected_frame_num = -1;
1626 /* Freeze the packet list while we redo it, so we don't get any
1627 screen updates while it happens. */
1628 new_packet_list_freeze();
1631 /* We need to re-initialize all the state information that protocols
1632 keep, because some preference that controls a dissector has changed,
1633 which might cause the state information to be constructed differently
1634 by that dissector. */
1636 /* We might receive new packets while redissecting, and we don't
1637 want to dissect those before their time. */
1638 cf->redissecting = TRUE;
1640 /* Cleanup all data structures used for dissection. */
1641 cleanup_dissection();
1642 /* Initialize all data structures used for dissection. */
1645 /* We need to redissect the packets so we have to discard our old
1646 * packet list store. */
1647 new_packet_list_clear();
1648 add_to_packet_list = TRUE;
1651 /* We don't yet know which will be the first and last frames displayed. */
1652 cf->first_displayed = 0;
1653 cf->last_displayed = 0;
1655 /* We currently don't display any packets */
1656 cf->displayed_count = 0;
1658 /* Iterate through the list of frames. Call a routine for each frame
1659 to check whether it should be displayed and, if so, add it to
1660 the display list. */
1661 nstime_set_unset(&first_ts);
1662 nstime_set_unset(&prev_dis_ts);
1663 nstime_set_unset(&prev_cap_ts);
1666 /* Update the progress bar when it gets to this value. */
1667 progbar_nextstep = 0;
1668 /* When we reach the value that triggers a progress bar update,
1669 bump that value by this amount. */
1670 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1671 /* Count of packets at which we've looked. */
1673 /* Progress so far. */
1677 g_get_current_time(&start_time);
1679 /* no previous row yet */
1680 prev_frame_num = -1;
1683 preceding_frame_num = -1;
1684 preceding_frame = NULL;
1685 following_frame_num = -1;
1686 following_frame = NULL;
1688 selected_frame_seen = FALSE;
1690 for (framenum = 1; framenum <= cf->count; framenum++) {
1691 fdata = frame_data_sequence_find(cf->frames, framenum);
1693 /* Create the progress bar if necessary.
1694 We check on every iteration of the loop, so that it takes no
1695 longer than the standard time to create it (otherwise, for a
1696 large file, we might take considerably longer than that standard
1697 time in order to get to the next progress bar step). */
1698 if (progbar == NULL)
1699 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1700 &stop_flag, &start_time,
1703 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1704 when we update it, we have to run the GTK+ main loop to get it
1705 to repaint what's pending, and doing so may involve an "ioctl()"
1706 to see if there's any pending input from an X server, and doing
1707 that for every packet can be costly, especially on a big file. */
1708 if (count >= progbar_nextstep) {
1709 /* let's not divide by zero. I should never be started
1710 * with count == 0, so let's assert that
1712 g_assert(cf->count > 0);
1713 progbar_val = (gfloat) count / cf->count;
1715 if (progbar != NULL) {
1716 g_snprintf(status_str, sizeof(status_str),
1717 "%4u of %u frames", count, cf->count);
1718 update_progress_dlg(progbar, progbar_val, status_str);
1721 progbar_nextstep += progbar_quantum;
1725 /* Well, the user decided to abort the filtering. Just stop.
1727 XXX - go back to the previous filter? Users probably just
1728 want not to wait for a filtering operation to finish;
1729 unless we cancel by having no filter, reverting to the
1730 previous filter will probably be even more expensive than
1731 continuing the filtering, as it involves going back to the
1732 beginning and filtering, and even with no filter we currently
1733 have to re-generate the entire clist, which is also expensive.
1735 I'm not sure what Network Monitor does, but it doesn't appear
1736 to give you an unfiltered display if you cancel. */
1743 /* Since all state for the frame was destroyed, mark the frame
1744 * as not visited, free the GSList referring to the state
1745 * data (the per-frame data itself was freed by
1746 * "init_dissection()"), and null out the GSList pointer. */
1747 fdata->flags.visited = 0;
1748 frame_data_cleanup(fdata);
1750 /* cleanup_dissection() calls se_free_all();
1751 * And after that fdata->col_text (which is allocated using se_alloc0())
1752 * no longer points to valid memory.
1754 init_col_text(fdata, cf->cinfo.num_cols);
1757 if (!cf_read_frame(cf, fdata))
1758 break; /* error reading the frame */
1760 /* If the previous frame is displayed, and we haven't yet seen the
1761 selected frame, remember that frame - it's the closest one we've
1762 yet seen before the selected frame. */
1763 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1764 preceding_frame_num = prev_frame_num;
1765 preceding_frame = prev_frame;
1767 add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1768 tap_flags, &cf->pseudo_header, cf->pd,
1770 add_to_packet_list);
1772 /* If this frame is displayed, and this is the first frame we've
1773 seen displayed after the selected frame, remember this frame -
1774 it's the closest one we've yet seen at or after the selected
1776 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1777 following_frame_num = fdata->num;
1778 following_frame = fdata;
1780 if (fdata == selected_frame) {
1781 selected_frame_seen = TRUE;
1782 if (fdata->flags.passed_dfilter)
1783 selected_frame_num = fdata->num;
1786 /* Remember this frame - it'll be the previous frame
1787 on the next pass through the loop. */
1788 prev_frame_num = fdata->num;
1792 /* We are done redissecting the packet list. */
1793 cf->redissecting = FALSE;
1796 /* Clear out what remains of the visited flags and per-frame data
1799 XXX - that may cause various forms of bogosity when dissecting
1800 these frames, as they won't have been seen by this sequential
1801 pass, but the only alternative I see is to keep scanning them
1802 even though the user requested that the scan stop, and that
1803 would leave the user stuck with an Wireshark grinding on
1804 until it finishes. Should we just stick them with that? */
1805 for (; framenum <= cf->count; framenum++) {
1806 fdata = frame_data_sequence_find(cf->frames, framenum);
1807 fdata->flags.visited = 0;
1808 frame_data_cleanup(fdata);
1812 /* We're done filtering the packets; destroy the progress bar if it
1814 if (progbar != NULL)
1815 destroy_progress_dlg(progbar);
1817 /* Unfreeze the packet list. */
1818 if (!add_to_packet_list)
1819 new_packet_list_recreate_visible_rows();
1821 /* Compute the time it took to filter the file */
1822 compute_elapsed(&start_time);
1824 new_packet_list_thaw();
1826 if (selected_frame_num == -1) {
1827 /* The selected frame didn't pass the filter. */
1828 if (selected_frame == NULL) {
1829 /* That's because there *was* no selected frame. Make the first
1830 displayed frame the current frame. */
1831 selected_frame_num = 0;
1833 /* Find the nearest displayed frame to the selected frame (whether
1834 it's before or after that frame) and make that the current frame.
1835 If the next and previous displayed frames are equidistant from the
1836 selected frame, choose the next one. */
1837 g_assert(following_frame == NULL ||
1838 following_frame->num >= selected_frame->num);
1839 g_assert(preceding_frame == NULL ||
1840 preceding_frame->num <= selected_frame->num);
1841 if (following_frame == NULL) {
1842 /* No frame after the selected frame passed the filter, so we
1843 have to select the last displayed frame before the selected
1845 selected_frame_num = preceding_frame_num;
1846 selected_frame = preceding_frame;
1847 } else if (preceding_frame == NULL) {
1848 /* No frame before the selected frame passed the filter, so we
1849 have to select the first displayed frame after the selected
1851 selected_frame_num = following_frame_num;
1852 selected_frame = following_frame;
1854 /* Frames before and after the selected frame passed the filter, so
1855 we'll select the previous frame */
1856 selected_frame_num = preceding_frame_num;
1857 selected_frame = preceding_frame;
1862 if (selected_frame_num == -1) {
1863 /* There are no frames displayed at all. */
1864 cf_unselect_packet(cf);
1866 /* Either the frame that was selected passed the filter, or we've
1867 found the nearest displayed frame to that frame. Select it, make
1868 it the focus row, and make it visible. */
1869 /* Set to invalid to force update of packet list and packet details */
1870 cf->current_row = -1;
1871 if (selected_frame_num == 0) {
1872 new_packet_list_select_first_row();
1874 if (!new_packet_list_select_row_from_data(selected_frame)) {
1875 /* We didn't find a row corresponding to this frame.
1876 This means that the frame isn't being displayed currently,
1877 so we can't select it. */
1878 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
1879 "%sEnd of capture exceeded!%s\n\n"
1880 "The capture file is probably not fully dissected.",
1881 simple_dialog_primary_start(), simple_dialog_primary_end());
1886 /* Cleanup and release all dfilter resources */
1887 dfilter_free(dfcode);
1892 * Scan trough all frame data and recalculate the ref time
1893 * without rereading the file.
1894 * XXX - do we need a progres bar or is this fast enough?
1897 ref_time_packets(capture_file *cf)
1902 nstime_set_unset(&first_ts);
1903 nstime_set_unset(&prev_dis_ts);
1906 for (framenum = 1; framenum <= cf->count; framenum++) {
1907 fdata = frame_data_sequence_find(cf->frames, framenum);
1909 /* just add some value here until we know if it is being displayed or not */
1910 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1916 /* If we don't have the time stamp of the first packet in the
1917 capture, it's because this is the first packet. Save the time
1918 stamp of this packet as the time stamp of the first packet. */
1919 if (nstime_is_unset(&first_ts)) {
1920 first_ts = fdata->abs_ts;
1922 /* if this frames is marked as a reference time frame, reset
1923 firstsec and firstusec to this frame */
1924 if(fdata->flags.ref_time){
1925 first_ts = fdata->abs_ts;
1928 /* If we don't have the time stamp of the previous displayed packet,
1929 it's because this is the first displayed packet. Save the time
1930 stamp of this packet as the time stamp of the previous displayed
1932 if (nstime_is_unset(&prev_dis_ts)) {
1933 prev_dis_ts = fdata->abs_ts;
1936 /* Get the time elapsed between the first packet and this packet. */
1937 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
1939 /* If it's greater than the current elapsed time, set the elapsed time
1940 to it (we check for "greater than" so as not to be confused by
1941 time moving backwards). */
1942 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
1943 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
1944 cf->elapsed_time = fdata->rel_ts;
1947 /* Get the time elapsed between the previous displayed packet and
1949 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
1951 prev_dis_ts = fdata->abs_ts;
1956 if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
1957 /* This frame either passed the display filter list or is marked as
1958 a time reference frame. All time reference frames are displayed
1959 even if they dont pass the display filter */
1960 if(fdata->flags.ref_time){
1961 /* if this was a TIME REF frame we should reset the cum_bytes field */
1962 cum_bytes = fdata->pkt_len;
1963 fdata->cum_bytes = cum_bytes;
1965 /* increase cum_bytes with this packets length */
1966 cum_bytes += fdata->pkt_len;
1979 process_specified_packets(capture_file *cf, packet_range_t *range,
1980 const char *string1, const char *string2, gboolean terminate_is_stop,
1981 gboolean (*callback)(capture_file *, frame_data *,
1982 union wtap_pseudo_header *, const guint8 *, void *),
1983 void *callback_args)
1987 union wtap_pseudo_header pseudo_header;
1988 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1989 psp_return_t ret = PSP_FINISHED;
1991 progdlg_t *progbar = NULL;
1994 gboolean progbar_stop_flag;
1995 GTimeVal progbar_start_time;
1996 gchar progbar_status_str[100];
1997 int progbar_nextstep;
1998 int progbar_quantum;
1999 range_process_e process_this;
2001 /* Update the progress bar when it gets to this value. */
2002 progbar_nextstep = 0;
2003 /* When we reach the value that triggers a progress bar update,
2004 bump that value by this amount. */
2005 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2006 /* Count of packets at which we've looked. */
2008 /* Progress so far. */
2011 progbar_stop_flag = FALSE;
2012 g_get_current_time(&progbar_start_time);
2014 packet_range_process_init(range);
2016 /* Iterate through all the packets, printing the packets that
2017 were selected by the current display filter. */
2018 for (framenum = 1; framenum <= cf->count; framenum++) {
2019 fdata = frame_data_sequence_find(cf->frames, framenum);
2021 /* Create the progress bar if necessary.
2022 We check on every iteration of the loop, so that it takes no
2023 longer than the standard time to create it (otherwise, for a
2024 large file, we might take considerably longer than that standard
2025 time in order to get to the next progress bar step). */
2026 if (progbar == NULL)
2027 progbar = delayed_create_progress_dlg(string1, string2,
2030 &progbar_start_time,
2033 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2034 when we update it, we have to run the GTK+ main loop to get it
2035 to repaint what's pending, and doing so may involve an "ioctl()"
2036 to see if there's any pending input from an X server, and doing
2037 that for every packet can be costly, especially on a big file. */
2038 if (progbar_count >= progbar_nextstep) {
2039 /* let's not divide by zero. I should never be started
2040 * with count == 0, so let's assert that
2042 g_assert(cf->count > 0);
2043 progbar_val = (gfloat) progbar_count / cf->count;
2045 if (progbar != NULL) {
2046 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2047 "%4u of %u packets", progbar_count, cf->count);
2048 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2051 progbar_nextstep += progbar_quantum;
2054 if (progbar_stop_flag) {
2055 /* Well, the user decided to abort the operation. Just stop,
2056 and arrange to return PSP_STOPPED to our caller, so they know
2057 it was stopped explicitly. */
2064 /* do we have to process this packet? */
2065 process_this = packet_range_process_packet(range, fdata);
2066 if (process_this == range_process_next) {
2067 /* this packet uninteresting, continue with next one */
2069 } else if (process_this == range_processing_finished) {
2070 /* all interesting packets processed, stop the loop */
2074 /* Get the packet */
2075 if (!cf_read_frame_r(cf, fdata, &pseudo_header, pd)) {
2076 /* Attempt to get the packet failed. */
2080 /* Process the packet */
2081 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
2082 /* Callback failed. We assume it reported the error appropriately. */
2088 /* We're done printing the packets; destroy the progress bar if
2090 if (progbar != NULL)
2091 destroy_progress_dlg(progbar);
2097 gboolean construct_protocol_tree;
2099 } retap_callback_args_t;
2102 retap_packet(capture_file *cf _U_, frame_data *fdata,
2103 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2106 retap_callback_args_t *args = argsp;
2109 epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
2110 tap_queue_init(&edt);
2111 epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
2112 tap_push_tapped_queue(&edt);
2113 epan_dissect_cleanup(&edt);
2119 cf_retap_packets(capture_file *cf)
2121 packet_range_t range;
2122 retap_callback_args_t callback_args;
2123 gboolean filtering_tap_listeners;
2126 /* Do we have any tap listeners with filters? */
2127 filtering_tap_listeners = have_filtering_tap_listeners();
2129 tap_flags = union_of_tap_listener_flags();
2131 /* If any tap listeners have filters, or require the protocol tree,
2132 construct the protocol tree. */
2133 callback_args.construct_protocol_tree = filtering_tap_listeners ||
2134 (tap_flags & TL_REQUIRES_PROTO_TREE);
2136 /* If any tap listeners require the columns, construct them. */
2137 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2139 /* Reset the tap listeners. */
2140 reset_tap_listeners();
2142 /* Iterate through the list of packets, dissecting all packets and
2143 re-running the taps. */
2144 packet_range_init(&range);
2145 packet_range_process_init(&range);
2146 switch (process_specified_packets(cf, &range, "Recalculating statistics on",
2147 "all packets", TRUE, retap_packet,
2150 /* Completed successfully. */
2154 /* Well, the user decided to abort the refiltering.
2155 Return CF_READ_ABORTED so our caller knows they did that. */
2156 return CF_READ_ABORTED;
2159 /* Error while retapping. */
2160 return CF_READ_ERROR;
2163 g_assert_not_reached();
2168 print_args_t *print_args;
2169 gboolean print_header_line;
2170 char *header_line_buf;
2171 int header_line_buf_len;
2172 gboolean print_formfeed;
2173 gboolean print_separator;
2177 } print_callback_args_t;
2180 print_packet(capture_file *cf, frame_data *fdata,
2181 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2184 print_callback_args_t *args = argsp;
2191 gboolean proto_tree_needed;
2192 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2193 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2195 /* Create the protocol tree, and make it visible, if we're printing
2196 the dissection or the hex data.
2197 XXX - do we need it if we're just printing the hex data? */
2199 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2200 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2202 /* Fill in the column information if we're printing the summary
2204 if (args->print_args->print_summary) {
2205 col_custom_prime_edt(&edt, &cf->cinfo);
2206 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2207 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2209 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2211 if (args->print_formfeed) {
2212 if (!new_page(args->print_args->stream))
2215 if (args->print_separator) {
2216 if (!print_line(args->print_args->stream, 0, ""))
2222 * We generate bookmarks, if the output format supports them.
2223 * The name is "__frameN__".
2225 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2227 if (args->print_args->print_summary) {
2228 if (args->print_header_line) {
2229 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2231 args->print_header_line = FALSE; /* we might not need to print any more */
2233 cp = &args->line_buf[0];
2235 for (i = 0; i < cf->cinfo.num_cols; i++) {
2236 /* Find the length of the string for this column. */
2237 column_len = (int) strlen(cf->cinfo.col_data[i]);
2238 if (args->col_widths[i] > column_len)
2239 column_len = args->col_widths[i];
2241 /* Make sure there's room in the line buffer for the column; if not,
2242 double its length. */
2243 line_len += column_len + 1; /* "+1" for space */
2244 if (line_len > args->line_buf_len) {
2245 cp_off = (int) (cp - args->line_buf);
2246 args->line_buf_len = 2 * line_len;
2247 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2248 cp = args->line_buf + cp_off;
2251 /* Right-justify the packet number column. */
2252 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2253 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
2255 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
2257 if (i != cf->cinfo.num_cols - 1)
2263 * Generate a bookmark, using the summary line as the title.
2265 if (!print_bookmark(args->print_args->stream, bookmark_name,
2269 if (!print_line(args->print_args->stream, 0, args->line_buf))
2273 * Generate a bookmark, using "Frame N" as the title, as we're not
2274 * printing the summary line.
2276 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2277 if (!print_bookmark(args->print_args->stream, bookmark_name,
2280 } /* if (print_summary) */
2282 if (args->print_args->print_dissections != print_dissections_none) {
2283 if (args->print_args->print_summary) {
2284 /* Separate the summary line from the tree with a blank line. */
2285 if (!print_line(args->print_args->stream, 0, ""))
2289 /* Print the information in that tree. */
2290 if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
2293 /* Print a blank line if we print anything after this (aka more than one packet). */
2294 args->print_separator = TRUE;
2296 /* Print a header line if we print any more packet summaries */
2297 args->print_header_line = TRUE;
2300 if (args->print_args->print_hex) {
2301 /* Print the full packet data as hex. */
2302 if (!print_hex_data(args->print_args->stream, &edt))
2305 /* Print a blank line if we print anything after this (aka more than one packet). */
2306 args->print_separator = TRUE;
2308 /* Print a header line if we print any more packet summaries */
2309 args->print_header_line = TRUE;
2310 } /* if (args->print_args->print_dissections != print_dissections_none) */
2312 epan_dissect_cleanup(&edt);
2314 /* do we want to have a formfeed between each packet from now on? */
2315 if(args->print_args->print_formfeed) {
2316 args->print_formfeed = TRUE;
2322 epan_dissect_cleanup(&edt);
2327 cf_print_packets(capture_file *cf, print_args_t *print_args)
2330 print_callback_args_t callback_args;
2338 callback_args.print_args = print_args;
2339 callback_args.print_header_line = TRUE;
2340 callback_args.header_line_buf = NULL;
2341 callback_args.header_line_buf_len = 256;
2342 callback_args.print_formfeed = FALSE;
2343 callback_args.print_separator = FALSE;
2344 callback_args.line_buf = NULL;
2345 callback_args.line_buf_len = 256;
2346 callback_args.col_widths = NULL;
2348 if (!print_preamble(print_args->stream, cf->filename)) {
2349 destroy_print_stream(print_args->stream);
2350 return CF_PRINT_WRITE_ERROR;
2353 if (print_args->print_summary) {
2354 /* We're printing packet summaries. Allocate the header line buffer
2355 and get the column widths. */
2356 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2358 /* Find the widths for each of the columns - maximum of the
2359 width of the title and the width of the data - and construct
2360 a buffer with a line containing the column titles. */
2361 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2362 cp = &callback_args.header_line_buf[0];
2364 for (i = 0; i < cf->cinfo.num_cols; i++) {
2365 /* Don't pad the last column. */
2366 if (i == cf->cinfo.num_cols - 1)
2367 callback_args.col_widths[i] = 0;
2369 callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
2370 data_width = get_column_char_width(get_column_format(i));
2371 if (data_width > callback_args.col_widths[i])
2372 callback_args.col_widths[i] = data_width;
2375 /* Find the length of the string for this column. */
2376 column_len = (int) strlen(cf->cinfo.col_title[i]);
2377 if (callback_args.col_widths[i] > column_len)
2378 column_len = callback_args.col_widths[i];
2380 /* Make sure there's room in the line buffer for the column; if not,
2381 double its length. */
2382 line_len += column_len + 1; /* "+1" for space */
2383 if (line_len > callback_args.header_line_buf_len) {
2384 cp_off = (int) (cp - callback_args.header_line_buf);
2385 callback_args.header_line_buf_len = 2 * line_len;
2386 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2387 callback_args.header_line_buf_len + 1);
2388 cp = callback_args.header_line_buf + cp_off;
2391 /* Right-justify the packet number column. */
2392 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2393 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2395 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2397 if (i != cf->cinfo.num_cols - 1)
2402 /* Now start out the main line buffer with the same length as the
2403 header line buffer. */
2404 callback_args.line_buf_len = callback_args.header_line_buf_len;
2405 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2406 } /* if (print_summary) */
2408 /* Iterate through the list of packets, printing the packets we were
2410 ret = process_specified_packets(cf, &print_args->range, "Printing",
2411 "selected packets", TRUE, print_packet,
2414 g_free(callback_args.header_line_buf);
2415 g_free(callback_args.line_buf);
2416 g_free(callback_args.col_widths);
2421 /* Completed successfully. */
2425 /* Well, the user decided to abort the printing.
2427 XXX - note that what got generated before they did that
2428 will get printed if we're piping to a print program; we'd
2429 have to write to a file and then hand that to the print
2430 program to make it actually not print anything. */
2434 /* Error while printing.
2436 XXX - note that what got generated before they did that
2437 will get printed if we're piping to a print program; we'd
2438 have to write to a file and then hand that to the print
2439 program to make it actually not print anything. */
2440 destroy_print_stream(print_args->stream);
2441 return CF_PRINT_WRITE_ERROR;
2444 if (!print_finale(print_args->stream)) {
2445 destroy_print_stream(print_args->stream);
2446 return CF_PRINT_WRITE_ERROR;
2449 if (!destroy_print_stream(print_args->stream))
2450 return CF_PRINT_WRITE_ERROR;
2456 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2457 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2463 /* Create the protocol tree, but don't fill in the column information. */
2464 epan_dissect_init(&edt, TRUE, TRUE);
2465 epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2467 /* Write out the information in that tree. */
2468 proto_tree_write_pdml(&edt, fh);
2470 epan_dissect_cleanup(&edt);
2476 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2481 fh = ws_fopen(print_args->file, "w");
2483 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2485 write_pdml_preamble(fh);
2488 return CF_PRINT_WRITE_ERROR;
2491 /* Iterate through the list of packets, printing the packets we were
2493 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2494 "selected packets", TRUE,
2495 write_pdml_packet, fh);
2500 /* Completed successfully. */
2504 /* Well, the user decided to abort the printing. */
2508 /* Error while printing. */
2510 return CF_PRINT_WRITE_ERROR;
2513 write_pdml_finale(fh);
2516 return CF_PRINT_WRITE_ERROR;
2519 /* XXX - check for an error */
2526 write_psml_packet(capture_file *cf, frame_data *fdata,
2527 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2532 gboolean proto_tree_needed;
2534 /* Fill in the column information, only create the protocol tree
2535 if having custom columns. */
2536 proto_tree_needed = have_custom_cols(&cf->cinfo);
2537 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2538 col_custom_prime_edt(&edt, &cf->cinfo);
2539 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2540 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2542 /* Write out the information in that tree. */
2543 proto_tree_write_psml(&edt, fh);
2545 epan_dissect_cleanup(&edt);
2551 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2556 fh = ws_fopen(print_args->file, "w");
2558 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2560 write_psml_preamble(fh);
2563 return CF_PRINT_WRITE_ERROR;
2566 /* Iterate through the list of packets, printing the packets we were
2568 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2569 "selected packets", TRUE,
2570 write_psml_packet, fh);
2575 /* Completed successfully. */
2579 /* Well, the user decided to abort the printing. */
2583 /* Error while printing. */
2585 return CF_PRINT_WRITE_ERROR;
2588 write_psml_finale(fh);
2591 return CF_PRINT_WRITE_ERROR;
2594 /* XXX - check for an error */
2601 write_csv_packet(capture_file *cf, frame_data *fdata,
2602 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2607 gboolean proto_tree_needed;
2609 /* Fill in the column information, only create the protocol tree
2610 if having custom columns. */
2611 proto_tree_needed = have_custom_cols(&cf->cinfo);
2612 epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2613 col_custom_prime_edt(&edt, &cf->cinfo);
2614 epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2615 epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2617 /* Write out the information in that tree. */
2618 proto_tree_write_csv(&edt, fh);
2620 epan_dissect_cleanup(&edt);
2626 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2631 fh = ws_fopen(print_args->file, "w");
2633 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2635 write_csv_preamble(fh);
2638 return CF_PRINT_WRITE_ERROR;
2641 /* Iterate through the list of packets, printing the packets we were
2643 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2644 "selected packets", TRUE,
2645 write_csv_packet, fh);
2650 /* Completed successfully. */
2654 /* Well, the user decided to abort the printing. */
2658 /* Error while printing. */
2660 return CF_PRINT_WRITE_ERROR;
2663 write_csv_finale(fh);
2666 return CF_PRINT_WRITE_ERROR;
2669 /* XXX - check for an error */
2676 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
2677 union wtap_pseudo_header *pseudo_header _U_,
2678 const guint8 *pd, void *argsp)
2682 proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh);
2687 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2692 fh = ws_fopen(print_args->file, "w");
2695 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2697 write_carrays_preamble(fh);
2701 return CF_PRINT_WRITE_ERROR;
2704 /* Iterate through the list of packets, printing the packets we were
2706 ret = process_specified_packets(cf, &print_args->range,
2708 "selected packets", TRUE,
2709 write_carrays_packet, fh);
2712 /* Completed successfully. */
2715 /* Well, the user decided to abort the printing. */
2718 /* Error while printing. */
2720 return CF_PRINT_WRITE_ERROR;
2723 write_carrays_finale(fh);
2727 return CF_PRINT_WRITE_ERROR;
2735 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2736 search_direction dir)
2740 mdata.string = string;
2741 mdata.string_len = strlen(string);
2742 return find_packet(cf, match_protocol_tree, &mdata, dir);
2746 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2748 mdata->frame_matched = FALSE;
2749 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2750 mdata->string_len = strlen(mdata->string);
2752 /* Iterate through all the nodes looking for matching text */
2753 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2754 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2758 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2760 match_data *mdata = criterion;
2763 /* Load the frame's data. */
2764 if (!cf_read_frame(cf, fdata)) {
2765 /* Attempt to get the packet failed. */
2769 /* Construct the protocol tree, including the displayed text */
2770 epan_dissect_init(&edt, TRUE, TRUE);
2771 /* We don't need the column information */
2772 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2774 /* Iterate through all the nodes, seeing if they have text that matches. */
2776 mdata->frame_matched = FALSE;
2777 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2778 epan_dissect_cleanup(&edt);
2779 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2783 match_subtree_text(proto_node *node, gpointer data)
2785 match_data *mdata = (match_data*) data;
2786 const gchar *string = mdata->string;
2787 size_t string_len = mdata->string_len;
2788 capture_file *cf = mdata->cf;
2789 field_info *fi = PNODE_FINFO(node);
2790 gchar label_str[ITEM_LABEL_LENGTH];
2797 g_assert(fi && "dissection with an invisible proto tree?");
2799 if (mdata->frame_matched) {
2800 /* We already had a match; don't bother doing any more work. */
2804 /* Don't match invisible entries. */
2805 if (PROTO_ITEM_IS_HIDDEN(node))
2808 /* was a free format label produced? */
2810 label_ptr = fi->rep->representation;
2812 /* no, make a generic label */
2813 label_ptr = label_str;
2814 proto_item_fill_label(fi, label_str);
2817 /* Does that label match? */
2818 label_len = strlen(label_ptr);
2819 for (i = 0; i < label_len; i++) {
2820 c_char = label_ptr[i];
2822 c_char = toupper(c_char);
2823 if (c_char == string[c_match]) {
2825 if (c_match == string_len) {
2826 /* No need to look further; we have a match */
2827 mdata->frame_matched = TRUE;
2835 /* Recurse into the subtree, if it exists */
2836 if (node->first_child != NULL)
2837 proto_tree_children_foreach(node, match_subtree_text, mdata);
2841 cf_find_packet_summary_line(capture_file *cf, const char *string,
2842 search_direction dir)
2846 mdata.string = string;
2847 mdata.string_len = strlen(string);
2848 return find_packet(cf, match_summary_line, &mdata, dir);
2852 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2854 match_data *mdata = criterion;
2855 const gchar *string = mdata->string;
2856 size_t string_len = mdata->string_len;
2858 const char *info_column;
2859 size_t info_column_len;
2860 match_result result = MR_NOTMATCHED;
2866 /* Load the frame's data. */
2867 if (!cf_read_frame(cf, fdata)) {
2868 /* Attempt to get the packet failed. */
2872 /* Don't bother constructing the protocol tree */
2873 epan_dissect_init(&edt, FALSE, FALSE);
2874 /* Get the column information */
2875 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2877 /* Find the Info column */
2878 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2879 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2880 /* Found it. See if we match. */
2881 info_column = edt.pi.cinfo->col_data[colx];
2882 info_column_len = strlen(info_column);
2883 for (i = 0; i < info_column_len; i++) {
2884 c_char = info_column[i];
2886 c_char = toupper(c_char);
2887 if (c_char == string[c_match]) {
2889 if (c_match == string_len) {
2890 result = MR_MATCHED;
2899 epan_dissect_cleanup(&edt);
2906 } cbs_t; /* "Counted byte string" */
2909 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
2910 search_direction dir)
2915 info.data_len = string_size;
2917 /* String or hex search? */
2919 /* String search - what type of string? */
2920 switch (cf->scs_type) {
2922 case SCS_ASCII_AND_UNICODE:
2923 return find_packet(cf, match_ascii_and_unicode, &info, dir);
2926 return find_packet(cf, match_ascii, &info, dir);
2929 return find_packet(cf, match_unicode, &info, dir);
2932 g_assert_not_reached();
2936 return find_packet(cf, match_binary, &info, dir);
2940 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2942 cbs_t *info = criterion;
2943 const guint8 *ascii_text = info->data;
2944 size_t textlen = info->data_len;
2945 match_result result;
2951 /* Load the frame's data. */
2952 if (!cf_read_frame(cf, fdata)) {
2953 /* Attempt to get the packet failed. */
2957 result = MR_NOTMATCHED;
2958 buf_len = fdata->pkt_len;
2959 for (i = 0; i < buf_len; i++) {
2962 c_char = toupper(c_char);
2964 if (c_char == ascii_text[c_match]) {
2966 if (c_match == textlen) {
2967 result = MR_MATCHED;
2968 cf->search_pos = i; /* Save the position of the last character
2969 for highlighting the field. */
2980 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2982 cbs_t *info = criterion;
2983 const guint8 *ascii_text = info->data;
2984 size_t textlen = info->data_len;
2985 match_result result;
2991 /* Load the frame's data. */
2992 if (!cf_read_frame(cf, fdata)) {
2993 /* Attempt to get the packet failed. */
2997 result = MR_NOTMATCHED;
2998 buf_len = fdata->pkt_len;
2999 for (i = 0; i < buf_len; i++) {
3002 c_char = toupper(c_char);
3003 if (c_char == ascii_text[c_match]) {
3005 if (c_match == textlen) {
3006 result = MR_MATCHED;
3007 cf->search_pos = i; /* Save the position of the last character
3008 for highlighting the field. */
3018 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3020 cbs_t *info = criterion;
3021 const guint8 *ascii_text = info->data;
3022 size_t textlen = info->data_len;
3023 match_result result;
3029 /* Load the frame's data. */
3030 if (!cf_read_frame(cf, fdata)) {
3031 /* Attempt to get the packet failed. */
3035 result = MR_NOTMATCHED;
3036 buf_len = fdata->pkt_len;
3037 for (i = 0; i < buf_len; i++) {
3040 c_char = toupper(c_char);
3041 if (c_char == ascii_text[c_match]) {
3044 if (c_match == textlen) {
3045 result = MR_MATCHED;
3046 cf->search_pos = i; /* Save the position of the last character
3047 for highlighting the field. */
3057 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3059 cbs_t *info = criterion;
3060 const guint8 *binary_data = info->data;
3061 size_t datalen = info->data_len;
3062 match_result result;
3067 /* Load the frame's data. */
3068 if (!cf_read_frame(cf, fdata)) {
3069 /* Attempt to get the packet failed. */
3073 result = MR_NOTMATCHED;
3074 buf_len = fdata->pkt_len;
3075 for (i = 0; i < buf_len; i++) {
3076 if (cf->pd[i] == binary_data[c_match]) {
3078 if (c_match == datalen) {
3079 result = MR_MATCHED;
3080 cf->search_pos = i; /* Save the position of the last character
3081 for highlighting the field. */
3091 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3092 search_direction dir)
3094 return find_packet(cf, match_dfilter, sfcode, dir);
3098 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3099 search_direction dir)
3104 if (!dfilter_compile(filter, &sfcode)) {
3106 * XXX - this shouldn't happen, as the filter string is machine
3111 if (sfcode == NULL) {
3113 * XXX - this shouldn't happen, as the filter string is machine
3118 result = find_packet(cf, match_dfilter, sfcode, dir);
3119 dfilter_free(sfcode);
3124 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3126 dfilter_t *sfcode = criterion;
3128 match_result result;
3130 /* Load the frame's data. */
3131 if (!cf_read_frame(cf, fdata)) {
3132 /* Attempt to get the packet failed. */
3136 epan_dissect_init(&edt, TRUE, FALSE);
3137 epan_dissect_prime_dfilter(&edt, sfcode);
3138 epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3139 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3140 epan_dissect_cleanup(&edt);
3145 cf_find_packet_marked(capture_file *cf, search_direction dir)
3147 return find_packet(cf, match_marked, NULL, dir);
3151 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3153 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3157 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3159 return find_packet(cf, match_time_reference, NULL, dir);
3163 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3165 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3169 find_packet(capture_file *cf,
3170 match_result (*match_function)(capture_file *, frame_data *, void *),
3171 void *criterion, search_direction dir)
3173 frame_data *start_fd;
3176 frame_data *new_fd = NULL;
3177 progdlg_t *progbar = NULL;
3182 GTimeVal start_time;
3183 gchar status_str[100];
3184 int progbar_nextstep;
3185 int progbar_quantum;
3187 match_result result;
3189 start_fd = cf->current_frame;
3190 if (start_fd != NULL) {
3191 /* Iterate through the list of packets, starting at the packet we've
3192 picked, calling a routine to run the filter on the packet, see if
3193 it matches, and stop if so. */
3195 framenum = start_fd->num;
3197 /* Update the progress bar when it gets to this value. */
3198 progbar_nextstep = 0;
3199 /* When we reach the value that triggers a progress bar update,
3200 bump that value by this amount. */
3201 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3202 /* Progress so far. */
3206 g_get_current_time(&start_time);
3208 title = cf->sfilter?cf->sfilter:"";
3210 /* Create the progress bar if necessary.
3211 We check on every iteration of the loop, so that it takes no
3212 longer than the standard time to create it (otherwise, for a
3213 large file, we might take considerably longer than that standard
3214 time in order to get to the next progress bar step). */
3215 if (progbar == NULL)
3216 progbar = delayed_create_progress_dlg("Searching", title,
3217 FALSE, &stop_flag, &start_time, progbar_val);
3219 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3220 when we update it, we have to run the GTK+ main loop to get it
3221 to repaint what's pending, and doing so may involve an "ioctl()"
3222 to see if there's any pending input from an X server, and doing
3223 that for every packet can be costly, especially on a big file. */
3224 if (count >= progbar_nextstep) {
3225 /* let's not divide by zero. I should never be started
3226 * with count == 0, so let's assert that
3228 g_assert(cf->count > 0);
3230 progbar_val = (gfloat) count / cf->count;
3232 if (progbar != NULL) {
3233 g_snprintf(status_str, sizeof(status_str),
3234 "%4u of %u packets", count, cf->count);
3235 update_progress_dlg(progbar, progbar_val, status_str);
3238 progbar_nextstep += progbar_quantum;
3242 /* Well, the user decided to abort the search. Go back to the
3243 frame where we started. */
3248 /* Go past the current frame. */
3249 if (dir == SD_BACKWARD) {
3250 /* Go on to the previous frame. */
3251 if (framenum == 1) {
3253 * XXX - other apps have a bit more of a detailed message
3254 * for this, and instead of offering "OK" and "Cancel",
3255 * they offer things such as "Continue" and "Cancel";
3256 * we need an API for popping up alert boxes with
3257 * {Verb} and "Cancel".
3260 if (prefs.gui_find_wrap)
3262 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3263 framenum = cf->count; /* wrap around */
3267 statusbar_push_temporary_msg("Search reached the beginning.");
3268 framenum = start_fd->num; /* stay on previous packet */
3273 /* Go on to the next frame. */
3274 if (framenum == cf->count) {
3275 if (prefs.gui_find_wrap)
3277 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3278 framenum = 1; /* wrap around */
3282 statusbar_push_temporary_msg("Search reached the end.");
3283 framenum = start_fd->num; /* stay on previous packet */
3288 fdata = frame_data_sequence_find(cf->frames, framenum);
3292 /* Is this packet in the display? */
3293 if (fdata->flags.passed_dfilter) {
3294 /* Yes. Does it match the search criterion? */
3295 result = (*match_function)(cf, fdata, criterion);
3296 if (result == MR_ERROR) {
3297 /* Error; our caller has reported the error. Go back to the frame
3298 where we started. */
3301 } else if (result == MR_MATCHED) {
3302 /* Yes. Go to the new frame. */
3308 if (fdata == start_fd) {
3309 /* We're back to the frame we were on originally, and that frame
3310 doesn't match the search filter. The search failed. */
3315 /* We're done scanning the packets; destroy the progress bar if it
3317 if (progbar != NULL)
3318 destroy_progress_dlg(progbar);
3321 if (new_fd != NULL) {
3322 /* Find and select */
3323 cf->search_in_progress = TRUE;
3324 found = new_packet_list_select_row_from_data(new_fd);
3325 cf->search_in_progress = FALSE;
3326 cf->search_pos = 0; /* Reset the position */
3328 /* We didn't find a row corresponding to this frame.
3329 This means that the frame isn't being displayed currently,
3330 so we can't select it. */
3331 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3332 "%sEnd of capture exceeded!%s\n\n"
3333 "The capture file is probably not fully dissected.",
3334 simple_dialog_primary_start(), simple_dialog_primary_end());
3337 return TRUE; /* success */
3339 return FALSE; /* failure */
3343 cf_goto_frame(capture_file *cf, guint fnumber)
3347 fdata = frame_data_sequence_find(cf->frames, fnumber);
3349 if (fdata == NULL) {
3350 /* we didn't find a packet with that packet number */
3351 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3352 return FALSE; /* we failed to go to that packet */
3354 if (!fdata->flags.passed_dfilter) {
3355 /* that packet currently isn't displayed */
3356 /* XXX - add it to the set of displayed packets? */
3357 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3358 return FALSE; /* we failed to go to that packet */
3361 if (!new_packet_list_select_row_from_data(fdata)) {
3362 /* We didn't find a row corresponding to this frame.
3363 This means that the frame isn't being displayed currently,
3364 so we can't select it. */
3365 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3366 "%sEnd of capture exceeded!%s\n\n"
3367 "The capture file is probably not fully dissected.",
3368 simple_dialog_primary_start(), simple_dialog_primary_end());
3371 return TRUE; /* we got to that packet */
3377 /* Find and select */
3378 new_packet_list_select_first_row();
3379 return TRUE; /* we got to that packet */
3383 cf_goto_bottom_frame()
3385 /* Find and select */
3386 new_packet_list_select_last_row();
3387 return TRUE; /* we got to that packet */
3391 * Go to frame specified by currently selected protocol tree item.
3394 cf_goto_framenum(capture_file *cf)
3396 header_field_info *hfinfo;
3399 if (cf->finfo_selected) {
3400 hfinfo = cf->finfo_selected->hfinfo;
3402 if (hfinfo->type == FT_FRAMENUM) {
3403 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3405 return cf_goto_frame(cf, framenum);
3412 /* Select the packet on a given row. */
3414 cf_select_packet(capture_file *cf, int row)
3418 /* Get the frame data struct pointer for this frame */
3419 fdata = new_packet_list_get_row_data(row);
3421 if (fdata == NULL) {
3422 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3423 the first entry is added to it by "real_insert_row()", that row
3424 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3425 our version and the vanilla GTK+ version).
3427 This means that a "select-row" signal is emitted; this causes
3428 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3431 "cf_select_packet()" fetches, above, the data associated with the
3432 row that was selected; however, as "gtk_clist_append()", which
3433 called "real_insert_row()", hasn't yet returned, we haven't yet
3434 associated any data with that row, so we get back a null pointer.
3436 We can't assume that there's only one frame in the frame list,
3437 either, as we may be filtering the display.
3439 We therefore assume that, if "row" is 0, i.e. the first row
3440 is being selected, and "cf->first_displayed" equals
3441 "cf->last_displayed", i.e. there's only one frame being
3442 displayed, that frame is the frame we want.
3444 This means we have to set "cf->first_displayed" and
3445 "cf->last_displayed" before adding the row to the
3446 GtkCList; see the comment in "add_packet_to_packet_list()". */
3448 if (row == 0 && cf->first_displayed == cf->last_displayed)
3449 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3452 /* If fdata _still_ isn't set simply give up. */
3453 if (fdata == NULL) {
3457 /* Get the data in that frame. */
3458 if (!cf_read_frame (cf, fdata)) {
3462 /* Record that this frame is the current frame. */
3463 cf->current_frame = fdata;
3464 cf->current_row = row;
3466 /* Create the logical protocol tree. */
3467 if (cf->edt != NULL)
3468 epan_dissect_free(cf->edt);
3470 /* We don't need the columns here. */
3471 cf->edt = epan_dissect_new(TRUE, TRUE);
3473 tap_build_interesting(cf->edt);
3474 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3477 dfilter_macro_build_ftv_cache(cf->edt->tree);
3479 cf_callback_invoke(cf_cb_packet_selected, cf);
3482 /* Unselect the selected packet, if any. */
3484 cf_unselect_packet(capture_file *cf)
3486 /* Destroy the epan_dissect_t for the unselected packet. */
3487 if (cf->edt != NULL) {
3488 epan_dissect_free(cf->edt);
3492 /* No packet is selected. */
3493 cf->current_frame = NULL;
3494 cf->current_row = 0;
3496 cf_callback_invoke(cf_cb_packet_unselected, cf);
3498 /* No protocol tree means no selected field. */
3499 cf_unselect_field(cf);
3502 /* Unset the selected protocol tree field, if any. */
3504 cf_unselect_field(capture_file *cf)
3506 cf->finfo_selected = NULL;
3508 cf_callback_invoke(cf_cb_field_unselected, cf);
3512 * Mark a particular frame.
3515 cf_mark_frame(capture_file *cf, frame_data *frame)
3517 if (! frame->flags.marked) {
3518 frame->flags.marked = TRUE;
3519 if (cf->count > cf->marked_count)
3525 * Unmark a particular frame.
3528 cf_unmark_frame(capture_file *cf, frame_data *frame)
3530 if (frame->flags.marked) {
3531 frame->flags.marked = FALSE;
3532 if (cf->marked_count > 0)
3538 * Ignore a particular frame.
3541 cf_ignore_frame(capture_file *cf, frame_data *frame)
3543 if (! frame->flags.ignored) {
3544 frame->flags.ignored = TRUE;
3545 if (cf->count > cf->ignored_count)
3546 cf->ignored_count++;
3551 * Un-ignore a particular frame.
3554 cf_unignore_frame(capture_file *cf, frame_data *frame)
3556 if (frame->flags.ignored) {
3557 frame->flags.ignored = FALSE;
3558 if (cf->ignored_count > 0)
3559 cf->ignored_count--;
3566 } save_callback_args_t;
3569 * Save a capture to a file, in a particular format, saving either
3570 * all packets, all currently-displayed packets, or all marked packets.
3572 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3573 * up a message box for the failure.
3576 save_packet(capture_file *cf _U_, frame_data *fdata,
3577 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3580 save_callback_args_t *args = argsp;
3581 struct wtap_pkthdr hdr;
3584 /* init the wtap header for saving */
3585 hdr.ts.secs = fdata->abs_ts.secs;
3586 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3587 hdr.caplen = fdata->cap_len;
3588 hdr.len = fdata->pkt_len;
3589 hdr.pkt_encap = fdata->lnk_t;
3591 /* and save the packet */
3592 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3593 cf_write_failure_alert_box(args->fname, err);
3600 * Can this capture file be saved in any format except by copying the raw data?
3603 cf_can_save_as(capture_file *cf)
3607 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
3608 /* To save a file with Wiretap, Wiretap has to handle that format,
3609 and its code to handle that format must be able to write a file
3610 with this file's encapsulation type. */
3611 if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
3612 /* OK, we can write it out in this type. */
3617 /* No, we couldn't save it in any format. */
3622 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3624 gchar *from_filename;
3628 save_callback_args_t callback_args;
3630 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
3632 /* don't write over an existing file. */
3633 /* this should've been already checked by our caller, just to be sure... */
3634 if (file_exists(fname)) {
3635 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3636 "%sCapture file: \"%s\" already exists!%s\n\n"
3637 "Please choose a different filename.",
3638 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3642 packet_range_process_init(range);
3644 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3645 /* We're not filtering packets, and we're saving it in the format
3646 it's already in, so we can just move or copy the raw data. */
3648 if (cf->is_tempfile) {
3649 /* The file being saved is a temporary file from a live
3650 capture, so it doesn't need to stay around under that name;
3651 first, try renaming the capture buffer file to the new name. */
3653 if (ws_rename(cf->filename, fname) == 0) {
3654 /* That succeeded - there's no need to copy the source file. */
3655 from_filename = NULL;
3658 if (errno == EXDEV) {
3659 /* They're on different file systems, so we have to copy the
3662 from_filename = cf->filename;
3664 /* The rename failed, but not because they're on different
3665 file systems - put up an error message. (Or should we
3666 just punt and try to copy? The only reason why I'd
3667 expect the rename to fail and the copy to succeed would
3668 be if we didn't have permission to remove the file from
3669 the temporary directory, and that might be fixable - but
3670 is it worth requiring the user to go off and fix it?) */
3671 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3672 file_rename_error_message(errno), fname);
3678 from_filename = cf->filename;
3681 /* It's a permanent file, so we should copy it, and not remove the
3684 from_filename = cf->filename;
3688 /* Copy the file, if we haven't moved it. */
3689 if (!copy_file_binary_mode(from_filename, fname))
3693 /* Either we're filtering packets, or we're saving in a different
3694 format; we can't do that by copying or moving the capture file,
3695 we have to do it by writing the packets out in Wiretap. */
3696 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3699 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3703 /* XXX - we let the user save a subset of the packets.
3705 If we do that, should we make that file the current file? If so,
3706 it means we can no longer get at the other packets. What does
3709 /* Iterate through the list of packets, processing the packets we were
3712 XXX - we've already called "packet_range_process_init(range)", but
3713 "process_specified_packets()" will do it again. Fortunately,
3714 that's harmless in this case, as we haven't done anything to
3715 "range" since we initialized it. */
3716 callback_args.pdh = pdh;
3717 callback_args.fname = fname;
3718 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3719 TRUE, save_packet, &callback_args)) {
3722 /* Completed successfully. */
3726 /* The user decided to abort the saving.
3727 XXX - remove the output file? */
3731 /* Error while saving. */
3732 wtap_dump_close(pdh, &err);
3736 if (!wtap_dump_close(pdh, &err)) {
3737 cf_close_failure_alert_box(fname, err);
3742 cf_callback_invoke(cf_cb_file_save_finished, NULL);
3744 if (packet_range_process_all(range)) {
3745 /* We saved the entire capture, not just some packets from it.
3746 Open and read the file we saved it to.
3748 XXX - this is somewhat of a waste; we already have the
3749 packets, all this gets us is updated file type information
3750 (which we could just stuff into "cf"), and having the new
3751 file be the one we have opened and from which we're reading
3752 the data, and it means we have to spend time opening and
3753 reading the file, which could be a significant amount of
3754 time if the file is large. */
3755 cf->user_saved = TRUE;
3757 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3758 /* XXX - report errors if this fails?
3759 What should we return if it fails or is aborted? */
3761 switch (cf_read(cf, TRUE)) {
3765 /* Just because we got an error, that doesn't mean we were unable
3766 to read any of the file; we handle what we could get from the
3770 case CF_READ_ABORTED:
3771 /* The user bailed out of re-reading the capture file; the
3772 capture file has been closed - just return (without
3773 changing any menu settings; "cf_close()" set them
3774 correctly for the "no capture file open" state). */
3777 cf_callback_invoke(cf_cb_file_save_reload_finished, cf);
3783 cf_callback_invoke(cf_cb_file_save_failed, NULL);
3788 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3789 gboolean for_writing, int file_type)
3792 /* Wiretap error. */
3795 case WTAP_ERR_NOT_REGULAR_FILE:
3796 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3797 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3801 case WTAP_ERR_RANDOM_OPEN_PIPE:
3802 /* Seen only when opening a capture file for reading. */
3803 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3804 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
3808 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3809 /* Seen only when opening a capture file for reading. */
3810 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3811 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
3815 case WTAP_ERR_UNSUPPORTED:
3816 /* Seen only when opening a capture file for reading. */
3817 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3818 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
3820 filename, err_info);
3824 case WTAP_ERR_CANT_WRITE_TO_PIPE:
3825 /* Seen only when opening a capture file for writing. */
3826 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3827 "The file \"%s\" is a pipe, and %s capture files can't be "
3828 "written to a pipe.",
3829 filename, wtap_file_type_string(file_type));
3832 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3833 /* Seen only when opening a capture file for writing. */
3834 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3835 "Wireshark doesn't support writing capture files in that format.");
3838 case WTAP_ERR_UNSUPPORTED_ENCAP:
3840 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3841 "Wireshark can't save this capture in that format.");
3843 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3844 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
3846 filename, err_info);
3851 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3853 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3854 "Wireshark can't save this capture in that format.");
3856 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3857 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
3862 case WTAP_ERR_BAD_RECORD:
3863 /* Seen only when opening a capture file for reading. */
3864 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3865 "The file \"%s\" appears to be damaged or corrupt.\n"
3867 filename, err_info);
3871 case WTAP_ERR_CANT_OPEN:
3873 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3874 "The file \"%s\" could not be created for some unknown reason.",
3877 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3878 "The file \"%s\" could not be opened for some unknown reason.",
3883 case WTAP_ERR_SHORT_READ:
3884 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3885 "The file \"%s\" appears to have been cut short"
3886 " in the middle of a packet or other data.",
3890 case WTAP_ERR_SHORT_WRITE:
3891 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3892 "A full header couldn't be written to the file \"%s\".",
3896 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
3897 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3898 "Gzip compression not supported by this file type.");
3901 case WTAP_ERR_DECOMPRESS:
3902 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3903 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
3904 "(%s)", filename, err_info);
3909 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3910 "The file \"%s\" could not be %s: %s.",
3912 for_writing ? "created" : "opened",
3913 wtap_strerror(err));
3918 open_failure_alert_box(filename, err, for_writing);
3923 file_rename_error_message(int err)
3926 static char errmsg_errno[1024+1];
3931 errmsg = "The path to the file \"%s\" doesn't exist.";
3935 errmsg = "You don't have permission to move the capture file to \"%s\".";
3939 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3940 "The file \"%%s\" could not be moved: %s.",
3941 wtap_strerror(err));
3942 errmsg = errmsg_errno;
3949 cf_write_failure_alert_box(const char *filename, int err)
3952 /* Wiretap error. */
3953 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3954 "An error occurred while writing to the file \"%s\": %s.",
3955 filename, wtap_strerror(err));
3958 write_failure_alert_box(filename, err);
3962 /* Check for write errors - if the file is being written to an NFS server,
3963 a write error may not show up until the file is closed, as NFS clients
3964 might not send writes to the server until the "write()" call finishes,
3965 so that the write may fail on the server but the "write()" may succeed. */
3967 cf_close_failure_alert_box(const char *filename, int err)
3970 /* Wiretap error. */
3973 case WTAP_ERR_CANT_CLOSE:
3974 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3975 "The file \"%s\" couldn't be closed for some unknown reason.",
3979 case WTAP_ERR_SHORT_WRITE:
3980 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3981 "Not all the packets could be written to the file \"%s\".",
3986 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3987 "An error occurred while closing the file \"%s\": %s.",
3988 filename, wtap_strerror(err));
3993 We assume that a close error from the OS is really a write error. */
3994 write_failure_alert_box(filename, err);
3998 /* Reload the current capture file. */
4000 cf_reload(capture_file *cf) {
4002 gboolean is_tempfile;
4005 /* If the file could be opened, "cf_open()" calls "cf_close()"
4006 to get rid of state for the old capture file before filling in state
4007 for the new capture file. "cf_close()" will remove the file if
4008 it's a temporary file; we don't want that to happen (for one thing,
4009 it'd prevent subsequent reopens from working). Remember whether it's
4010 a temporary file, mark it as not being a temporary file, and then
4011 reopen it as the type of file it was.
4013 Also, "cf_close()" will free "cf->filename", so we must make
4014 a copy of it first. */
4015 filename = g_strdup(cf->filename);
4016 is_tempfile = cf->is_tempfile;
4017 cf->is_tempfile = FALSE;
4018 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4019 switch (cf_read(cf, FALSE)) {
4023 /* Just because we got an error, that doesn't mean we were unable
4024 to read any of the file; we handle what we could get from the
4028 case CF_READ_ABORTED:
4029 /* The user bailed out of re-reading the capture file; the
4030 capture file has been closed - just free the capture file name
4031 string and return (without changing the last containing
4037 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4038 Instead, the file was left open, so we should restore "cf->is_tempfile"
4041 XXX - change the menu? Presumably "cf_open()" will do that;
4042 make sure it does! */
4043 cf->is_tempfile = is_tempfile;
4045 /* "cf_open()" made a copy of the file name we handed it, so
4046 we should free up our copy. */
4056 * indent-tabs-mode: nil
4059 * ex: set shiftwidth=2 tabstop=8 expandtab
4060 * :indentSize=2:tabSize=8:noTabs=true: