4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include <wsutil/tempfile.h>
34 #include <wsutil/file_util.h>
35 #include <wsutil/filesystem.h>
36 #include <ws_version_info.h>
38 #include <wiretap/merge.h>
40 #include <epan/exceptions.h>
41 #include <epan/epan-int.h>
42 #include <epan/epan.h>
43 #include <epan/column.h>
44 #include <epan/packet.h>
45 #include <epan/column-utils.h>
46 #include <epan/expert.h>
47 #include <epan/prefs.h>
48 #include <epan/dfilter/dfilter.h>
49 #include <epan/epan_dissect.h>
51 #include <epan/dissectors/packet-ber.h>
52 #include <epan/timestamp.h>
53 #include <epan/dfilter/dfilter-macro.h>
54 #include <epan/strutil.h>
55 #include <epan/addr_resolv.h>
56 #include <epan/color_filters.h>
61 #include "frame_tvbuff.h"
63 #include "ui/alert_box.h"
64 #include "ui/simple_dialog.h"
65 #include "ui/main_statusbar.h"
66 #include "ui/progress_dlg.h"
67 #include "ui/ui_util.h"
69 /* Needed for addrinfo */
70 #ifdef HAVE_SYS_TYPES_H
71 # include <sys/types.h>
74 #ifdef HAVE_SYS_SOCKET_H
75 #include <sys/socket.h>
78 #ifdef HAVE_NETINET_IN_H
79 # include <netinet/in.h>
86 #ifdef HAVE_WINSOCK2_H
87 # include <winsock2.h>
91 # include <ws2tcpip.h>
95 gboolean auto_scroll_live; /* GTK+ only? */
98 static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
99 column_info *cinfo, gint64 offset);
101 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
108 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
110 static void match_subtree_text(proto_node *node, gpointer data);
111 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
113 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
115 static match_result match_narrow(capture_file *cf, frame_data *fdata,
117 static match_result match_wide(capture_file *cf, frame_data *fdata,
119 static match_result match_binary(capture_file *cf, frame_data *fdata,
121 static match_result match_regex(capture_file *cf, frame_data *fdata,
123 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
125 static match_result match_marked(capture_file *cf, frame_data *fdata,
127 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
129 static gboolean find_packet(capture_file *cf,
130 match_result (*match_function)(capture_file *, frame_data *, void *),
131 void *criterion, search_direction dir);
133 static const char *cf_get_user_packet_comment(capture_file *cf, const frame_data *fd);
135 static void cf_open_failure_alert_box(const char *filename, int err,
136 gchar *err_info, gboolean for_writing,
138 static void cf_rename_failure_alert_box(const char *filename, int err);
139 static void cf_close_failure_alert_box(const char *filename, int err);
140 static void ref_time_packets(capture_file *cf);
142 /* Seconds spent processing packets between pushing UI updates. */
143 #define PROGBAR_UPDATE_INTERVAL 0.150
145 /* Show the progress bar after this many seconds. */
146 #define PROGBAR_SHOW_DELAY 0.5
149 * We could probably use g_signal_...() instead of the callbacks below but that
150 * would require linking our CLI programs to libgobject and creating an object
151 * instance for the signals.
154 cf_callback_t cb_fct;
156 } cf_callback_data_t;
158 static GList *cf_callbacks = NULL;
161 cf_callback_invoke(int event, gpointer data)
163 cf_callback_data_t *cb;
164 GList *cb_item = cf_callbacks;
166 /* there should be at least one interested */
167 g_assert(cb_item != NULL);
169 while (cb_item != NULL) {
170 cb = (cf_callback_data_t *)cb_item->data;
171 cb->cb_fct(event, data, cb->user_data);
172 cb_item = g_list_next(cb_item);
178 cf_callback_add(cf_callback_t func, gpointer user_data)
180 cf_callback_data_t *cb;
182 cb = g_new(cf_callback_data_t,1);
184 cb->user_data = user_data;
186 cf_callbacks = g_list_prepend(cf_callbacks, cb);
190 cf_callback_remove(cf_callback_t func, gpointer user_data)
192 cf_callback_data_t *cb;
193 GList *cb_item = cf_callbacks;
195 while (cb_item != NULL) {
196 cb = (cf_callback_data_t *)cb_item->data;
197 if (cb->cb_fct == func && cb->user_data == user_data) {
198 cf_callbacks = g_list_remove(cf_callbacks, cb);
202 cb_item = g_list_next(cb_item);
205 g_assert_not_reached();
209 cf_timestamp_auto_precision(capture_file *cf)
213 /* don't try to get the file's precision if none is opened */
214 if (cf->state == FILE_CLOSED) {
218 /* Set the column widths of those columns that show the time in
219 "command-line-specified" format. */
220 for (i = 0; i < cf->cinfo.num_cols; i++) {
221 if (col_has_time_fmt(&cf->cinfo, i)) {
222 packet_list_resize_column(i);
228 cf_get_computed_elapsed(capture_file *cf)
230 return cf->computed_elapsed;
234 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
237 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
242 g_get_current_time(&time_now);
244 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
245 time_now.tv_usec - start_time->tv_usec;
247 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
250 static const nstime_t *
251 ws_get_frame_ts(void *data, guint32 frame_num)
253 capture_file *cf = (capture_file *) data;
255 if (cf->prev_dis && cf->prev_dis->num == frame_num)
256 return &cf->prev_dis->abs_ts;
258 if (cf->prev_cap && cf->prev_cap->num == frame_num)
259 return &cf->prev_cap->abs_ts;
262 frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
264 return (fd) ? &fd->abs_ts : NULL;
271 ws_get_user_comment(void *data, const frame_data *fd)
273 capture_file *cf = (capture_file *) data;
275 return cf_get_user_packet_comment(cf, fd);
279 ws_epan_new(capture_file *cf)
281 epan_t *epan = epan_new();
284 epan->get_frame_ts = ws_get_frame_ts;
285 epan->get_interface_name = cap_file_get_interface_name;
286 epan->get_user_comment = ws_get_user_comment;
292 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
297 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
301 /* The open succeeded. Close whatever capture file we had open,
302 and fill in the information for this file. */
305 /* Initialize the packet header. */
306 wtap_phdr_init(&cf->phdr);
308 /* XXX - we really want to initialize this after we've read all
309 the packets, so we know how much we'll ultimately need. */
310 ws_buffer_init(&cf->buf, 1500);
312 /* Create new epan session for dissection.
313 * (The old one was freed in cf_close().)
315 cf->epan = ws_epan_new(cf);
317 /* We're about to start reading the file. */
318 cf->state = FILE_READ_IN_PROGRESS;
323 /* Set the file name because we need it to set the follow stream filter.
324 XXX - is that still true? We need it for other reasons, though,
326 cf->filename = g_strdup(fname);
328 /* Indicate whether it's a permanent or temporary file. */
329 cf->is_tempfile = is_tempfile;
331 /* No user changes yet. */
332 cf->unsaved_changes = FALSE;
334 cf->computed_elapsed = 0;
336 cf->cd_t = wtap_file_type_subtype(cf->wth);
337 cf->open_type = type;
338 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
340 cf->packet_comment_count = 0;
341 cf->displayed_count = 0;
342 cf->marked_count = 0;
343 cf->ignored_count = 0;
344 cf->ref_time_count = 0;
345 cf->drops_known = FALSE;
347 cf->snap = wtap_snapshot_length(cf->wth);
349 /* Snapshot length not known. */
350 cf->has_snap = FALSE;
351 cf->snap = WTAP_MAX_PACKET_SIZE;
355 /* Allocate a frame_data_sequence for the frames in this file */
356 cf->frames = new_frame_data_sequence();
358 nstime_set_zero(&cf->elapsed_time);
364 packet_list_queue_draw();
365 cf_callback_invoke(cf_cb_file_opened, cf);
367 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
368 /* tell the BER dissector the file name */
369 ber_set_filename(cf->filename);
372 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
373 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
378 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
383 * Add an encapsulation type to cf->linktypes.
386 cf_add_encapsulation_type(capture_file *cf, int encap)
390 for (i = 0; i < cf->linktypes->len; i++) {
391 if (g_array_index(cf->linktypes, gint, i) == encap)
392 return; /* it's already there */
394 /* It's not already there - add it. */
395 g_array_append_val(cf->linktypes, encap);
398 /* Reset everything to a pristine state */
400 cf_close(capture_file *cf)
402 cf->stop_flag = FALSE;
403 if (cf->state == FILE_CLOSED)
404 return; /* Nothing to do */
406 /* Die if we're in the middle of reading a file. */
407 g_assert(cf->state != FILE_READ_IN_PROGRESS);
409 cf_callback_invoke(cf_cb_file_closing, cf);
411 /* close things, if not already closed before */
412 color_filters_cleanup();
418 /* We have no file open... */
419 if (cf->filename != NULL) {
420 /* If it's a temporary file, remove it. */
422 ws_unlink(cf->filename);
423 g_free(cf->filename);
426 /* ...which means we have no changes to that file to save. */
427 cf->unsaved_changes = FALSE;
429 /* no open_routine type */
430 cf->open_type = WTAP_TYPE_AUTO;
432 /* Clean up the packet header. */
433 wtap_phdr_cleanup(&cf->phdr);
435 /* Free up the packet buffer. */
436 ws_buffer_free(&cf->buf);
438 dfilter_free(cf->rfcode);
440 if (cf->frames != NULL) {
441 free_frame_data_sequence(cf->frames);
444 #ifdef WANT_PACKET_EDITOR
445 if (cf->edited_frames) {
446 g_tree_destroy(cf->edited_frames);
447 cf->edited_frames = NULL;
450 if (cf->frames_user_comments) {
451 g_tree_destroy(cf->frames_user_comments);
452 cf->frames_user_comments = NULL;
454 cf_unselect_packet(cf); /* nothing to select */
455 cf->first_displayed = 0;
456 cf->last_displayed = 0;
458 /* No frames, no frame selected, no field in that frame selected. */
460 cf->current_frame = 0;
462 cf->finfo_selected = NULL;
464 /* No frame link-layer types, either. */
465 if (cf->linktypes != NULL) {
466 g_array_free(cf->linktypes, TRUE);
467 cf->linktypes = NULL;
470 /* Clear the packet list. */
471 packet_list_freeze();
476 nstime_set_zero(&cf->elapsed_time);
478 reset_tap_listeners();
483 /* We have no file open. */
484 cf->state = FILE_CLOSED;
486 cf_callback_invoke(cf_cb_file_closed, cf);
490 * TRUE if the progress dialog doesn't exist and it looks like we'll
491 * take > 2s to load, FALSE otherwise.
493 static inline gboolean
494 progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
498 if (progdlg) return FALSE;
499 elapsed = g_timer_elapsed(prog_timer, NULL);
500 if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
501 || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
508 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
512 progbar_val = (gfloat) file_pos / (gfloat) size;
513 if (progbar_val > 1.0) {
515 /* The file probably grew while we were reading it.
516 * Update file size, and try again.
518 size = wtap_file_size(cf->wth, NULL);
521 progbar_val = (gfloat) file_pos / (gfloat) size;
523 /* If it's still > 1, either "wtap_file_size()" failed (in which
524 * case there's not much we can do about it), or the file
525 * *shrank* (in which case there's not much we can do about
526 * it); just clip the progress value at 1.0.
528 if (progbar_val > 1.0f)
532 g_snprintf(status_str, status_size,
533 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
534 file_pos / 1024, size / 1024);
540 cf_read(capture_file *cf, gboolean reloading)
543 gchar *err_info = NULL;
545 progdlg_t *volatile progbar = NULL;
546 GTimer *prog_timer = g_timer_new();
550 volatile gboolean create_proto_tree;
554 /* Compile the current display filter.
555 * We assume this will not fail since cf->dfilter is only set in
556 * cf_filter IFF the filter was valid.
558 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
559 g_assert(!cf->dfilter || (compiled && dfcode));
561 /* Get the union of the flags for all tap listeners. */
562 tap_flags = union_of_tap_listener_flags();
564 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
566 reset_tap_listeners();
568 name_ptr = g_filename_display_basename(cf->filename);
571 cf_callback_invoke(cf_cb_file_reload_started, cf);
573 cf_callback_invoke(cf_cb_file_read_started, cf);
575 /* Record whether the file is compressed.
576 XXX - do we know this at open time? */
577 cf->iscompressed = wtap_iscompressed(cf->wth);
579 /* The packet list window will be empty until the file is completly loaded */
580 packet_list_freeze();
582 cf->stop_flag = FALSE;
583 g_get_current_time(&start_time);
585 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
595 gchar status_str[100];
599 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
601 /* Find the size of the file. */
602 size = wtap_file_size(cf->wth, NULL);
604 g_timer_start(prog_timer);
606 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
609 file_pos = wtap_read_so_far(cf->wth);
611 /* Create the progress bar if necessary. */
612 if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
613 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
615 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
616 TRUE, &cf->stop_flag, &start_time, progbar_val);
618 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
619 TRUE, &cf->stop_flag, &start_time, progbar_val);
623 * Update the progress bar, but do it only after
624 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
625 * and packets_bar_update will likely trigger UI paint events, which
626 * might take a while depending on the platform and display. Reset
627 * our timer *after* painting.
629 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
630 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
631 /* update the packet bar content on the first run or frequently on very large files */
632 update_progress_dlg(progbar, progbar_val, status_str);
633 packets_bar_update();
634 g_timer_start(prog_timer);
639 /* Well, the user decided to abort the read. He/She will be warned and
640 it might be enough for him/her to work with the already loaded
642 This is especially true for very large capture files, where you don't
643 want to wait loading the whole file (which may last minutes or even
644 hours even on fast machines) just to see that it was the wrong file. */
647 read_packet(cf, dfcode, &edt, cinfo, data_offset);
650 CATCH(OutOfMemoryError) {
651 simple_message_box(ESD_TYPE_ERROR, NULL,
652 "More information and workarounds can be found at\n"
653 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
654 "Sorry, but Wireshark has run out of memory and has to terminate now.");
656 /* Could we close the current capture and free up memory from that? */
658 /* we have to terminate, as we cannot recover from the memory error */
664 /* Free the display name */
667 /* Cleanup and release all dfilter resources */
668 if (dfcode != NULL) {
669 dfilter_free(dfcode);
672 epan_dissect_cleanup(&edt);
674 /* We're done reading the file; destroy the progress bar if it was created. */
676 destroy_progress_dlg(progbar);
677 g_timer_destroy(prog_timer);
679 /* We're done reading sequentially through the file. */
680 cf->state = FILE_READ_DONE;
682 /* Close the sequential I/O side, to free up memory it requires. */
683 wtap_sequential_close(cf->wth);
685 /* Allow the protocol dissectors to free up memory that they
686 * don't need after the sequential run-through of the packets. */
687 postseq_cleanup_all_protocols();
689 /* compute the time it took to load the file */
690 compute_elapsed(cf, &start_time);
692 /* Set the file encapsulation type now; we don't know what it is until
693 we've looked at all the packets, as we don't know until then whether
694 there's more than one type (and thus whether it's
695 WTAP_ENCAP_PER_PACKET). */
696 cf->lnk_t = wtap_file_encap(cf->wth);
698 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
703 cf_callback_invoke(cf_cb_file_reload_finished, cf);
705 cf_callback_invoke(cf_cb_file_read_finished, cf);
707 /* If we have any displayed packets to select, select the first of those
708 packets by making the first row the selected row. */
709 if (cf->first_displayed != 0) {
710 packet_list_select_first_row();
714 simple_message_box(ESD_TYPE_WARN, NULL,
715 "The remaining packets in the file were discarded.\n"
717 "As a lot of packets from the original file will be missing,\n"
718 "remember to be careful when saving the current content to a file.\n",
719 "File loading was cancelled.");
720 return CF_READ_ERROR;
724 /* Put up a message box noting that the read failed somewhere along
725 the line. Don't throw out the stuff we managed to read, though,
729 case WTAP_ERR_UNSUPPORTED:
730 simple_error_message_box(
731 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
732 err_info != NULL ? err_info : "no information supplied");
736 case WTAP_ERR_SHORT_READ:
737 simple_error_message_box(
738 "The capture file appears to have been cut short"
739 " in the middle of a packet.");
742 case WTAP_ERR_BAD_FILE:
743 simple_error_message_box(
744 "The capture file appears to be damaged or corrupt.\n(%s)",
745 err_info != NULL ? err_info : "no information supplied");
749 case WTAP_ERR_DECOMPRESS:
750 simple_error_message_box(
751 "The compressed capture file appears to be damaged or corrupt.\n(%s)",
752 err_info != NULL ? err_info : "no information supplied");
757 simple_error_message_box(
758 "An error occurred while reading the"
759 " capture file: %s.", wtap_strerror(err));
762 return CF_READ_ERROR;
769 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
772 volatile int newly_displayed_packets = 0;
775 gboolean create_proto_tree;
779 /* Compile the current display filter.
780 * We assume this will not fail since cf->dfilter is only set in
781 * cf_filter IFF the filter was valid.
783 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
784 g_assert(!cf->dfilter || (compiled && dfcode));
786 /* Get the union of the flags for all tap listeners. */
787 tap_flags = union_of_tap_listener_flags();
789 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
793 packet_list_check_end();
794 /* Don't freeze/thaw the list when doing live capture */
795 /*packet_list_freeze();*/
797 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
799 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
802 gint64 data_offset = 0;
805 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
807 while (to_read != 0) {
808 wtap_cleareof(cf->wth);
809 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
812 if (cf->state == FILE_READ_ABORTED) {
813 /* Well, the user decided to exit Wireshark. Break out of the
814 loop, and let the code below (which is called even if there
815 aren't any packets left to read) exit. */
818 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
819 newly_displayed_packets++;
824 CATCH(OutOfMemoryError) {
825 simple_message_box(ESD_TYPE_ERROR, NULL,
826 "More information and workarounds can be found at\n"
827 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
828 "Sorry, but Wireshark has run out of memory and has to terminate now.");
830 /* Could we close the current capture and free up memory from that? */
831 return CF_READ_ABORTED;
833 /* we have to terminate, as we cannot recover from the memory error */
839 /* Update the file encapsulation; it might have changed based on the
840 packets we've read. */
841 cf->lnk_t = wtap_file_encap(cf->wth);
843 /* Cleanup and release all dfilter resources */
844 if (dfcode != NULL) {
845 dfilter_free(dfcode);
848 epan_dissect_cleanup(&edt);
850 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
851 cf->count, cf->state, *err);*/
853 /* Don't freeze/thaw the list when doing live capture */
854 /*packet_list_thaw();*/
855 /* With the new packet list the first packet
856 * isn't automatically selected.
858 if (!cf->current_frame)
859 packet_list_select_first_row();
861 /* moving to the end of the packet list - if the user requested so and
862 we have some new packets. */
863 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
864 packet_list_moveto_end();
866 if (cf->state == FILE_READ_ABORTED) {
867 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
868 so that our caller can kill off the capture child process;
869 this will cause an EOF on the pipe from the child, so
870 "cf_finish_tail()" will be called, and it will clean up
872 return CF_READ_ABORTED;
873 } else if (*err != 0) {
874 /* We got an error reading the capture file.
875 XXX - pop up a dialog box instead? */
876 if (err_info != NULL) {
877 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
878 wtap_strerror(*err), cf->filename, err_info);
881 g_warning("Error \"%s\" while reading \"%s\"",
882 wtap_strerror(*err), cf->filename);
884 return CF_READ_ERROR;
890 cf_fake_continue_tail(capture_file *cf) {
891 cf->state = FILE_READ_DONE;
895 cf_finish_tail(capture_file *cf, int *err)
902 gboolean create_proto_tree;
906 /* Compile the current display filter.
907 * We assume this will not fail since cf->dfilter is only set in
908 * cf_filter IFF the filter was valid.
910 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
911 g_assert(!cf->dfilter || (compiled && dfcode));
913 /* Get the union of the flags for all tap listeners. */
914 tap_flags = union_of_tap_listener_flags();
915 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
917 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
919 if (cf->wth == NULL) {
921 return CF_READ_ERROR;
924 packet_list_check_end();
925 /* Don't freeze/thaw the list when doing live capture */
926 /*packet_list_freeze();*/
928 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
930 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
931 if (cf->state == FILE_READ_ABORTED) {
932 /* Well, the user decided to abort the read. Break out of the
933 loop, and let the code below (which is called even if there
934 aren't any packets left to read) exit. */
937 read_packet(cf, dfcode, &edt, cinfo, data_offset);
940 /* Cleanup and release all dfilter resources */
941 if (dfcode != NULL) {
942 dfilter_free(dfcode);
945 epan_dissect_cleanup(&edt);
947 /* Don't freeze/thaw the list when doing live capture */
948 /*packet_list_thaw();*/
950 if (cf->state == FILE_READ_ABORTED) {
951 /* Well, the user decided to abort the read. We're only called
952 when the child capture process closes the pipe to us (meaning
953 it's probably exited), so we can just close the capture
954 file; we return CF_READ_ABORTED so our caller can do whatever
955 is appropriate when that happens. */
957 return CF_READ_ABORTED;
960 if (auto_scroll_live && cf->count != 0)
961 packet_list_moveto_end();
963 /* We're done reading sequentially through the file. */
964 cf->state = FILE_READ_DONE;
966 /* We're done reading sequentially through the file; close the
967 sequential I/O side, to free up memory it requires. */
968 wtap_sequential_close(cf->wth);
970 /* Allow the protocol dissectors to free up memory that they
971 * don't need after the sequential run-through of the packets. */
972 postseq_cleanup_all_protocols();
974 /* Update the file encapsulation; it might have changed based on the
975 packets we've read. */
976 cf->lnk_t = wtap_file_encap(cf->wth);
978 /* Update the details in the file-set dialog, as the capture file
979 * has likely grown since we first stat-ed it */
980 fileset_update_file(cf->filename);
983 /* We got an error reading the capture file.
984 XXX - pop up a dialog box? */
985 if (err_info != NULL) {
986 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
987 wtap_strerror(*err), cf->filename, err_info);
990 g_warning("Error \"%s\" while reading \"%s\"",
991 wtap_strerror(*err), cf->filename);
993 return CF_READ_ERROR;
998 #endif /* HAVE_LIBPCAP */
1001 cf_get_display_name(capture_file *cf)
1005 /* Return a name to use in displays */
1006 if (!cf->is_tempfile) {
1007 /* Get the last component of the file name, and use that. */
1009 displayname = g_filename_display_basename(cf->filename);
1011 displayname=g_strdup("(No file)");
1014 /* The file we read is a temporary file from a live capture or
1015 a merge operation; we don't mention its name, but, if it's
1016 from a capture, give the source of the capture. */
1018 displayname = g_strdup(cf->source);
1020 displayname = g_strdup("(Untitled)");
1026 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1032 cf->source = g_strdup(source);
1034 cf->source = g_strdup("");
1038 const gchar *cf_get_tempfile_source(capture_file *cf) {
1046 /* XXX - use a macro instead? */
1048 cf_get_packet_count(capture_file *cf)
1053 /* XXX - use a macro instead? */
1055 cf_is_tempfile(capture_file *cf)
1057 return cf->is_tempfile;
1060 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1062 cf->is_tempfile = is_tempfile;
1066 /* XXX - use a macro instead? */
1067 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1069 cf->drops_known = drops_known;
1072 /* XXX - use a macro instead? */
1073 void cf_set_drops(capture_file *cf, guint32 drops)
1078 /* XXX - use a macro instead? */
1079 gboolean cf_get_drops_known(capture_file *cf)
1081 return cf->drops_known;
1084 /* XXX - use a macro instead? */
1085 guint32 cf_get_drops(capture_file *cf)
1090 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1092 cf->rfcode = rfcode;
1096 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1097 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1098 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1102 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1103 &cf->ref, cf->prev_dis);
1104 cf->prev_cap = fdata;
1106 if (dfcode != NULL) {
1107 epan_dissect_prime_dfilter(edt, dfcode);
1110 /* Prepare coloring rules, this ensures that display filter rules containing
1111 * frame.color_rule references are still processed.
1112 * TODO: actually detect that situation or maybe apply other optimizations? */
1113 if (edt->tree && color_filters_used()) {
1114 color_filters_prime_edt(edt);
1115 fdata->flags.need_colorize = 1;
1119 /* Dissect the frame. */
1120 epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1122 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1123 if (dfcode != NULL) {
1124 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1126 if (fdata->flags.passed_dfilter) {
1127 /* This frame passed the display filter but it may depend on other
1128 * (potentially not displayed) frames. Find those frames and mark them
1131 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
1134 fdata->flags.passed_dfilter = 1;
1136 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1137 cf->displayed_count++;
1139 if (add_to_packet_list) {
1140 /* We fill the needed columns from new_packet_list */
1141 row = packet_list_append(cinfo, fdata);
1144 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1146 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1147 cf->prev_dis = fdata;
1149 /* If we haven't yet seen the first frame, this is it. */
1150 if (cf->first_displayed == 0)
1151 cf->first_displayed = fdata->num;
1153 /* This is the last frame we've seen so far. */
1154 cf->last_displayed = fdata->num;
1157 epan_dissect_reset(edt);
1161 /* read in a new packet */
1162 /* returns the row of the new packet in the packet list or -1 if not displayed */
1164 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1165 column_info *cinfo, gint64 offset)
1167 struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1168 const guint8 *buf = wtap_buf_ptr(cf->wth);
1175 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1176 it's not already there.
1177 XXX - yes, this is O(N), so if every packet had a different
1178 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1179 there are probably going to be a small number of encapsulation types
1181 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1183 /* The frame number of this packet is one more than the count of
1184 frames in the file so far. */
1185 framenum = cf->count + 1;
1187 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1191 epan_dissect_t rf_edt;
1193 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1194 epan_dissect_prime_dfilter(&rf_edt, cf->rfcode);
1195 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1196 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1197 epan_dissect_cleanup(&rf_edt);
1201 /* This does a shallow copy of fdlocal, which is good enough. */
1202 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1205 if (phdr->opt_comment != NULL)
1206 cf->packet_comment_count++;
1207 cf->f_datalen = offset + fdlocal.cap_len;
1209 if (!cf->redissecting) {
1210 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1211 cinfo, phdr, buf, TRUE);
1219 typedef struct _callback_data_t {
1221 GTimeVal start_time;
1229 merge_callback(merge_event event, int num _U_,
1230 const merge_in_file_t in_files[], const guint in_file_count,
1234 callback_data_t *cb_data = (callback_data_t*) data;
1236 g_assert(cb_data != NULL);
1240 case MERGE_EVENT_INPUT_FILES_OPENED:
1244 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1248 case MERGE_EVENT_READY_TO_MERGE:
1249 /* Get the sum of the sizes of all the files. */
1250 for (i = 0; i < in_file_count; i++)
1251 cb_data->f_len += in_files[i].size;
1253 cb_data->prog_timer = g_timer_new();
1254 g_timer_start(cb_data->prog_timer);
1256 g_get_current_time(&cb_data->start_time);
1259 case MERGE_EVENT_PACKET_WAS_READ:
1261 gint64 data_offset = 0;
1263 /* Get the sum of the data offsets in all of the files. */
1265 for (i = 0; i < in_file_count; i++)
1266 data_offset += in_files[i].data_offset;
1268 /* Create the progress bar if necessary.
1269 We check on every iteration of the loop, so that it takes no
1270 longer than the standard time to create it (otherwise, for a
1271 large file, we might take considerably longer than that standard
1272 time in order to get to the next progress bar step). */
1273 if (cb_data->progbar == NULL) {
1274 cb_data->progbar = delayed_create_progress_dlg(NULL, "Merging", "files",
1275 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1279 * Update the progress bar, but do it only after
1280 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1281 * and packets_bar_update will likely trigger UI paint events, which
1282 * might take a while depending on the platform and display. Reset
1283 * our timer *after* painting.
1285 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1287 gint64 file_pos = 0;
1288 /* Get the sum of the seek positions in all of the files. */
1289 for (i = 0; i < in_file_count; i++)
1290 file_pos += wtap_read_so_far(in_files[i].wth);
1292 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1293 if (progbar_val > 1.0f) {
1294 /* Some file probably grew while we were reading it.
1295 That "shouldn't happen", so we'll just clip the progress
1300 if (cb_data->progbar != NULL) {
1301 gchar status_str[100];
1302 g_snprintf(status_str, sizeof(status_str),
1303 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1304 file_pos / 1024, cb_data->f_len / 1024);
1305 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1307 g_timer_start(cb_data->prog_timer);
1312 case MERGE_EVENT_DONE:
1313 /* We're done merging the files; destroy the progress bar if it was created. */
1314 if (cb_data->progbar != NULL)
1315 destroy_progress_dlg(cb_data->progbar);
1316 g_timer_destroy(cb_data->prog_timer);
1320 return cb_data->stop_flag;
1326 cf_merge_files_to_tempfile(char **out_filenamep, int in_file_count,
1327 char *const *in_filenames, int file_type,
1331 gchar *err_info = NULL;
1333 merge_result status;
1334 merge_progress_callback_t cb;
1336 /* prepare our callback routine */
1337 cb.callback_func = merge_callback;
1338 cb.data = g_malloc0(sizeof(callback_data_t));
1340 /* merge the files */
1341 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1342 (const char *const *) in_filenames,
1343 in_file_count, do_append,
1344 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1345 "Wireshark", &cb, &err, &err_info,
1354 case MERGE_USER_ABORTED:
1355 /* this isn't really an error, though we will return CF_ERROR later */
1358 case MERGE_ERR_CANT_OPEN_INFILE:
1359 cf_open_failure_alert_box(in_filenames[err_fileno], err, err_info,
1363 case MERGE_ERR_CANT_OPEN_OUTFILE:
1364 cf_open_failure_alert_box(*out_filenamep, err, err_info, TRUE,
1368 case MERGE_ERR_CANT_READ_INFILE: /* fall through */
1369 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1370 case MERGE_ERR_CANT_WRITE_OUTFILE:
1371 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1373 simple_error_message_box("%s", err_info ? err_info : "unknown error");
1379 if (status != MERGE_OK) {
1380 /* Callers aren't expected to treat an error or an explicit abort
1381 differently - we put up error dialogs ourselves, so they don't
1389 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1391 const char *filter_new = dftext ? dftext : "";
1392 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1395 GTimeVal start_time;
1397 /* if new filter equals old one, do nothing unless told to do so */
1398 if (!force && strcmp(filter_new, filter_old) == 0) {
1404 if (dftext == NULL) {
1405 /* The new filter is an empty filter (i.e., display all packets).
1406 * so leave dfcode==NULL
1410 * We have a filter; make a copy of it (as we'll be saving it),
1411 * and try to compile it.
1413 dftext = g_strdup(dftext);
1414 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1415 /* The attempt failed; report an error. */
1416 simple_message_box(ESD_TYPE_ERROR, NULL,
1417 "See the help for a description of the display filter syntax.",
1418 "\"%s\" isn't a valid display filter: %s",
1426 if (dfcode == NULL) {
1427 /* Yes - free the filter text, and set it to null. */
1433 /* We have a valid filter. Replace the current filter. */
1434 g_free(cf->dfilter);
1435 cf->dfilter = dftext;
1436 g_get_current_time(&start_time);
1439 /* Now rescan the packet list, applying the new filter, but not
1440 throwing away information constructed on a previous pass. */
1441 if (cf->state != FILE_CLOSED) {
1442 if (dftext == NULL) {
1443 rescan_packets(cf, "Resetting", "Filter", FALSE);
1445 rescan_packets(cf, "Filtering", dftext, FALSE);
1449 /* Cleanup and release all dfilter resources */
1450 dfilter_free(dfcode);
1456 cf_reftime_packets(capture_file *cf)
1458 ref_time_packets(cf);
1462 cf_redissect_packets(capture_file *cf)
1464 if (cf->state != FILE_CLOSED) {
1465 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1470 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1471 struct wtap_pkthdr *phdr, Buffer *buf)
1475 gchar *display_basename;
1477 #ifdef WANT_PACKET_EDITOR
1478 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1479 if (G_UNLIKELY(fdata->file_off == -1)) {
1480 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1483 simple_error_message_box("fdata->file_off == -1, but can't find modified frame.");
1487 *phdr = frame->phdr;
1488 ws_buffer_assure_space(buf, frame->phdr.caplen);
1489 memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
1494 if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1495 display_basename = g_filename_display_basename(cf->filename);
1498 case WTAP_ERR_BAD_FILE:
1499 simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)",
1500 display_basename, wtap_strerror(err),
1501 err_info != NULL ? err_info : "no information supplied");
1506 simple_error_message_box(
1507 "An error occurred while reading from the file \"%s\": %s.",
1508 display_basename, wtap_strerror(err));
1511 g_free(display_basename);
1518 cf_read_record(capture_file *cf, frame_data *fdata)
1520 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1523 /* Rescan the list of packets, reconstructing the CList.
1525 "action" describes why we're doing this; it's used in the progress
1528 "action_item" describes what we're doing; it's used in the progress
1531 "redissect" is TRUE if we need to make the dissectors reconstruct
1532 any state information they have (because a preference that affects
1533 some dissector has changed, meaning some dissector might construct
1534 its state differently from the way it was constructed the last time). */
1536 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1538 /* Rescan packets new packet list */
1541 progdlg_t *progbar = NULL;
1542 GTimer *prog_timer = g_timer_new();
1544 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1545 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1546 gboolean selected_frame_seen;
1548 GTimeVal start_time;
1549 gchar status_str[100];
1553 gboolean create_proto_tree;
1555 gboolean add_to_packet_list = FALSE;
1557 guint32 frames_count;
1559 /* Compile the current display filter.
1560 * We assume this will not fail since cf->dfilter is only set in
1561 * cf_filter IFF the filter was valid.
1563 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1564 g_assert(!cf->dfilter || (compiled && dfcode));
1566 /* Get the union of the flags for all tap listeners. */
1567 tap_flags = union_of_tap_listener_flags();
1568 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1570 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
1572 reset_tap_listeners();
1573 /* Which frame, if any, is the currently selected frame?
1574 XXX - should the selected frame or the focus frame be the "current"
1575 frame, that frame being the one from which "Find Frame" searches
1577 selected_frame = cf->current_frame;
1579 /* Mark frame num as not found */
1580 selected_frame_num = -1;
1582 /* Freeze the packet list while we redo it, so we don't get any
1583 screen updates while it happens. */
1584 packet_list_freeze();
1587 /* We need to re-initialize all the state information that protocols
1588 keep, because some preference that controls a dissector has changed,
1589 which might cause the state information to be constructed differently
1590 by that dissector. */
1592 /* We might receive new packets while redissecting, and we don't
1593 want to dissect those before their time. */
1594 cf->redissecting = TRUE;
1596 /* 'reset' dissection session */
1597 epan_free(cf->epan);
1598 if (cf->edt && cf->edt->pi.fd) {
1599 /* All pointers in "per frame proto data" for the currently selected
1600 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1601 Free them here to avoid unintended usage in packet_list_clear(). */
1602 frame_data_destroy(cf->edt->pi.fd);
1604 cf->epan = ws_epan_new(cf);
1605 cf->cinfo.epan = cf->epan;
1607 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1608 called via epan_new() / init_dissection() when reloading Lua plugins. */
1609 if (!create_proto_tree && have_filtering_tap_listeners()) {
1610 create_proto_tree = TRUE;
1613 /* We need to redissect the packets so we have to discard our old
1614 * packet list store. */
1615 packet_list_clear();
1616 add_to_packet_list = TRUE;
1619 /* We don't yet know which will be the first and last frames displayed. */
1620 cf->first_displayed = 0;
1621 cf->last_displayed = 0;
1623 /* We currently don't display any packets */
1624 cf->displayed_count = 0;
1626 /* Iterate through the list of frames. Call a routine for each frame
1627 to check whether it should be displayed and, if so, add it to
1628 the display list. */
1630 cf->prev_dis = NULL;
1631 cf->prev_cap = NULL;
1634 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1636 g_timer_start(prog_timer);
1637 /* Count of packets at which we've looked. */
1639 /* Progress so far. */
1642 cf->stop_flag = FALSE;
1643 g_get_current_time(&start_time);
1645 /* no previous row yet */
1646 prev_frame_num = -1;
1649 preceding_frame_num = -1;
1650 preceding_frame = NULL;
1651 following_frame_num = -1;
1652 following_frame = NULL;
1654 selected_frame_seen = FALSE;
1656 frames_count = cf->count;
1658 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1660 for (framenum = 1; framenum <= frames_count; framenum++) {
1661 fdata = frame_data_sequence_find(cf->frames, framenum);
1663 /* Create the progress bar if necessary.
1664 We check on every iteration of the loop, so that it takes no
1665 longer than the standard time to create it (otherwise, for a
1666 large file, we might take considerably longer than that standard
1667 time in order to get to the next progress bar step). */
1668 if (progbar == NULL)
1669 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1675 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1676 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1677 * likely trigger UI paint events, which might take a while depending on
1678 * the platform and display. Reset our timer *after* painting.
1680 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1681 /* let's not divide by zero. I should never be started
1682 * with count == 0, so let's assert that
1684 g_assert(cf->count > 0);
1685 progbar_val = (gfloat) count / frames_count;
1687 if (progbar != NULL) {
1688 g_snprintf(status_str, sizeof(status_str),
1689 "%4u of %u frames", count, frames_count);
1690 update_progress_dlg(progbar, progbar_val, status_str);
1693 g_timer_start(prog_timer);
1696 if (cf->stop_flag) {
1697 /* Well, the user decided to abort the filtering. Just stop.
1699 XXX - go back to the previous filter? Users probably just
1700 want not to wait for a filtering operation to finish;
1701 unless we cancel by having no filter, reverting to the
1702 previous filter will probably be even more expensive than
1703 continuing the filtering, as it involves going back to the
1704 beginning and filtering, and even with no filter we currently
1705 have to re-generate the entire clist, which is also expensive.
1707 I'm not sure what Network Monitor does, but it doesn't appear
1708 to give you an unfiltered display if you cancel. */
1715 /* Since all state for the frame was destroyed, mark the frame
1716 * as not visited, free the GSList referring to the state
1717 * data (the per-frame data itself was freed by
1718 * "init_dissection()"), and null out the GSList pointer. */
1719 frame_data_reset(fdata);
1720 frames_count = cf->count;
1723 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1724 fdata->flags.dependent_of_displayed = 0;
1726 if (!cf_read_record(cf, fdata))
1727 break; /* error reading the frame */
1729 /* If the previous frame is displayed, and we haven't yet seen the
1730 selected frame, remember that frame - it's the closest one we've
1731 yet seen before the selected frame. */
1732 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1733 preceding_frame_num = prev_frame_num;
1734 preceding_frame = prev_frame;
1737 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1739 ws_buffer_start_ptr(&cf->buf),
1740 add_to_packet_list);
1742 /* If this frame is displayed, and this is the first frame we've
1743 seen displayed after the selected frame, remember this frame -
1744 it's the closest one we've yet seen at or after the selected
1746 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1747 following_frame_num = fdata->num;
1748 following_frame = fdata;
1750 if (fdata == selected_frame) {
1751 selected_frame_seen = TRUE;
1752 if (fdata->flags.passed_dfilter)
1753 selected_frame_num = fdata->num;
1756 /* Remember this frame - it'll be the previous frame
1757 on the next pass through the loop. */
1758 prev_frame_num = fdata->num;
1762 epan_dissect_cleanup(&edt);
1764 /* We are done redissecting the packet list. */
1765 cf->redissecting = FALSE;
1768 frames_count = cf->count;
1769 /* Clear out what remains of the visited flags and per-frame data
1772 XXX - that may cause various forms of bogosity when dissecting
1773 these frames, as they won't have been seen by this sequential
1774 pass, but the only alternative I see is to keep scanning them
1775 even though the user requested that the scan stop, and that
1776 would leave the user stuck with an Wireshark grinding on
1777 until it finishes. Should we just stick them with that? */
1778 for (; framenum <= frames_count; framenum++) {
1779 fdata = frame_data_sequence_find(cf->frames, framenum);
1780 frame_data_reset(fdata);
1784 /* We're done filtering the packets; destroy the progress bar if it
1786 if (progbar != NULL)
1787 destroy_progress_dlg(progbar);
1788 g_timer_destroy(prog_timer);
1790 /* Unfreeze the packet list. */
1791 if (!add_to_packet_list)
1792 packet_list_recreate_visible_rows();
1794 /* Compute the time it took to filter the file */
1795 compute_elapsed(cf, &start_time);
1799 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1801 if (selected_frame_num == -1) {
1802 /* The selected frame didn't pass the filter. */
1803 if (selected_frame == NULL) {
1804 /* That's because there *was* no selected frame. Make the first
1805 displayed frame the current frame. */
1806 selected_frame_num = 0;
1808 /* Find the nearest displayed frame to the selected frame (whether
1809 it's before or after that frame) and make that the current frame.
1810 If the next and previous displayed frames are equidistant from the
1811 selected frame, choose the next one. */
1812 g_assert(following_frame == NULL ||
1813 following_frame->num >= selected_frame->num);
1814 g_assert(preceding_frame == NULL ||
1815 preceding_frame->num <= selected_frame->num);
1816 if (following_frame == NULL) {
1817 /* No frame after the selected frame passed the filter, so we
1818 have to select the last displayed frame before the selected
1820 selected_frame_num = preceding_frame_num;
1821 selected_frame = preceding_frame;
1822 } else if (preceding_frame == NULL) {
1823 /* No frame before the selected frame passed the filter, so we
1824 have to select the first displayed frame after the selected
1826 selected_frame_num = following_frame_num;
1827 selected_frame = following_frame;
1829 /* Frames before and after the selected frame passed the filter, so
1830 we'll select the previous frame */
1831 selected_frame_num = preceding_frame_num;
1832 selected_frame = preceding_frame;
1837 if (selected_frame_num == -1) {
1838 /* There are no frames displayed at all. */
1839 cf_unselect_packet(cf);
1841 /* Either the frame that was selected passed the filter, or we've
1842 found the nearest displayed frame to that frame. Select it, make
1843 it the focus row, and make it visible. */
1844 /* Set to invalid to force update of packet list and packet details */
1845 cf->current_row = -1;
1846 if (selected_frame_num == 0) {
1847 packet_list_select_first_row();
1849 if (!packet_list_select_row_from_data(selected_frame)) {
1850 /* We didn't find a row corresponding to this frame.
1851 This means that the frame isn't being displayed currently,
1852 so we can't select it. */
1853 simple_message_box(ESD_TYPE_INFO, NULL,
1854 "The capture file is probably not fully dissected.",
1855 "End of capture exceeded.");
1860 /* Cleanup and release all dfilter resources */
1861 dfilter_free(dfcode);
1866 * Scan through all frame data and recalculate the ref time
1867 * without rereading the file.
1868 * XXX - do we need a progres bar or is this fast enough?
1871 ref_time_packets(capture_file *cf)
1878 cf->prev_dis = NULL;
1881 for (framenum = 1; framenum <= cf->count; framenum++) {
1882 fdata = frame_data_sequence_find(cf->frames, framenum);
1884 /* just add some value here until we know if it is being displayed or not */
1885 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1891 /* If we don't have the time stamp of the first packet in the
1892 capture, it's because this is the first packet. Save the time
1893 stamp of this packet as the time stamp of the first packet. */
1894 if (cf->ref == NULL)
1896 /* if this frames is marked as a reference time frame, reset
1897 firstsec and firstusec to this frame */
1898 if (fdata->flags.ref_time)
1901 /* If we don't have the time stamp of the previous displayed packet,
1902 it's because this is the first displayed packet. Save the time
1903 stamp of this packet as the time stamp of the previous displayed
1905 if (cf->prev_dis == NULL) {
1906 cf->prev_dis = fdata;
1909 /* Get the time elapsed between the first packet and this packet. */
1910 fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
1911 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
1913 /* If it's greater than the current elapsed time, set the elapsed time
1914 to it (we check for "greater than" so as not to be confused by
1915 time moving backwards). */
1916 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1917 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1918 cf->elapsed_time = rel_ts;
1921 /* If this frame is displayed, get the time elapsed between the
1922 previous displayed packet and this packet. */
1923 if ( fdata->flags.passed_dfilter ) {
1924 fdata->prev_dis_num = cf->prev_dis->num;
1925 cf->prev_dis = fdata;
1931 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1932 /* This frame either passed the display filter list or is marked as
1933 a time reference frame. All time reference frames are displayed
1934 even if they don't pass the display filter */
1935 if (fdata->flags.ref_time) {
1936 /* if this was a TIME REF frame we should reset the cum_bytes field */
1937 cf->cum_bytes = fdata->pkt_len;
1938 fdata->cum_bytes = cf->cum_bytes;
1940 /* increase cum_bytes with this packets length */
1941 cf->cum_bytes += fdata->pkt_len;
1954 process_specified_records(capture_file *cf, packet_range_t *range,
1955 const char *string1, const char *string2, gboolean terminate_is_stop,
1956 gboolean (*callback)(capture_file *, frame_data *,
1957 struct wtap_pkthdr *, const guint8 *, void *),
1958 void *callback_args,
1959 gboolean show_progress_bar)
1964 psp_return_t ret = PSP_FINISHED;
1966 progdlg_t *progbar = NULL;
1967 GTimer *prog_timer = g_timer_new();
1970 GTimeVal progbar_start_time;
1971 gchar progbar_status_str[100];
1972 range_process_e process_this;
1973 struct wtap_pkthdr phdr;
1975 wtap_phdr_init(&phdr);
1976 ws_buffer_init(&buf, 1500);
1978 g_timer_start(prog_timer);
1979 /* Count of packets at which we've looked. */
1981 /* Progress so far. */
1984 cf->stop_flag = FALSE;
1985 g_get_current_time(&progbar_start_time);
1988 packet_range_process_init(range);
1990 /* Iterate through all the packets, printing the packets that
1991 were selected by the current display filter. */
1992 for (framenum = 1; framenum <= cf->count; framenum++) {
1993 fdata = frame_data_sequence_find(cf->frames, framenum);
1995 /* Create the progress bar if necessary.
1996 We check on every iteration of the loop, so that it takes no
1997 longer than the standard time to create it (otherwise, for a
1998 large file, we might take considerably longer than that standard
1999 time in order to get to the next progress bar step). */
2000 if (show_progress_bar && progbar == NULL)
2001 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2004 &progbar_start_time,
2008 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
2009 * has elapsed. Calling update_progress_dlg and packets_bar_update will
2010 * likely trigger UI paint events, which might take a while depending on
2011 * the platform and display. Reset our timer *after* painting.
2013 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2014 /* let's not divide by zero. I should never be started
2015 * with count == 0, so let's assert that
2017 g_assert(cf->count > 0);
2018 progbar_val = (gfloat) progbar_count / cf->count;
2020 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2021 "%4u of %u packets", progbar_count, cf->count);
2022 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2024 g_timer_start(prog_timer);
2027 if (cf->stop_flag) {
2028 /* Well, the user decided to abort the operation. Just stop,
2029 and arrange to return PSP_STOPPED to our caller, so they know
2030 it was stopped explicitly. */
2037 if (range != NULL) {
2038 /* do we have to process this packet? */
2039 process_this = packet_range_process_packet(range, fdata);
2040 if (process_this == range_process_next) {
2041 /* this packet uninteresting, continue with next one */
2043 } else if (process_this == range_processing_finished) {
2044 /* all interesting packets processed, stop the loop */
2049 /* Get the packet */
2050 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2051 /* Attempt to get the packet failed. */
2055 /* Process the packet */
2056 if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2057 /* Callback failed. We assume it reported the error appropriately. */
2063 /* We're done printing the packets; destroy the progress bar if
2065 if (progbar != NULL)
2066 destroy_progress_dlg(progbar);
2067 g_timer_destroy(prog_timer);
2069 wtap_phdr_cleanup(&phdr);
2070 ws_buffer_free(&buf);
2078 } retap_callback_args_t;
2081 retap_packet(capture_file *cf, frame_data *fdata,
2082 struct wtap_pkthdr *phdr, const guint8 *pd,
2085 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2087 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2088 epan_dissect_reset(&args->edt);
2094 cf_retap_packets(capture_file *cf)
2096 packet_range_t range;
2097 retap_callback_args_t callback_args;
2098 gboolean construct_protocol_tree;
2099 gboolean filtering_tap_listeners;
2103 /* Presumably the user closed the capture file. */
2105 return CF_READ_ABORTED;
2108 cf_callback_invoke(cf_cb_file_retap_started, cf);
2110 /* Do we have any tap listeners with filters? */
2111 filtering_tap_listeners = have_filtering_tap_listeners();
2113 tap_flags = union_of_tap_listener_flags();
2115 /* If any tap listeners have filters, or require the protocol tree,
2116 construct the protocol tree. */
2117 construct_protocol_tree = filtering_tap_listeners ||
2118 (tap_flags & TL_REQUIRES_PROTO_TREE);
2120 /* If any tap listeners require the columns, construct them. */
2121 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2123 /* Reset the tap listeners. */
2124 reset_tap_listeners();
2126 epan_dissect_init(&callback_args.edt, cf->epan, construct_protocol_tree, FALSE);
2128 /* Iterate through the list of packets, dissecting all packets and
2129 re-running the taps. */
2130 packet_range_init(&range, cf);
2131 packet_range_process_init(&range);
2133 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2134 "all packets", TRUE, retap_packet,
2135 &callback_args, TRUE);
2137 epan_dissect_cleanup(&callback_args.edt);
2139 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2143 /* Completed successfully. */
2147 /* Well, the user decided to abort the refiltering.
2148 Return CF_READ_ABORTED so our caller knows they did that. */
2149 return CF_READ_ABORTED;
2152 /* Error while retapping. */
2153 return CF_READ_ERROR;
2156 g_assert_not_reached();
2161 print_args_t *print_args;
2162 gboolean print_header_line;
2163 char *header_line_buf;
2164 int header_line_buf_len;
2165 gboolean print_formfeed;
2166 gboolean print_separator;
2170 int num_visible_cols;
2173 } print_callback_args_t;
2176 print_packet(capture_file *cf, frame_data *fdata,
2177 struct wtap_pkthdr *phdr, const guint8 *pd,
2180 print_callback_args_t *args = (print_callback_args_t *)argsp;
2186 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2187 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2188 col_item_t* col_item;
2190 /* Fill in the column information if we're printing the summary
2192 if (args->print_args->print_summary) {
2193 col_custom_prime_edt(&args->edt, &cf->cinfo);
2194 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2195 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2197 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2199 if (args->print_formfeed) {
2200 if (!new_page(args->print_args->stream))
2203 if (args->print_separator) {
2204 if (!print_line(args->print_args->stream, 0, ""))
2210 * We generate bookmarks, if the output format supports them.
2211 * The name is "__frameN__".
2213 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2215 if (args->print_args->print_summary) {
2216 if (!args->print_args->print_col_headings)
2217 args->print_header_line = FALSE;
2218 if (args->print_header_line) {
2219 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2221 args->print_header_line = FALSE; /* we might not need to print any more */
2223 cp = &args->line_buf[0];
2225 for (i = 0; i < args->num_visible_cols; i++) {
2226 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2227 /* Find the length of the string for this column. */
2228 column_len = (int) strlen(col_item->col_data);
2229 if (args->col_widths[i] > column_len)
2230 column_len = args->col_widths[i];
2232 /* Make sure there's room in the line buffer for the column; if not,
2233 double its length. */
2234 line_len += column_len + 1; /* "+1" for space */
2235 if (line_len > args->line_buf_len) {
2236 cp_off = (int) (cp - args->line_buf);
2237 args->line_buf_len = 2 * line_len;
2238 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2239 cp = args->line_buf + cp_off;
2242 /* Right-justify the packet number column. */
2243 if (col_item->col_fmt == COL_NUMBER)
2244 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2246 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2248 if (i != args->num_visible_cols - 1)
2254 * Generate a bookmark, using the summary line as the title.
2256 if (!print_bookmark(args->print_args->stream, bookmark_name,
2260 if (!print_line(args->print_args->stream, 0, args->line_buf))
2264 * Generate a bookmark, using "Frame N" as the title, as we're not
2265 * printing the summary line.
2267 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2268 if (!print_bookmark(args->print_args->stream, bookmark_name,
2271 } /* if (print_summary) */
2273 if (args->print_args->print_dissections != print_dissections_none) {
2274 if (args->print_args->print_summary) {
2275 /* Separate the summary line from the tree with a blank line. */
2276 if (!print_line(args->print_args->stream, 0, ""))
2280 /* Print the information in that tree. */
2281 if (!proto_tree_print(args->print_args, &args->edt, NULL, args->print_args->stream))
2284 /* Print a blank line if we print anything after this (aka more than one packet). */
2285 args->print_separator = TRUE;
2287 /* Print a header line if we print any more packet summaries */
2288 if (args->print_args->print_col_headings)
2289 args->print_header_line = TRUE;
2292 if (args->print_args->print_hex) {
2293 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2294 if (!print_line(args->print_args->stream, 0, ""))
2297 /* Print the full packet data as hex. */
2298 if (!print_hex_data(args->print_args->stream, &args->edt))
2301 /* Print a blank line if we print anything after this (aka more than one packet). */
2302 args->print_separator = TRUE;
2304 /* Print a header line if we print any more packet summaries */
2305 if (args->print_args->print_col_headings)
2306 args->print_header_line = TRUE;
2307 } /* if (args->print_args->print_dissections != print_dissections_none) */
2309 epan_dissect_reset(&args->edt);
2311 /* do we want to have a formfeed between each packet from now on? */
2312 if (args->print_args->print_formfeed) {
2313 args->print_formfeed = TRUE;
2319 epan_dissect_reset(&args->edt);
2324 cf_print_packets(capture_file *cf, print_args_t *print_args,
2325 gboolean show_progress_bar)
2327 print_callback_args_t callback_args;
2330 int i, cp_off, column_len, line_len;
2331 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2335 gboolean proto_tree_needed;
2337 callback_args.print_args = print_args;
2338 callback_args.print_header_line = print_args->print_col_headings;
2339 callback_args.header_line_buf = NULL;
2340 callback_args.header_line_buf_len = 256;
2341 callback_args.print_formfeed = FALSE;
2342 callback_args.print_separator = FALSE;
2343 callback_args.line_buf = NULL;
2344 callback_args.line_buf_len = 256;
2345 callback_args.col_widths = NULL;
2346 callback_args.num_visible_cols = 0;
2347 callback_args.visible_cols = NULL;
2349 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2350 destroy_print_stream(print_args->stream);
2351 return CF_PRINT_WRITE_ERROR;
2354 if (print_args->print_summary) {
2355 /* We're printing packet summaries. Allocate the header line buffer
2356 and get the column widths. */
2357 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2359 /* Find the number of visible columns and the last visible column */
2360 for (i = 0; i < prefs.num_cols; i++) {
2362 clp = g_list_nth(prefs.col_list, i);
2363 if (clp == NULL) /* Sanity check, Invalid column requested */
2366 cfmt = (fmt_data *) clp->data;
2367 if (cfmt->visible) {
2369 last_visible_col = i;
2373 /* Find the widths for each of the columns - maximum of the
2374 width of the title and the width of the data - and construct
2375 a buffer with a line containing the column titles. */
2376 callback_args.num_visible_cols = num_visible_col;
2377 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2378 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2379 cp = &callback_args.header_line_buf[0];
2381 visible_col_count = 0;
2382 for (i = 0; i < cf->cinfo.num_cols; i++) {
2384 clp = g_list_nth(prefs.col_list, i);
2385 if (clp == NULL) /* Sanity check, Invalid column requested */
2388 cfmt = (fmt_data *) clp->data;
2389 if (cfmt->visible == FALSE)
2392 /* Save the order of visible columns */
2393 callback_args.visible_cols[visible_col_count] = i;
2395 /* Don't pad the last column. */
2396 if (i == last_visible_col)
2397 callback_args.col_widths[visible_col_count] = 0;
2399 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2400 data_width = get_column_char_width(get_column_format(i));
2401 if (data_width > callback_args.col_widths[visible_col_count])
2402 callback_args.col_widths[visible_col_count] = data_width;
2405 /* Find the length of the string for this column. */
2406 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2407 if (callback_args.col_widths[i] > column_len)
2408 column_len = callback_args.col_widths[visible_col_count];
2410 /* Make sure there's room in the line buffer for the column; if not,
2411 double its length. */
2412 line_len += column_len + 1; /* "+1" for space */
2413 if (line_len > callback_args.header_line_buf_len) {
2414 cp_off = (int) (cp - callback_args.header_line_buf);
2415 callback_args.header_line_buf_len = 2 * line_len;
2416 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2417 callback_args.header_line_buf_len + 1);
2418 cp = callback_args.header_line_buf + cp_off;
2421 /* Right-justify the packet number column. */
2422 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2423 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2425 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2427 if (i != cf->cinfo.num_cols - 1)
2430 visible_col_count++;
2434 /* Now start out the main line buffer with the same length as the
2435 header line buffer. */
2436 callback_args.line_buf_len = callback_args.header_line_buf_len;
2437 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2438 } /* if (print_summary) */
2440 /* Create the protocol tree, and make it visible, if we're printing
2441 the dissection or the hex data.
2442 XXX - do we need it if we're just printing the hex data? */
2444 callback_args.print_args->print_dissections != print_dissections_none ||
2445 callback_args.print_args->print_hex ||
2446 have_custom_cols(&cf->cinfo) || have_field_extractors();
2447 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2449 /* Iterate through the list of packets, printing the packets we were
2451 ret = process_specified_records(cf, &print_args->range, "Printing",
2452 "selected packets", TRUE, print_packet,
2453 &callback_args, show_progress_bar);
2454 epan_dissect_cleanup(&callback_args.edt);
2455 g_free(callback_args.header_line_buf);
2456 g_free(callback_args.line_buf);
2457 g_free(callback_args.col_widths);
2458 g_free(callback_args.visible_cols);
2463 /* Completed successfully. */
2467 /* Well, the user decided to abort the printing.
2469 XXX - note that what got generated before they did that
2470 will get printed if we're piping to a print program; we'd
2471 have to write to a file and then hand that to the print
2472 program to make it actually not print anything. */
2476 /* Error while printing.
2478 XXX - note that what got generated before they did that
2479 will get printed if we're piping to a print program; we'd
2480 have to write to a file and then hand that to the print
2481 program to make it actually not print anything. */
2482 destroy_print_stream(print_args->stream);
2483 return CF_PRINT_WRITE_ERROR;
2486 if (!print_finale(print_args->stream)) {
2487 destroy_print_stream(print_args->stream);
2488 return CF_PRINT_WRITE_ERROR;
2491 if (!destroy_print_stream(print_args->stream))
2492 return CF_PRINT_WRITE_ERROR;
2500 print_args_t *print_args;
2501 } write_packet_callback_args_t;
2504 write_pdml_packet(capture_file *cf, frame_data *fdata,
2505 struct wtap_pkthdr *phdr, const guint8 *pd,
2508 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2510 /* Create the protocol tree, but don't fill in the column information. */
2511 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2513 /* Write out the information in that tree. */
2514 write_pdml_proto_tree(NULL, NULL, &args->edt, args->fh);
2516 epan_dissect_reset(&args->edt);
2518 return !ferror(args->fh);
2522 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2524 write_packet_callback_args_t callback_args;
2528 fh = ws_fopen(print_args->file, "w");
2530 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2532 write_pdml_preamble(fh, cf->filename);
2535 return CF_PRINT_WRITE_ERROR;
2538 callback_args.fh = fh;
2539 callback_args.print_args = print_args;
2540 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2542 /* Iterate through the list of packets, printing the packets we were
2544 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2545 "selected packets", TRUE,
2546 write_pdml_packet, &callback_args, TRUE);
2548 epan_dissect_cleanup(&callback_args.edt);
2553 /* Completed successfully. */
2557 /* Well, the user decided to abort the printing. */
2561 /* Error while printing. */
2563 return CF_PRINT_WRITE_ERROR;
2566 write_pdml_finale(fh);
2569 return CF_PRINT_WRITE_ERROR;
2572 /* XXX - check for an error */
2579 write_psml_packet(capture_file *cf, frame_data *fdata,
2580 struct wtap_pkthdr *phdr, const guint8 *pd,
2583 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2585 /* Fill in the column information */
2586 col_custom_prime_edt(&args->edt, &cf->cinfo);
2587 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2588 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2590 /* Write out the column information. */
2591 write_psml_columns(&args->edt, args->fh);
2593 epan_dissect_reset(&args->edt);
2595 return !ferror(args->fh);
2599 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2601 write_packet_callback_args_t callback_args;
2605 gboolean proto_tree_needed;
2607 fh = ws_fopen(print_args->file, "w");
2609 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2611 write_psml_preamble(&cf->cinfo, fh);
2614 return CF_PRINT_WRITE_ERROR;
2617 callback_args.fh = fh;
2618 callback_args.print_args = print_args;
2620 /* Fill in the column information, only create the protocol tree
2621 if having custom columns or field extractors. */
2622 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2623 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2625 /* Iterate through the list of packets, printing the packets we were
2627 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2628 "selected packets", TRUE,
2629 write_psml_packet, &callback_args, TRUE);
2631 epan_dissect_cleanup(&callback_args.edt);
2636 /* Completed successfully. */
2640 /* Well, the user decided to abort the printing. */
2644 /* Error while printing. */
2646 return CF_PRINT_WRITE_ERROR;
2649 write_psml_finale(fh);
2652 return CF_PRINT_WRITE_ERROR;
2655 /* XXX - check for an error */
2662 write_csv_packet(capture_file *cf, frame_data *fdata,
2663 struct wtap_pkthdr *phdr, const guint8 *pd,
2666 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2668 /* Fill in the column information */
2669 col_custom_prime_edt(&args->edt, &cf->cinfo);
2670 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2671 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2673 /* Write out the column information. */
2674 write_csv_columns(&args->edt, args->fh);
2676 epan_dissect_reset(&args->edt);
2678 return !ferror(args->fh);
2682 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2684 write_packet_callback_args_t callback_args;
2685 gboolean proto_tree_needed;
2689 fh = ws_fopen(print_args->file, "w");
2691 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2693 write_csv_column_titles(&cf->cinfo, fh);
2696 return CF_PRINT_WRITE_ERROR;
2699 callback_args.fh = fh;
2700 callback_args.print_args = print_args;
2702 /* only create the protocol tree if having custom columns or field extractors. */
2703 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2704 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2706 /* Iterate through the list of packets, printing the packets we were
2708 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2709 "selected packets", TRUE,
2710 write_csv_packet, &callback_args, TRUE);
2712 epan_dissect_cleanup(&callback_args.edt);
2717 /* Completed successfully. */
2721 /* Well, the user decided to abort the printing. */
2725 /* Error while printing. */
2727 return CF_PRINT_WRITE_ERROR;
2730 /* XXX - check for an error */
2737 carrays_write_packet(capture_file *cf, frame_data *fdata,
2738 struct wtap_pkthdr *phdr,
2739 const guint8 *pd, void *argsp)
2741 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2743 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2744 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2745 epan_dissect_reset(&args->edt);
2747 return !ferror(args->fh);
2751 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2753 write_packet_callback_args_t callback_args;
2757 fh = ws_fopen(print_args->file, "w");
2760 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2764 return CF_PRINT_WRITE_ERROR;
2767 callback_args.fh = fh;
2768 callback_args.print_args = print_args;
2769 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2771 /* Iterate through the list of packets, printing the packets we were
2773 ret = process_specified_records(cf, &print_args->range,
2775 "selected packets", TRUE,
2776 carrays_write_packet, &callback_args, TRUE);
2778 epan_dissect_cleanup(&callback_args.edt);
2782 /* Completed successfully. */
2785 /* Well, the user decided to abort the printing. */
2788 /* Error while printing. */
2790 return CF_PRINT_WRITE_ERROR;
2798 write_json_packet(capture_file *cf, frame_data *fdata,
2799 struct wtap_pkthdr *phdr, const guint8 *pd,
2802 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2804 /* Create the protocol tree, but don't fill in the column information. */
2805 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2807 /* Write out the information in that tree. */
2808 write_json_proto_tree(NULL, args->print_args, NULL, &args->edt, args->fh);
2810 epan_dissect_reset(&args->edt);
2812 return !ferror(args->fh);
2816 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2818 write_packet_callback_args_t callback_args;
2822 fh = ws_fopen(print_args->file, "w");
2824 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2826 write_json_preamble(fh);
2829 return CF_PRINT_WRITE_ERROR;
2832 callback_args.fh = fh;
2833 callback_args.print_args = print_args;
2834 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2836 /* Iterate through the list of packets, printing the packets we were
2838 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2839 "selected packets", TRUE,
2840 write_json_packet, &callback_args, TRUE);
2842 epan_dissect_cleanup(&callback_args.edt);
2847 /* Completed successfully. */
2851 /* Well, the user decided to abort the printing. */
2855 /* Error while printing. */
2857 return CF_PRINT_WRITE_ERROR;
2860 write_json_finale(fh);
2863 return CF_PRINT_WRITE_ERROR;
2866 /* XXX - check for an error */
2873 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2874 search_direction dir)
2878 mdata.string = string;
2879 mdata.string_len = strlen(string);
2880 return find_packet(cf, match_protocol_tree, &mdata, dir);
2884 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2886 mdata->frame_matched = FALSE;
2887 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2888 mdata->string_len = strlen(mdata->string);
2890 /* Iterate through all the nodes looking for matching text */
2891 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2892 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2896 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2898 match_data *mdata = (match_data *)criterion;
2901 /* Load the frame's data. */
2902 if (!cf_read_record(cf, fdata)) {
2903 /* Attempt to get the packet failed. */
2907 /* Construct the protocol tree, including the displayed text */
2908 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2909 /* We don't need the column information */
2910 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
2912 /* Iterate through all the nodes, seeing if they have text that matches. */
2914 mdata->frame_matched = FALSE;
2915 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2916 epan_dissect_cleanup(&edt);
2917 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2921 match_subtree_text(proto_node *node, gpointer data)
2923 match_data *mdata = (match_data *) data;
2924 const gchar *string = mdata->string;
2925 size_t string_len = mdata->string_len;
2926 capture_file *cf = mdata->cf;
2927 field_info *fi = PNODE_FINFO(node);
2928 gchar label_str[ITEM_LABEL_LENGTH];
2935 /* dissection with an invisible proto tree? */
2938 if (mdata->frame_matched) {
2939 /* We already had a match; don't bother doing any more work. */
2943 /* Don't match invisible entries. */
2944 if (PROTO_ITEM_IS_HIDDEN(node))
2947 /* was a free format label produced? */
2949 label_ptr = fi->rep->representation;
2951 /* no, make a generic label */
2952 label_ptr = label_str;
2953 proto_item_fill_label(fi, label_str);
2957 if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
2958 mdata->frame_matched = TRUE;
2963 /* Does that label match? */
2964 label_len = strlen(label_ptr);
2965 for (i = 0; i < label_len; i++) {
2966 c_char = label_ptr[i];
2968 c_char = g_ascii_toupper(c_char);
2969 if (c_char == string[c_match]) {
2971 if (c_match == string_len) {
2972 /* No need to look further; we have a match */
2973 mdata->frame_matched = TRUE;
2982 /* Recurse into the subtree, if it exists */
2983 if (node->first_child != NULL)
2984 proto_tree_children_foreach(node, match_subtree_text, mdata);
2988 cf_find_packet_summary_line(capture_file *cf, const char *string,
2989 search_direction dir)
2993 mdata.string = string;
2994 mdata.string_len = strlen(string);
2995 return find_packet(cf, match_summary_line, &mdata, dir);
2999 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3001 match_data *mdata = (match_data *)criterion;
3002 const gchar *string = mdata->string;
3003 size_t string_len = mdata->string_len;
3005 const char *info_column;
3006 size_t info_column_len;
3007 match_result result = MR_NOTMATCHED;
3013 /* Load the frame's data. */
3014 if (!cf_read_record(cf, fdata)) {
3015 /* Attempt to get the packet failed. */
3019 /* Don't bother constructing the protocol tree */
3020 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3021 /* Get the column information */
3022 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
3025 /* Find the Info column */
3026 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3027 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3028 /* Found it. See if we match. */
3029 info_column = edt.pi.cinfo->columns[colx].col_data;
3030 info_column_len = strlen(info_column);
3032 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3033 result = MR_MATCHED;
3037 for (i = 0; i < info_column_len; i++) {
3038 c_char = info_column[i];
3040 c_char = g_ascii_toupper(c_char);
3041 if (c_char == string[c_match]) {
3043 if (c_match == string_len) {
3044 result = MR_MATCHED;
3054 epan_dissect_cleanup(&edt);
3061 } cbs_t; /* "Counted byte string" */
3065 * The current match_* routines only support ASCII case insensitivity and don't
3066 * convert UTF-8 inputs to UTF-16 for matching.
3068 * We could modify them to use the GLib Unicode routines or the International
3069 * Components for Unicode library but it's not apparent that we could do so
3070 * without consuming a lot more CPU and memory or that searching would be
3071 * significantly better.
3075 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3076 search_direction dir)
3081 info.data_len = string_size;
3083 /* Regex, String or hex search? */
3085 /* Regular Expression search */
3086 return find_packet(cf, match_regex, NULL, dir);
3087 } else if (cf->string) {
3088 /* String search - what type of string? */
3089 switch (cf->scs_type) {
3091 case SCS_NARROW_AND_WIDE:
3092 return find_packet(cf, match_narrow_and_wide, &info, dir);
3095 return find_packet(cf, match_narrow, &info, dir);
3098 return find_packet(cf, match_wide, &info, dir);
3101 g_assert_not_reached();
3105 return find_packet(cf, match_binary, &info, dir);
3109 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3111 cbs_t *info = (cbs_t *)criterion;
3112 const guint8 *ascii_text = info->data;
3113 size_t textlen = info->data_len;
3114 match_result result;
3121 /* Load the frame's data. */
3122 if (!cf_read_record(cf, fdata)) {
3123 /* Attempt to get the packet failed. */
3127 result = MR_NOTMATCHED;
3128 buf_len = fdata->cap_len;
3129 pd = ws_buffer_start_ptr(&cf->buf);
3131 while (i < buf_len) {
3134 c_char = g_ascii_toupper(c_char);
3135 if (c_char != '\0') {
3136 if (c_char == ascii_text[c_match]) {
3138 if (c_match == textlen) {
3139 result = MR_MATCHED;
3140 cf->search_pos = i; /* Save the position of the last character
3141 for highlighting the field. */
3142 cf->search_len = (guint32)textlen;
3147 g_assert(i>=c_match);
3148 i -= (guint32)c_match;
3158 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3161 cbs_t *info = (cbs_t *)criterion;
3162 const guint8 *ascii_text = info->data;
3163 size_t textlen = info->data_len;
3164 match_result result;
3170 /* Load the frame's data. */
3171 if (!cf_read_record(cf, fdata)) {
3172 /* Attempt to get the packet failed. */
3176 result = MR_NOTMATCHED;
3177 buf_len = fdata->cap_len;
3178 pd = ws_buffer_start_ptr(&cf->buf);
3180 while (i < buf_len) {
3183 c_char = g_ascii_toupper(c_char);
3184 if (c_char == ascii_text[c_match]) {
3186 if (c_match == textlen) {
3187 result = MR_MATCHED;
3188 cf->search_pos = i; /* Save the position of the last character
3189 for highlighting the field. */
3190 cf->search_len = (guint32)textlen;
3195 g_assert(i>=c_match);
3196 i -= (guint32)c_match;
3206 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3208 cbs_t *info = (cbs_t *)criterion;
3209 const guint8 *ascii_text = info->data;
3210 size_t textlen = info->data_len;
3211 match_result result;
3218 /* Load the frame's data. */
3219 if (!cf_read_record(cf, fdata)) {
3220 /* Attempt to get the packet failed. */
3224 result = MR_NOTMATCHED;
3225 buf_len = fdata->cap_len;
3226 pd = ws_buffer_start_ptr(&cf->buf);
3228 while (i < buf_len) {
3231 c_char = g_ascii_toupper(c_char);
3232 if (c_char == ascii_text[c_match]) {
3234 if (c_match == textlen) {
3235 result = MR_MATCHED;
3236 cf->search_pos = i; /* Save the position of the last character
3237 for highlighting the field. */
3238 cf->search_len = (guint32)textlen;
3244 g_assert(i>=(c_match*2));
3245 i -= (guint32)c_match*2;
3254 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3256 cbs_t *info = (cbs_t *)criterion;
3257 const guint8 *binary_data = info->data;
3258 size_t datalen = info->data_len;
3259 match_result result;
3265 /* Load the frame's data. */
3266 if (!cf_read_record(cf, fdata)) {
3267 /* Attempt to get the packet failed. */
3271 result = MR_NOTMATCHED;
3272 buf_len = fdata->cap_len;
3273 pd = ws_buffer_start_ptr(&cf->buf);
3275 while (i < buf_len) {
3276 if (pd[i] == binary_data[c_match]) {
3278 if (c_match == datalen) {
3279 result = MR_MATCHED;
3280 cf->search_pos = i; /* Save the position of the last character
3281 for highlighting the field. */
3282 cf->search_len = (guint32)datalen;
3287 g_assert(i>=c_match);
3288 i -= (guint32)c_match;
3297 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3299 match_result result = MR_NOTMATCHED;
3300 GMatchInfo *match_info = NULL;
3302 /* Load the frame's data. */
3303 if (!cf_read_record(cf, fdata)) {
3304 /* Attempt to get the packet failed. */
3308 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3309 0, (GRegexMatchFlags) 0, &match_info, NULL))
3311 gint start_pos = 0, end_pos = 0;
3312 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3313 cf->search_pos = end_pos - 1;
3314 cf->search_len = end_pos - start_pos;
3315 result = MR_MATCHED;
3321 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3322 search_direction dir)
3324 return find_packet(cf, match_dfilter, sfcode, dir);
3328 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3329 search_direction dir)
3334 if (!dfilter_compile(filter, &sfcode, NULL)) {
3336 * XXX - this shouldn't happen, as the filter string is machine
3341 if (sfcode == NULL) {
3343 * XXX - this shouldn't happen, as the filter string is machine
3348 result = find_packet(cf, match_dfilter, sfcode, dir);
3349 dfilter_free(sfcode);
3354 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3356 dfilter_t *sfcode = (dfilter_t *)criterion;
3358 match_result result;
3360 /* Load the frame's data. */
3361 if (!cf_read_record(cf, fdata)) {
3362 /* Attempt to get the packet failed. */
3366 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3367 epan_dissect_prime_dfilter(&edt, sfcode);
3368 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3369 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3370 epan_dissect_cleanup(&edt);
3375 cf_find_packet_marked(capture_file *cf, search_direction dir)
3377 return find_packet(cf, match_marked, NULL, dir);
3381 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3383 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3387 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3389 return find_packet(cf, match_time_reference, NULL, dir);
3393 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3395 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3399 find_packet(capture_file *cf,
3400 match_result (*match_function)(capture_file *, frame_data *, void *),
3401 void *criterion, search_direction dir)
3403 frame_data *start_fd;
3406 frame_data *new_fd = NULL;
3407 progdlg_t *progbar = NULL;
3408 GTimer *prog_timer = g_timer_new();
3412 GTimeVal start_time;
3413 gchar status_str[100];
3415 match_result result;
3417 start_fd = cf->current_frame;
3418 if (start_fd != NULL) {
3419 /* Iterate through the list of packets, starting at the packet we've
3420 picked, calling a routine to run the filter on the packet, see if
3421 it matches, and stop if so. */
3423 framenum = start_fd->num;
3425 g_timer_start(prog_timer);
3426 /* Progress so far. */
3429 cf->stop_flag = FALSE;
3430 g_get_current_time(&start_time);
3432 title = cf->sfilter?cf->sfilter:"";
3434 /* Create the progress bar if necessary.
3435 We check on every iteration of the loop, so that it takes no
3436 longer than the standard time to create it (otherwise, for a
3437 large file, we might take considerably longer than that standard
3438 time in order to get to the next progress bar step). */
3439 if (progbar == NULL)
3440 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3441 FALSE, &cf->stop_flag, &start_time, progbar_val);
3444 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3445 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3446 * likely trigger UI paint events, which might take a while depending on
3447 * the platform and display. Reset our timer *after* painting.
3449 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3450 /* let's not divide by zero. I should never be started
3451 * with count == 0, so let's assert that
3453 g_assert(cf->count > 0);
3455 progbar_val = (gfloat) count / cf->count;
3457 g_snprintf(status_str, sizeof(status_str),
3458 "%4u of %u packets", count, cf->count);
3459 update_progress_dlg(progbar, progbar_val, status_str);
3461 g_timer_start(prog_timer);
3464 if (cf->stop_flag) {
3465 /* Well, the user decided to abort the search. Go back to the
3466 frame where we started. */
3471 /* Go past the current frame. */
3472 if (dir == SD_BACKWARD) {
3473 /* Go on to the previous frame. */
3474 if (framenum == 1) {
3476 * XXX - other apps have a bit more of a detailed message
3477 * for this, and instead of offering "OK" and "Cancel",
3478 * they offer things such as "Continue" and "Cancel";
3479 * we need an API for popping up alert boxes with
3480 * {Verb} and "Cancel".
3483 if (prefs.gui_find_wrap)
3485 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3486 framenum = cf->count; /* wrap around */
3490 statusbar_push_temporary_msg("Search reached the beginning.");
3491 framenum = start_fd->num; /* stay on previous packet */
3496 /* Go on to the next frame. */
3497 if (framenum == cf->count) {
3498 if (prefs.gui_find_wrap)
3500 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3501 framenum = 1; /* wrap around */
3505 statusbar_push_temporary_msg("Search reached the end.");
3506 framenum = start_fd->num; /* stay on previous packet */
3511 fdata = frame_data_sequence_find(cf->frames, framenum);
3515 /* Is this packet in the display? */
3516 if (fdata->flags.passed_dfilter) {
3517 /* Yes. Does it match the search criterion? */
3518 result = (*match_function)(cf, fdata, criterion);
3519 if (result == MR_ERROR) {
3520 /* Error; our caller has reported the error. Go back to the frame
3521 where we started. */
3524 } else if (result == MR_MATCHED) {
3525 /* Yes. Go to the new frame. */
3531 if (fdata == start_fd) {
3532 /* We're back to the frame we were on originally, and that frame
3533 doesn't match the search filter. The search failed. */
3538 /* We're done scanning the packets; destroy the progress bar if it
3540 if (progbar != NULL)
3541 destroy_progress_dlg(progbar);
3542 g_timer_destroy(prog_timer);
3545 if (new_fd != NULL) {
3546 /* Find and select */
3547 cf->search_in_progress = TRUE;
3548 found = packet_list_select_row_from_data(new_fd);
3549 cf->search_in_progress = FALSE;
3550 cf->search_pos = 0; /* Reset the position */
3551 cf->search_len = 0; /* Reset length */
3553 /* We didn't find a row corresponding to this frame.
3554 This means that the frame isn't being displayed currently,
3555 so we can't select it. */
3556 simple_message_box(ESD_TYPE_INFO, NULL,
3557 "The capture file is probably not fully dissected.",
3558 "End of capture exceeded.");
3561 return TRUE; /* success */
3563 return FALSE; /* failure */
3567 cf_goto_frame(capture_file *cf, guint fnumber)
3571 if (cf == NULL || cf->frames == NULL) {
3572 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3573 statusbar_push_temporary_msg("There is no file loaded");
3574 return FALSE; /* we failed to go to that packet */
3577 fdata = frame_data_sequence_find(cf->frames, fnumber);
3579 if (fdata == NULL) {
3580 /* we didn't find a packet with that packet number */
3581 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3582 return FALSE; /* we failed to go to that packet */
3584 if (!fdata->flags.passed_dfilter) {
3585 /* that packet currently isn't displayed */
3586 /* XXX - add it to the set of displayed packets? */
3587 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3588 return FALSE; /* we failed to go to that packet */
3591 if (!packet_list_select_row_from_data(fdata)) {
3592 /* We didn't find a row corresponding to this frame.
3593 This means that the frame isn't being displayed currently,
3594 so we can't select it. */
3595 simple_message_box(ESD_TYPE_INFO, NULL,
3596 "The capture file is probably not fully dissected.",
3597 "End of capture exceeded.");
3600 return TRUE; /* we got to that packet */
3604 * Go to frame specified by currently selected protocol tree item.
3607 cf_goto_framenum(capture_file *cf)
3609 header_field_info *hfinfo;
3612 if (cf->finfo_selected) {
3613 hfinfo = cf->finfo_selected->hfinfo;
3615 if (hfinfo->type == FT_FRAMENUM) {
3616 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3618 return cf_goto_frame(cf, framenum);
3625 /* Select the packet on a given row. */
3627 cf_select_packet(capture_file *cf, int row)
3629 epan_dissect_t *old_edt;
3632 /* Get the frame data struct pointer for this frame */
3633 fdata = packet_list_get_row_data(row);
3635 if (fdata == NULL) {
3639 /* Get the data in that frame. */
3640 if (!cf_read_record (cf, fdata)) {
3644 /* Record that this frame is the current frame. */
3645 cf->current_frame = fdata;
3646 cf->current_row = row;
3649 /* Create the logical protocol tree. */
3650 /* We don't need the columns here. */
3651 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3653 tap_build_interesting(cf->edt);
3654 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3655 cf->current_frame, NULL);
3657 dfilter_macro_build_ftv_cache(cf->edt->tree);
3659 cf_callback_invoke(cf_cb_packet_selected, cf);
3661 if (old_edt != NULL)
3662 epan_dissect_free(old_edt);
3666 /* Unselect the selected packet, if any. */
3668 cf_unselect_packet(capture_file *cf)
3670 epan_dissect_t *old_edt = cf->edt;
3674 /* No packet is selected. */
3675 cf->current_frame = NULL;
3676 cf->current_row = 0;
3678 cf_callback_invoke(cf_cb_packet_unselected, cf);
3680 /* No protocol tree means no selected field. */
3681 cf_unselect_field(cf);
3683 /* Destroy the epan_dissect_t for the unselected packet. */
3684 if (old_edt != NULL)
3685 epan_dissect_free(old_edt);
3688 /* Unset the selected protocol tree field, if any. */
3690 cf_unselect_field(capture_file *cf)
3692 cf->finfo_selected = NULL;
3694 cf_callback_invoke(cf_cb_field_unselected, cf);
3698 * Mark a particular frame.
3701 cf_mark_frame(capture_file *cf, frame_data *frame)
3703 if (! frame->flags.marked) {
3704 frame->flags.marked = TRUE;
3705 if (cf->count > cf->marked_count)
3711 * Unmark a particular frame.
3714 cf_unmark_frame(capture_file *cf, frame_data *frame)
3716 if (frame->flags.marked) {
3717 frame->flags.marked = FALSE;
3718 if (cf->marked_count > 0)
3724 * Ignore a particular frame.
3727 cf_ignore_frame(capture_file *cf, frame_data *frame)
3729 if (! frame->flags.ignored) {
3730 frame->flags.ignored = TRUE;
3731 if (cf->count > cf->ignored_count)
3732 cf->ignored_count++;
3737 * Un-ignore a particular frame.
3740 cf_unignore_frame(capture_file *cf, frame_data *frame)
3742 if (frame->flags.ignored) {
3743 frame->flags.ignored = FALSE;
3744 if (cf->ignored_count > 0)
3745 cf->ignored_count--;
3750 * Read the comment in SHB block
3754 cf_read_shb_comment(capture_file *cf)
3756 wtap_block_t shb_inf;
3760 /* XXX - support multiple SHBs */
3761 shb_inf = wtap_file_get_shb(cf->wth);
3763 /* Get the first comment from the SHB. */
3764 /* XXX - support multiple comments */
3765 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3771 cf_update_capture_comment(capture_file *cf, gchar *comment)
3773 wtap_block_t shb_inf;
3777 /* XXX - support multiple SHBs */
3778 shb_inf = wtap_file_get_shb(cf->wth);
3780 /* Get the first comment from the SHB. */
3781 /* XXX - support multiple comments */
3782 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3783 /* There's no comment - add one. */
3784 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3786 /* See if the comment has changed or not */
3787 if (strcmp(shb_comment, comment) == 0) {
3792 /* The comment has changed, let's update it */
3793 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3795 /* Mark the file as having unsaved changes */
3796 cf->unsaved_changes = TRUE;
3800 cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
3802 if (cf->frames_user_comments)
3803 return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
3810 cf_get_comment(capture_file *cf, const frame_data *fd)
3814 /* fetch user comment */
3815 if (fd->flags.has_user_comment)
3816 return g_strdup(cf_get_user_packet_comment(cf, fd));
3818 /* fetch phdr comment */
3819 if (fd->flags.has_phdr_comment) {
3820 struct wtap_pkthdr phdr; /* Packet header */
3821 Buffer buf; /* Packet data */
3823 wtap_phdr_init(&phdr);
3824 ws_buffer_init(&buf, 1500);
3826 if (!cf_read_record_r(cf, fd, &phdr, &buf))
3827 { /* XXX, what we can do here? */ }
3829 comment = phdr.opt_comment;
3830 wtap_phdr_cleanup(&phdr);
3831 ws_buffer_free(&buf);
3838 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3840 const frame_data *fdata1 = (const frame_data *) a;
3841 const frame_data *fdata2 = (const frame_data *) b;
3843 return (fdata1->num < fdata2->num) ? -1 :
3844 (fdata1->num > fdata2->num) ? 1 :
3849 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3851 char *pkt_comment = cf_get_comment(cf, fd);
3853 /* Check if the comment has changed */
3854 if (!g_strcmp0(pkt_comment, new_comment)) {
3855 g_free(pkt_comment);
3858 g_free(pkt_comment);
3861 cf->packet_comment_count--;
3864 cf->packet_comment_count++;
3866 fd->flags.has_user_comment = TRUE;
3868 if (!cf->frames_user_comments)
3869 cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
3871 /* insert new packet comment */
3872 g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
3874 expert_update_comment_count(cf->packet_comment_count);
3876 /* OK, we have unsaved changes. */
3877 cf->unsaved_changes = TRUE;
3882 * What types of comments does this capture file have?
3885 cf_comment_types(capture_file *cf)
3887 guint32 comment_types = 0;
3889 if (cf_read_shb_comment(cf) != NULL)
3890 comment_types |= WTAP_COMMENT_PER_SECTION;
3891 if (cf->packet_comment_count != 0)
3892 comment_types |= WTAP_COMMENT_PER_PACKET;
3893 return comment_types;
3897 * Add a resolved address to this file's list of resolved addresses.
3900 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
3903 * XXX - support multiple resolved address lists, and add to the one
3904 * attached to this file?
3906 if (!add_ip_name_from_string(addr, name))
3909 /* OK, we have unsaved changes. */
3910 cf->unsaved_changes = TRUE;
3914 #ifdef WANT_PACKET_EDITOR
3916 g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3927 modified_frame_data_free(gpointer data)
3929 modified_frame_data *mfd = (modified_frame_data *)data;
3936 * Give a frame new, edited data.
3939 cf_set_frame_edited(capture_file *cf, frame_data *fd,
3940 struct wtap_pkthdr *phdr, guint8 *pd)
3942 modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data));
3945 mfd->pd = (char *)pd;
3947 if (cf->edited_frames == NULL)
3948 cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL,
3949 modified_frame_data_free);
3950 g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd);
3953 /* Mark the file as having unsaved changes */
3954 cf->unsaved_changes = TRUE;
3962 } save_callback_args_t;
3965 * Save a capture to a file, in a particular format, saving either
3966 * all packets, all currently-displayed packets, or all marked packets.
3968 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3969 * up a message box for the failure.
3972 save_record(capture_file *cf, frame_data *fdata,
3973 struct wtap_pkthdr *phdr, const guint8 *pd,
3976 save_callback_args_t *args = (save_callback_args_t *)argsp;
3977 struct wtap_pkthdr hdr;
3980 gchar *display_basename;
3981 const char *pkt_comment;
3983 if (fdata->flags.has_user_comment)
3984 pkt_comment = cf_get_user_packet_comment(cf, fdata);
3986 pkt_comment = phdr->opt_comment;
3988 /* init the wtap header for saving */
3989 /* TODO: reuse phdr */
3990 /* XXX - these are the only flags that correspond to data that we have
3991 in the frame_data structure and that matter on a per-packet basis.
3993 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
3994 and "on the wire" lengths, or it doesn't.
3996 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
3999 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
4000 from the packet flags. */
4001 hdr.rec_type = phdr->rec_type;
4002 hdr.presence_flags = 0;
4003 if (fdata->flags.has_ts)
4004 hdr.presence_flags |= WTAP_HAS_TS;
4005 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
4006 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
4007 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
4008 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
4010 hdr.caplen = phdr->caplen;
4011 hdr.len = phdr->len;
4012 hdr.pkt_encap = phdr->pkt_encap;
4014 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
4016 hdr.pack_flags = phdr->pack_flags;
4017 hdr.opt_comment = g_strdup(pkt_comment);
4020 hdr.pseudo_header = phdr->pseudo_header;
4023 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
4025 /* and save the packet */
4026 if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
4028 /* Wiretap error. */
4031 case WTAP_ERR_UNWRITABLE_ENCAP:
4033 * This is a problem with the particular frame we're writing and
4034 * the file type and subtype we're writing; note that, and report
4035 * the frame number and file type/subtype.
4037 simple_error_message_box(
4038 "Frame %u has a network type that can't be saved in a \"%s\" file.",
4039 fdata->num, wtap_file_type_subtype_string(args->file_type));
4042 case WTAP_ERR_PACKET_TOO_LARGE:
4044 * This is a problem with the particular frame we're writing and
4045 * the file type and subtype we're writing; note that, and report
4046 * the frame number and file type/subtype.
4048 simple_error_message_box(
4049 "Frame %u is larger than Wireshark supports in a \"%s\" file.",
4050 fdata->num, wtap_file_type_subtype_string(args->file_type));
4053 case WTAP_ERR_UNWRITABLE_REC_TYPE:
4055 * This is a problem with the particular record we're writing and
4056 * the file type and subtype we're writing; note that, and report
4057 * the record number and file type/subtype.
4059 simple_error_message_box(
4060 "Record %u has a record type that can't be saved in a \"%s\" file.",
4061 fdata->num, wtap_file_type_subtype_string(args->file_type));
4064 case WTAP_ERR_UNWRITABLE_REC_DATA:
4066 * This is a problem with the particular frame we're writing and
4067 * the file type and subtype we're writing; note that, and report
4068 * the frame number and file type/subtype.
4070 simple_error_message_box(
4071 "Record %u has data that can't be saved in a \"%s\" file.\n(%s)",
4072 fdata->num, wtap_file_type_subtype_string(args->file_type),
4073 err_info != NULL ? err_info : "no information supplied");
4078 display_basename = g_filename_display_basename(args->fname);
4079 simple_error_message_box(
4080 "An error occurred while writing to the file \"%s\": %s.",
4081 display_basename, wtap_strerror(err));
4082 g_free(display_basename);
4087 write_failure_alert_box(args->fname, err);
4092 g_free(hdr.opt_comment);
4097 * Can this capture file be written out in any format using Wiretap
4098 * rather than by copying the raw data?
4101 cf_can_write_with_wiretap(capture_file *cf)
4103 /* We don't care whether we support the comments in this file or not;
4104 if we can't, we'll offer the user the option of discarding the
4106 return wtap_dump_can_write(cf->linktypes, 0);
4110 * Should we let the user do a save?
4114 * the file has unsaved changes, and we can save it in some
4115 * format through Wiretap
4119 * the file is a temporary file and has no unsaved changes (so
4120 * that "saving" it just means copying it).
4122 * XXX - we shouldn't allow files to be edited if they can't be saved,
4123 * so cf->unsaved_changes should be true only if the file can be saved.
4125 * We don't care whether we support the comments in this file or not;
4126 * if we can't, we'll offer the user the option of discarding the
4130 cf_can_save(capture_file *cf)
4132 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4133 /* Saved changes, and we can write it out with Wiretap. */
4137 if (cf->is_tempfile && !cf->unsaved_changes) {
4139 * Temporary file with no unsaved changes, so we can just do a
4145 /* Nothing to save. */
4150 * Should we let the user do a "save as"?
4154 * we can save it in some format through Wiretap
4158 * the file is a temporary file and has no unsaved changes (so
4159 * that "saving" it just means copying it).
4161 * XXX - we shouldn't allow files to be edited if they can't be saved,
4162 * so cf->unsaved_changes should be true only if the file can be saved.
4164 * We don't care whether we support the comments in this file or not;
4165 * if we can't, we'll offer the user the option of discarding the
4169 cf_can_save_as(capture_file *cf)
4171 if (wtap_dump_can_write(cf->linktypes, 0)) {
4172 /* We can write it out with Wiretap. */
4176 if (cf->is_tempfile && !cf->unsaved_changes) {
4178 * Temporary file with no unsaved changes, so we can just do a
4184 /* Nothing to save. */
4189 * Does this file have unsaved data?
4192 cf_has_unsaved_data(capture_file *cf)
4195 * If this is a temporary file, or a file with unsaved changes, it
4198 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4202 * Quick scan to find packet offsets.
4204 static cf_read_status_t
4205 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
4207 const struct wtap_pkthdr *phdr;
4211 progdlg_t *progbar = NULL;
4212 GTimer *prog_timer = g_timer_new();
4215 GTimeVal start_time;
4216 gchar status_str[100];
4221 /* Close the old handle. */
4222 wtap_close(cf->wth);
4224 /* Open the new file. */
4225 /* XXX: this will go through all open_routines for a matching one. But right
4226 now rescan_file() is only used when a file is being saved to a different
4227 format than the original, and the user is not given a choice of which
4228 reader to use (only which format to save it in), so doing this makes
4230 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, err, &err_info, TRUE);
4231 if (cf->wth == NULL) {
4232 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
4233 return CF_READ_ERROR;
4236 /* We're scanning a file whose contents should be the same as what
4237 we had before, so we don't discard dissection state etc.. */
4240 /* Set the file name because we need it to set the follow stream filter.
4241 XXX - is that still true? We need it for other reasons, though,
4243 cf->filename = g_strdup(fname);
4245 /* Indicate whether it's a permanent or temporary file. */
4246 cf->is_tempfile = is_tempfile;
4248 /* No user changes yet. */
4249 cf->unsaved_changes = FALSE;
4251 cf->cd_t = wtap_file_type_subtype(cf->wth);
4252 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4254 cf->snap = wtap_snapshot_length(cf->wth);
4255 if (cf->snap == 0) {
4256 /* Snapshot length not known. */
4257 cf->has_snap = FALSE;
4258 cf->snap = WTAP_MAX_PACKET_SIZE;
4260 cf->has_snap = TRUE;
4262 name_ptr = g_filename_display_basename(cf->filename);
4264 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4266 /* Record whether the file is compressed.
4267 XXX - do we know this at open time? */
4268 cf->iscompressed = wtap_iscompressed(cf->wth);
4270 /* Find the size of the file. */
4271 size = wtap_file_size(cf->wth, NULL);
4273 g_timer_start(prog_timer);
4275 cf->stop_flag = FALSE;
4276 g_get_current_time(&start_time);
4279 phdr = wtap_phdr(cf->wth);
4280 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
4282 fdata = frame_data_sequence_find(cf->frames, framenum);
4283 fdata->file_off = data_offset;
4286 cf->f_datalen = wtap_read_so_far(cf->wth);
4288 /* Create the progress bar if necessary. */
4289 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4290 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4291 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4292 TRUE, &cf->stop_flag, &start_time, progbar_val);
4296 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4297 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4298 * likely trigger UI paint events, which might take a while depending on
4299 * the platform and display. Reset our timer *after* painting.
4301 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4302 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4303 /* update the packet bar content on the first run or frequently on very large files */
4304 update_progress_dlg(progbar, progbar_val, status_str);
4305 packets_bar_update();
4306 g_timer_start(prog_timer);
4310 if (cf->stop_flag) {
4311 /* Well, the user decided to abort the rescan. Sadly, as this
4312 isn't a reread, recovering is difficult, so we'll just
4313 close the current capture. */
4317 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4318 it's not already there.
4319 XXX - yes, this is O(N), so if every packet had a different
4320 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4321 there are probably going to be a small number of encapsulation types
4323 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4326 /* Free the display name */
4329 /* We're done reading the file; destroy the progress bar if it was created. */
4330 if (progbar != NULL)
4331 destroy_progress_dlg(progbar);
4332 g_timer_destroy(prog_timer);
4334 /* We're done reading sequentially through the file. */
4335 cf->state = FILE_READ_DONE;
4337 /* Close the sequential I/O side, to free up memory it requires. */
4338 wtap_sequential_close(cf->wth);
4340 /* compute the time it took to load the file */
4341 compute_elapsed(cf, &start_time);
4343 /* Set the file encapsulation type now; we don't know what it is until
4344 we've looked at all the packets, as we don't know until then whether
4345 there's more than one type (and thus whether it's
4346 WTAP_ENCAP_PER_PACKET). */
4347 cf->lnk_t = wtap_file_encap(cf->wth);
4349 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4351 if (cf->stop_flag) {
4352 /* Our caller will give up at this point. */
4353 return CF_READ_ABORTED;
4357 /* Put up a message box noting that the read failed somewhere along
4358 the line. Don't throw out the stuff we managed to read, though,
4362 case WTAP_ERR_UNSUPPORTED:
4363 simple_error_message_box(
4364 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
4365 err_info != NULL ? err_info : "no information supplied");
4369 case WTAP_ERR_SHORT_READ:
4370 simple_error_message_box(
4371 "The capture file appears to have been cut short"
4372 " in the middle of a packet.");
4375 case WTAP_ERR_BAD_FILE:
4376 simple_error_message_box(
4377 "The capture file appears to be damaged or corrupt.\n(%s)",
4378 err_info != NULL ? err_info : "no information supplied");
4382 case WTAP_ERR_DECOMPRESS:
4383 simple_error_message_box(
4384 "The compressed capture file appears to be damaged or corrupt.\n"
4386 err_info != NULL ? err_info : "no information supplied");
4391 simple_error_message_box(
4392 "An error occurred while reading the"
4393 " capture file: %s.", wtap_strerror(*err));
4396 return CF_READ_ERROR;
4402 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4403 gboolean compressed, gboolean discard_comments,
4404 gboolean dont_reopen)
4407 gchar *fname_new = NULL;
4410 addrinfo_lists_t *addr_lists;
4414 gchar *display_basename;
4421 save_callback_args_t callback_args;
4423 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4425 addr_lists = get_addrinfo_list();
4427 if (save_format == cf->cd_t && compressed == cf->iscompressed
4428 && !discard_comments && !cf->unsaved_changes
4429 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4430 /* We're saving in the format it's already in, and we're
4431 not discarding comments, and there are no changes we have
4432 in memory that aren't saved to the file, and we have no name
4433 resolution blocks to write, so we can just move or copy the raw data. */
4435 if (cf->is_tempfile) {
4436 /* The file being saved is a temporary file from a live
4437 capture, so it doesn't need to stay around under that name;
4438 first, try renaming the capture buffer file to the new name.
4439 This acts as a "safe save", in that, if the file already
4440 exists, the existing file will be removed only if the rename
4443 Sadly, on Windows, as we have the current capture file
4444 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4445 (to cause the rename to remove an existing target), as
4446 done by ws_stdio_rename() (ws_rename() is #defined to
4447 be ws_stdio_rename() on Windows) will fail.
4449 According to the MSDN documentation for CreateFile(), if,
4450 when we open a capture file, we were to directly do a CreateFile(),
4451 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4452 convert it to a file descriptor with _open_osfhandle(),
4453 that would allow the file to be renamed out from under us.
4455 However, that doesn't work in practice. Perhaps the problem
4456 is that the process doing the rename is the process that
4457 has the file open. */
4459 if (ws_rename(cf->filename, fname) == 0) {
4460 /* That succeeded - there's no need to copy the source file. */
4461 how_to_save = SAVE_WITH_MOVE;
4463 if (errno == EXDEV) {
4464 /* They're on different file systems, so we have to copy the
4466 how_to_save = SAVE_WITH_COPY;
4468 /* The rename failed, but not because they're on different
4469 file systems - put up an error message. (Or should we
4470 just punt and try to copy? The only reason why I'd
4471 expect the rename to fail and the copy to succeed would
4472 be if we didn't have permission to remove the file from
4473 the temporary directory, and that might be fixable - but
4474 is it worth requiring the user to go off and fix it?) */
4475 cf_rename_failure_alert_box(fname, errno);
4480 how_to_save = SAVE_WITH_COPY;
4483 /* It's a permanent file, so we should copy it, and not remove the
4485 how_to_save = SAVE_WITH_COPY;
4488 if (how_to_save == SAVE_WITH_COPY) {
4489 /* Copy the file, if we haven't moved it. If we're overwriting
4490 an existing file, we do it with a "safe save", by writing
4491 to a new file and, if the write succeeds, renaming the
4492 new file on top of the old file. */
4493 if (file_exists(fname)) {
4494 fname_new = g_strdup_printf("%s~", fname);
4495 if (!copy_file_binary_mode(cf->filename, fname_new))
4498 if (!copy_file_binary_mode(cf->filename, fname))
4503 /* Either we're saving in a different format or we're saving changes,
4504 such as added, modified, or removed comments, that haven't yet
4505 been written to the underlying file; we can't do that by copying
4506 or moving the capture file, we have to do it by writing the packets
4509 GArray *shb_hdrs = NULL;
4510 wtapng_iface_descriptions_t *idb_inf = NULL;
4511 GArray *nrb_hdrs = NULL;
4514 /* XXX: what free's this shb_hdr? */
4515 shb_hdrs = wtap_file_get_shb_for_new_file(cf->wth);
4516 idb_inf = wtap_file_get_idb_info(cf->wth);
4517 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
4519 /* Determine what file encapsulation type we should use. */
4520 encap = wtap_dump_file_encap_type(cf->linktypes);
4522 if (file_exists(fname)) {
4523 /* We're overwriting an existing file; write out to a new file,
4524 and, if that succeeds, rename the new file on top of the
4525 old file. That makes this a "safe save", so that we don't
4526 lose the old file if we have a problem writing out the new
4527 file. (If the existing file is the current capture file,
4528 we *HAVE* to do that, otherwise we're overwriting the file
4529 from which we're reading the packets that we're writing!) */
4530 fname_new = g_strdup_printf("%s~", fname);
4531 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4532 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4534 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4535 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4541 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4545 /* Add address resolution */
4546 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4548 /* Iterate through the list of packets, processing all the packets. */
4549 callback_args.pdh = pdh;
4550 callback_args.fname = fname;
4551 callback_args.file_type = save_format;
4552 switch (process_specified_records(cf, NULL, "Saving", "packets",
4553 TRUE, save_record, &callback_args, TRUE)) {
4556 /* Completed successfully. */
4560 /* The user decided to abort the saving.
4561 If we're writing to a temporary file, remove it.
4562 XXX - should we do so even if we're not writing to a
4564 wtap_dump_close(pdh, &err);
4565 if (fname_new != NULL)
4566 ws_unlink(fname_new);
4567 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4568 return CF_WRITE_ABORTED;
4571 /* Error while saving.
4572 If we're writing to a temporary file, remove it. */
4573 if (fname_new != NULL)
4574 ws_unlink(fname_new);
4575 wtap_dump_close(pdh, &err);
4579 if (!wtap_dump_close(pdh, &err)) {
4580 cf_close_failure_alert_box(fname, err);
4584 how_to_save = SAVE_WITH_WTAP;
4587 if (fname_new != NULL) {
4588 /* We wrote out to fname_new, and should rename it on top of
4589 fname. fname_new is now closed, so that should be possible even
4590 on Windows. However, on Windows, we first need to close whatever
4591 file descriptors we have open for fname. */
4593 wtap_fdclose(cf->wth);
4595 /* Now do the rename. */
4596 if (ws_rename(fname_new, fname) == -1) {
4597 /* Well, the rename failed. */
4598 cf_rename_failure_alert_box(fname, errno);
4600 /* Attempt to reopen the random file descriptor using the
4601 current file's filename. (At this point, the sequential
4602 file descriptor is closed.) */
4603 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4604 /* Oh, well, we're screwed. */
4605 display_basename = g_filename_display_basename(cf->filename);
4606 simple_error_message_box(
4607 file_open_error_message(err, FALSE), display_basename);
4608 g_free(display_basename);
4615 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4616 cf->unsaved_changes = FALSE;
4619 switch (how_to_save) {
4621 case SAVE_WITH_MOVE:
4622 /* We just moved the file, so the wtap structure refers to the
4623 new file, and all the information other than the filename
4624 and the "is temporary" status applies to the new file; just
4626 g_free(cf->filename);
4627 cf->filename = g_strdup(fname);
4628 cf->is_tempfile = FALSE;
4629 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4632 case SAVE_WITH_COPY:
4633 /* We just copied the file, s all the information other than
4634 the wtap structure, the filename, and the "is temporary"
4635 status applies to the new file; just update that. */
4636 wtap_close(cf->wth);
4637 /* Although we're just "copying" and then opening the copy, it will
4638 try all open_routine readers to open the copy, so we need to
4639 reset the cfile's open_type. */
4640 cf->open_type = WTAP_TYPE_AUTO;
4641 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4642 if (cf->wth == NULL) {
4643 cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
4646 g_free(cf->filename);
4647 cf->filename = g_strdup(fname);
4648 cf->is_tempfile = FALSE;
4650 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4653 case SAVE_WITH_WTAP:
4654 /* Open and read the file we saved to.
4656 XXX - this is somewhat of a waste; we already have the
4657 packets, all this gets us is updated file type information
4658 (which we could just stuff into "cf"), and having the new
4659 file be the one we have opened and from which we're reading
4660 the data, and it means we have to spend time opening and
4661 reading the file, which could be a significant amount of
4662 time if the file is large.
4664 If the capture-file-writing code were to return the
4665 seek offset of each packet it writes, we could save that
4666 in the frame_data structure for the frame, and just open
4667 the file without reading it again...
4669 ...as long as, for gzipped files, the process of writing
4670 out the file *also* generates the information needed to
4671 support fast random access to the compressed file. */
4672 /* rescan_file will cause us to try all open_routines, so
4673 reset cfile's open_type */
4674 cf->open_type = WTAP_TYPE_AUTO;
4675 if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) {
4676 /* The rescan failed; just close the file. Either
4677 a dialog was popped up for the failure, so the
4678 user knows what happened, or they stopped the
4679 rescan, in which case they know what happened. */
4685 /* If we were told to discard the comments, do so. */
4686 if (discard_comments) {
4687 /* Remove SHB comment, if any. */
4688 wtap_write_shb_comment(cf->wth, NULL);
4690 /* remove all user comments */
4691 for (framenum = 1; framenum <= cf->count; framenum++) {
4692 fdata = frame_data_sequence_find(cf->frames, framenum);
4694 fdata->flags.has_phdr_comment = FALSE;
4695 fdata->flags.has_user_comment = FALSE;
4698 if (cf->frames_user_comments) {
4699 g_tree_destroy(cf->frames_user_comments);
4700 cf->frames_user_comments = NULL;
4703 cf->packet_comment_count = 0;
4709 if (fname_new != NULL) {
4710 /* We were trying to write to a temporary file; get rid of it if it
4711 exists. (We don't care whether this fails, as, if it fails,
4712 there's not much we can do about it. I guess if it failed for
4713 a reason other than "it doesn't exist", we could report an
4714 error, so the user knows there's a junk file that they might
4715 want to clean up.) */
4716 ws_unlink(fname_new);
4719 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4720 return CF_WRITE_ERROR;
4724 cf_export_specified_packets(capture_file *cf, const char *fname,
4725 packet_range_t *range, guint save_format,
4726 gboolean compressed)
4728 gchar *fname_new = NULL;
4731 save_callback_args_t callback_args;
4732 GArray *shb_hdrs = NULL;
4733 wtapng_iface_descriptions_t *idb_inf = NULL;
4734 GArray *nrb_hdrs = NULL;
4737 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4739 packet_range_process_init(range);
4741 /* We're writing out specified packets from the specified capture
4742 file to another file. Even if all captured packets are to be
4743 written, don't special-case the operation - read each packet
4744 and then write it out if it's one of the specified ones. */
4746 /* XXX: what free's this shb_hdr? */
4747 shb_hdrs = wtap_file_get_shb_for_new_file(cf->wth);
4748 idb_inf = wtap_file_get_idb_info(cf->wth);
4749 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
4751 /* Determine what file encapsulation type we should use. */
4752 encap = wtap_dump_file_encap_type(cf->linktypes);
4754 if (file_exists(fname)) {
4755 /* We're overwriting an existing file; write out to a new file,
4756 and, if that succeeds, rename the new file on top of the
4757 old file. That makes this a "safe save", so that we don't
4758 lose the old file if we have a problem writing out the new
4759 file. (If the existing file is the current capture file,
4760 we *HAVE* to do that, otherwise we're overwriting the file
4761 from which we're reading the packets that we're writing!) */
4762 fname_new = g_strdup_printf("%s~", fname);
4763 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4764 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4766 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4767 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4773 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4777 /* Add address resolution */
4778 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4780 /* Iterate through the list of packets, processing the packets we were
4783 XXX - we've already called "packet_range_process_init(range)", but
4784 "process_specified_records()" will do it again. Fortunately,
4785 that's harmless in this case, as we haven't done anything to
4786 "range" since we initialized it. */
4787 callback_args.pdh = pdh;
4788 callback_args.fname = fname;
4789 callback_args.file_type = save_format;
4790 switch (process_specified_records(cf, range, "Writing", "specified records",
4791 TRUE, save_record, &callback_args, TRUE)) {
4794 /* Completed successfully. */
4798 /* The user decided to abort the saving.
4799 If we're writing to a temporary file, remove it.
4800 XXX - should we do so even if we're not writing to a
4802 wtap_dump_close(pdh, &err);
4803 if (fname_new != NULL)
4804 ws_unlink(fname_new);
4805 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4806 return CF_WRITE_ABORTED;
4810 /* Error while saving.
4811 If we're writing to a temporary file, remove it. */
4812 if (fname_new != NULL)
4813 ws_unlink(fname_new);
4814 wtap_dump_close(pdh, &err);
4818 if (!wtap_dump_close(pdh, &err)) {
4819 cf_close_failure_alert_box(fname, err);
4823 if (fname_new != NULL) {
4824 /* We wrote out to fname_new, and should rename it on top of
4825 fname; fname is now closed, so that should be possible even
4826 on Windows. Do the rename. */
4827 if (ws_rename(fname_new, fname) == -1) {
4828 /* Well, the rename failed. */
4829 cf_rename_failure_alert_box(fname, errno);
4834 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4838 if (fname_new != NULL) {
4839 /* We were trying to write to a temporary file; get rid of it if it
4840 exists. (We don't care whether this fails, as, if it fails,
4841 there's not much we can do about it. I guess if it failed for
4842 a reason other than "it doesn't exist", we could report an
4843 error, so the user knows there's a junk file that they might
4844 want to clean up.) */
4845 ws_unlink(fname_new);
4848 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4849 return CF_WRITE_ERROR;
4853 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
4854 gboolean for_writing, int file_type)
4856 gchar *display_basename;
4859 /* Wiretap error. */
4860 display_basename = g_filename_display_basename(filename);
4863 case WTAP_ERR_NOT_REGULAR_FILE:
4864 simple_error_message_box(
4865 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4869 case WTAP_ERR_RANDOM_OPEN_PIPE:
4870 /* Seen only when opening a capture file for reading. */
4871 simple_error_message_box(
4872 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.\n"
4873 "To capture from a pipe or FIFO use wireshark -i -",
4877 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
4878 /* Seen only when opening a capture file for reading. */
4879 simple_error_message_box(
4880 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
4884 case WTAP_ERR_UNSUPPORTED:
4885 /* Seen only when opening a capture file for reading. */
4886 simple_error_message_box(
4887 "The file \"%s\" contains record data that Wireshark doesn't support.\n"
4890 err_info != NULL ? err_info : "no information supplied");
4894 case WTAP_ERR_CANT_WRITE_TO_PIPE:
4895 /* Seen only when opening a capture file for writing. */
4896 simple_error_message_box(
4897 "The file \"%s\" is a pipe, and %s capture files can't be "
4898 "written to a pipe.",
4899 display_basename, wtap_file_type_subtype_string(file_type));
4902 case WTAP_ERR_UNWRITABLE_FILE_TYPE:
4903 /* Seen only when opening a capture file for writing. */
4904 simple_error_message_box(
4905 "Wireshark doesn't support writing capture files in that format.");
4908 case WTAP_ERR_UNWRITABLE_ENCAP:
4909 /* Seen only when opening a capture file for writing. */
4910 simple_error_message_box("Wireshark can't save this capture in that format.");
4913 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
4915 simple_error_message_box(
4916 "Wireshark can't save this capture in that format.");
4918 simple_error_message_box(
4919 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
4924 case WTAP_ERR_BAD_FILE:
4925 /* Seen only when opening a capture file for reading. */
4926 simple_error_message_box(
4927 "The file \"%s\" appears to be damaged or corrupt.\n"
4930 err_info != NULL ? err_info : "no information supplied");
4934 case WTAP_ERR_CANT_OPEN:
4936 simple_error_message_box(
4937 "The file \"%s\" could not be created for some unknown reason.",
4940 simple_error_message_box(
4941 "The file \"%s\" could not be opened for some unknown reason.",
4946 case WTAP_ERR_SHORT_READ:
4947 simple_error_message_box(
4948 "The file \"%s\" appears to have been cut short"
4949 " in the middle of a packet or other data.",
4953 case WTAP_ERR_SHORT_WRITE:
4954 simple_error_message_box(
4955 "A full header couldn't be written to the file \"%s\".",
4959 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4960 simple_error_message_box(
4961 "This file type cannot be written as a compressed file.");
4964 case WTAP_ERR_DECOMPRESS:
4965 simple_error_message_box(
4966 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
4967 "(%s)", display_basename,
4968 err_info != NULL ? err_info : "no information supplied");
4973 simple_error_message_box(
4974 "The file \"%s\" could not be %s: %s.",
4976 for_writing ? "created" : "opened",
4977 wtap_strerror(err));
4980 g_free(display_basename);
4983 open_failure_alert_box(filename, err, for_writing);
4988 * XXX - whether we mention the source pathname, the target pathname,
4989 * or both depends on the error and on what we find if we look for
4990 * one or both of them.
4993 cf_rename_failure_alert_box(const char *filename, int err)
4995 gchar *display_basename;
4997 display_basename = g_filename_display_basename(filename);
5001 /* XXX - should check whether the source exists and, if not,
5002 report it as the problem and, if so, report the destination
5004 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
5009 /* XXX - if we're doing a rename after a safe save, we should
5010 probably say something else. */
5011 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
5016 /* XXX - this should probably mention both the source and destination
5018 simple_error_message_box("The file \"%s\" could not be moved: %s.",
5019 display_basename, wtap_strerror(err));
5022 g_free(display_basename);
5025 /* Check for write errors - if the file is being written to an NFS server,
5026 a write error may not show up until the file is closed, as NFS clients
5027 might not send writes to the server until the "write()" call finishes,
5028 so that the write may fail on the server but the "write()" may succeed. */
5030 cf_close_failure_alert_box(const char *filename, int err)
5032 gchar *display_basename;
5035 /* Wiretap error. */
5036 display_basename = g_filename_display_basename(filename);
5039 case WTAP_ERR_CANT_CLOSE:
5040 simple_error_message_box(
5041 "The file \"%s\" couldn't be closed for some unknown reason.",
5045 case WTAP_ERR_SHORT_WRITE:
5046 simple_error_message_box(
5047 "Not all the packets could be written to the file \"%s\".",
5052 simple_error_message_box(
5053 "An error occurred while closing the file \"%s\": %s.",
5054 display_basename, wtap_strerror(err));
5057 g_free(display_basename);
5060 We assume that a close error from the OS is really a write error. */
5061 write_failure_alert_box(filename, err);
5065 /* Reload the current capture file. */
5067 cf_reload(capture_file *cf) {
5069 gboolean is_tempfile;
5072 /* If the file could be opened, "cf_open()" calls "cf_close()"
5073 to get rid of state for the old capture file before filling in state
5074 for the new capture file. "cf_close()" will remove the file if
5075 it's a temporary file; we don't want that to happen (for one thing,
5076 it'd prevent subsequent reopens from working). Remember whether it's
5077 a temporary file, mark it as not being a temporary file, and then
5078 reopen it as the type of file it was.
5080 Also, "cf_close()" will free "cf->filename", so we must make
5081 a copy of it first. */
5082 filename = g_strdup(cf->filename);
5083 is_tempfile = cf->is_tempfile;
5084 cf->is_tempfile = FALSE;
5085 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
5086 switch (cf_read(cf, TRUE)) {
5090 /* Just because we got an error, that doesn't mean we were unable
5091 to read any of the file; we handle what we could get from the
5095 case CF_READ_ABORTED:
5096 /* The user bailed out of re-reading the capture file; the
5097 capture file has been closed - just free the capture file name
5098 string and return (without changing the last containing
5104 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
5105 Instead, the file was left open, so we should restore "cf->is_tempfile"
5108 XXX - change the menu? Presumably "cf_open()" will do that;
5109 make sure it does! */
5110 cf->is_tempfile = is_tempfile;
5112 /* "cf_open()" made a copy of the file name we handed it, so
5113 we should free up our copy. */
5123 * indent-tabs-mode: nil
5126 * ex: set shiftwidth=2 tabstop=8 expandtab:
5127 * :indentSize=2:tabSize=8:noTabs=true: