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_interface_description = cap_file_get_interface_description;
287 epan->get_user_comment = ws_get_user_comment;
293 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
298 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
302 /* The open succeeded. Close whatever capture file we had open,
303 and fill in the information for this file. */
306 /* Initialize the packet header. */
307 wtap_phdr_init(&cf->phdr);
309 /* XXX - we really want to initialize this after we've read all
310 the packets, so we know how much we'll ultimately need. */
311 ws_buffer_init(&cf->buf, 1500);
313 /* Create new epan session for dissection.
314 * (The old one was freed in cf_close().)
316 cf->epan = ws_epan_new(cf);
318 /* We're about to start reading the file. */
319 cf->state = FILE_READ_IN_PROGRESS;
324 /* Set the file name because we need it to set the follow stream filter.
325 XXX - is that still true? We need it for other reasons, though,
327 cf->filename = g_strdup(fname);
329 /* Indicate whether it's a permanent or temporary file. */
330 cf->is_tempfile = is_tempfile;
332 /* No user changes yet. */
333 cf->unsaved_changes = FALSE;
335 cf->computed_elapsed = 0;
337 cf->cd_t = wtap_file_type_subtype(cf->wth);
338 cf->open_type = type;
339 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
341 cf->packet_comment_count = 0;
342 cf->displayed_count = 0;
343 cf->marked_count = 0;
344 cf->ignored_count = 0;
345 cf->ref_time_count = 0;
346 cf->drops_known = FALSE;
348 cf->snap = wtap_snapshot_length(cf->wth);
350 /* Snapshot length not known. */
351 cf->has_snap = FALSE;
352 cf->snap = WTAP_MAX_PACKET_SIZE;
356 /* Allocate a frame_data_sequence for the frames in this file */
357 cf->frames = new_frame_data_sequence();
359 nstime_set_zero(&cf->elapsed_time);
365 packet_list_queue_draw();
366 cf_callback_invoke(cf_cb_file_opened, cf);
368 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
369 /* tell the BER dissector the file name */
370 ber_set_filename(cf->filename);
373 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
374 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
379 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
384 * Add an encapsulation type to cf->linktypes.
387 cf_add_encapsulation_type(capture_file *cf, int encap)
391 for (i = 0; i < cf->linktypes->len; i++) {
392 if (g_array_index(cf->linktypes, gint, i) == encap)
393 return; /* it's already there */
395 /* It's not already there - add it. */
396 g_array_append_val(cf->linktypes, encap);
399 /* Reset everything to a pristine state */
401 cf_close(capture_file *cf)
403 cf->stop_flag = FALSE;
404 if (cf->state == FILE_CLOSED)
405 return; /* Nothing to do */
407 /* Die if we're in the middle of reading a file. */
408 g_assert(cf->state != FILE_READ_IN_PROGRESS);
410 cf_callback_invoke(cf_cb_file_closing, cf);
412 /* close things, if not already closed before */
413 color_filters_cleanup();
419 /* We have no file open... */
420 if (cf->filename != NULL) {
421 /* If it's a temporary file, remove it. */
423 ws_unlink(cf->filename);
424 g_free(cf->filename);
427 /* ...which means we have no changes to that file to save. */
428 cf->unsaved_changes = FALSE;
430 /* no open_routine type */
431 cf->open_type = WTAP_TYPE_AUTO;
433 /* Clean up the packet header. */
434 wtap_phdr_cleanup(&cf->phdr);
436 /* Free up the packet buffer. */
437 ws_buffer_free(&cf->buf);
439 dfilter_free(cf->rfcode);
441 if (cf->frames != NULL) {
442 free_frame_data_sequence(cf->frames);
445 #ifdef WANT_PACKET_EDITOR
446 if (cf->edited_frames) {
447 g_tree_destroy(cf->edited_frames);
448 cf->edited_frames = NULL;
451 if (cf->frames_user_comments) {
452 g_tree_destroy(cf->frames_user_comments);
453 cf->frames_user_comments = NULL;
455 cf_unselect_packet(cf); /* nothing to select */
456 cf->first_displayed = 0;
457 cf->last_displayed = 0;
459 /* No frames, no frame selected, no field in that frame selected. */
461 cf->current_frame = 0;
463 cf->finfo_selected = NULL;
465 /* No frame link-layer types, either. */
466 if (cf->linktypes != NULL) {
467 g_array_free(cf->linktypes, TRUE);
468 cf->linktypes = NULL;
471 /* Clear the packet list. */
472 packet_list_freeze();
477 nstime_set_zero(&cf->elapsed_time);
479 reset_tap_listeners();
484 /* We have no file open. */
485 cf->state = FILE_CLOSED;
487 cf_callback_invoke(cf_cb_file_closed, cf);
491 * TRUE if the progress dialog doesn't exist and it looks like we'll
492 * take > 2s to load, FALSE otherwise.
494 static inline gboolean
495 progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
499 if (progdlg) return FALSE;
500 elapsed = g_timer_elapsed(prog_timer, NULL);
501 if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
502 || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
509 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
513 progbar_val = (gfloat) file_pos / (gfloat) size;
514 if (progbar_val > 1.0) {
516 /* The file probably grew while we were reading it.
517 * Update file size, and try again.
519 size = wtap_file_size(cf->wth, NULL);
522 progbar_val = (gfloat) file_pos / (gfloat) size;
524 /* If it's still > 1, either "wtap_file_size()" failed (in which
525 * case there's not much we can do about it), or the file
526 * *shrank* (in which case there's not much we can do about
527 * it); just clip the progress value at 1.0.
529 if (progbar_val > 1.0f)
533 g_snprintf(status_str, status_size,
534 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
535 file_pos / 1024, size / 1024);
541 cf_read(capture_file *cf, gboolean reloading)
544 gchar *err_info = NULL;
546 progdlg_t *volatile progbar = NULL;
547 GTimer *prog_timer = g_timer_new();
551 volatile gboolean create_proto_tree;
555 /* Compile the current display filter.
556 * We assume this will not fail since cf->dfilter is only set in
557 * cf_filter IFF the filter was valid.
559 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
560 g_assert(!cf->dfilter || (compiled && dfcode));
562 /* Get the union of the flags for all tap listeners. */
563 tap_flags = union_of_tap_listener_flags();
565 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
567 reset_tap_listeners();
569 name_ptr = g_filename_display_basename(cf->filename);
572 cf_callback_invoke(cf_cb_file_reload_started, cf);
574 cf_callback_invoke(cf_cb_file_read_started, cf);
576 /* Record whether the file is compressed.
577 XXX - do we know this at open time? */
578 cf->iscompressed = wtap_iscompressed(cf->wth);
580 /* The packet list window will be empty until the file is completly loaded */
581 packet_list_freeze();
583 cf->stop_flag = FALSE;
584 g_get_current_time(&start_time);
586 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
596 gchar status_str[100];
600 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
602 /* Find the size of the file. */
603 size = wtap_file_size(cf->wth, NULL);
605 g_timer_start(prog_timer);
607 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
610 file_pos = wtap_read_so_far(cf->wth);
612 /* Create the progress bar if necessary. */
613 if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
614 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
616 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
617 TRUE, &cf->stop_flag, &start_time, progbar_val);
619 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
620 TRUE, &cf->stop_flag, &start_time, progbar_val);
624 * Update the progress bar, but do it only after
625 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
626 * and packets_bar_update will likely trigger UI paint events, which
627 * might take a while depending on the platform and display. Reset
628 * our timer *after* painting.
630 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
631 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
632 /* update the packet bar content on the first run or frequently on very large files */
633 update_progress_dlg(progbar, progbar_val, status_str);
634 packets_bar_update();
635 g_timer_start(prog_timer);
640 /* Well, the user decided to abort the read. He/She will be warned and
641 it might be enough for him/her to work with the already loaded
643 This is especially true for very large capture files, where you don't
644 want to wait loading the whole file (which may last minutes or even
645 hours even on fast machines) just to see that it was the wrong file. */
648 read_packet(cf, dfcode, &edt, cinfo, data_offset);
651 CATCH(OutOfMemoryError) {
652 simple_message_box(ESD_TYPE_ERROR, NULL,
653 "More information and workarounds can be found at\n"
654 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
655 "Sorry, but Wireshark has run out of memory and has to terminate now.");
657 /* Could we close the current capture and free up memory from that? */
659 /* we have to terminate, as we cannot recover from the memory error */
665 /* Free the display name */
668 /* Cleanup and release all dfilter resources */
669 if (dfcode != NULL) {
670 dfilter_free(dfcode);
673 epan_dissect_cleanup(&edt);
675 /* We're done reading the file; destroy the progress bar if it was created. */
677 destroy_progress_dlg(progbar);
678 g_timer_destroy(prog_timer);
680 /* We're done reading sequentially through the file. */
681 cf->state = FILE_READ_DONE;
683 /* Close the sequential I/O side, to free up memory it requires. */
684 wtap_sequential_close(cf->wth);
686 /* Allow the protocol dissectors to free up memory that they
687 * don't need after the sequential run-through of the packets. */
688 postseq_cleanup_all_protocols();
690 /* compute the time it took to load the file */
691 compute_elapsed(cf, &start_time);
693 /* Set the file encapsulation type now; we don't know what it is until
694 we've looked at all the packets, as we don't know until then whether
695 there's more than one type (and thus whether it's
696 WTAP_ENCAP_PER_PACKET). */
697 cf->lnk_t = wtap_file_encap(cf->wth);
699 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
704 cf_callback_invoke(cf_cb_file_reload_finished, cf);
706 cf_callback_invoke(cf_cb_file_read_finished, cf);
708 /* If we have any displayed packets to select, select the first of those
709 packets by making the first row the selected row. */
710 if (cf->first_displayed != 0) {
711 packet_list_select_first_row();
715 simple_message_box(ESD_TYPE_WARN, NULL,
716 "The remaining packets in the file were discarded.\n"
718 "As a lot of packets from the original file will be missing,\n"
719 "remember to be careful when saving the current content to a file.\n",
720 "File loading was cancelled.");
721 return CF_READ_ERROR;
725 /* Put up a message box noting that the read failed somewhere along
726 the line. Don't throw out the stuff we managed to read, though,
730 case WTAP_ERR_UNSUPPORTED:
731 simple_error_message_box(
732 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
733 err_info != NULL ? err_info : "no information supplied");
737 case WTAP_ERR_SHORT_READ:
738 simple_error_message_box(
739 "The capture file appears to have been cut short"
740 " in the middle of a packet.");
743 case WTAP_ERR_BAD_FILE:
744 simple_error_message_box(
745 "The capture file appears to be damaged or corrupt.\n(%s)",
746 err_info != NULL ? err_info : "no information supplied");
750 case WTAP_ERR_DECOMPRESS:
751 simple_error_message_box(
752 "The compressed capture file appears to be damaged or corrupt.\n(%s)",
753 err_info != NULL ? err_info : "no information supplied");
758 simple_error_message_box(
759 "An error occurred while reading the"
760 " capture file: %s.", wtap_strerror(err));
763 return CF_READ_ERROR;
770 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
773 volatile int newly_displayed_packets = 0;
776 gboolean create_proto_tree;
780 /* Compile the current display filter.
781 * We assume this will not fail since cf->dfilter is only set in
782 * cf_filter IFF the filter was valid.
784 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
785 g_assert(!cf->dfilter || (compiled && dfcode));
787 /* Get the union of the flags for all tap listeners. */
788 tap_flags = union_of_tap_listener_flags();
790 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
794 packet_list_check_end();
795 /* Don't freeze/thaw the list when doing live capture */
796 /*packet_list_freeze();*/
798 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
800 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
803 gint64 data_offset = 0;
806 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
808 while (to_read != 0) {
809 wtap_cleareof(cf->wth);
810 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
813 if (cf->state == FILE_READ_ABORTED) {
814 /* Well, the user decided to exit Wireshark. Break out of the
815 loop, and let the code below (which is called even if there
816 aren't any packets left to read) exit. */
819 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
820 newly_displayed_packets++;
825 CATCH(OutOfMemoryError) {
826 simple_message_box(ESD_TYPE_ERROR, NULL,
827 "More information and workarounds can be found at\n"
828 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
829 "Sorry, but Wireshark has run out of memory and has to terminate now.");
831 /* Could we close the current capture and free up memory from that? */
832 return CF_READ_ABORTED;
834 /* we have to terminate, as we cannot recover from the memory error */
840 /* Update the file encapsulation; it might have changed based on the
841 packets we've read. */
842 cf->lnk_t = wtap_file_encap(cf->wth);
844 /* Cleanup and release all dfilter resources */
845 if (dfcode != NULL) {
846 dfilter_free(dfcode);
849 epan_dissect_cleanup(&edt);
851 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
852 cf->count, cf->state, *err);*/
854 /* Don't freeze/thaw the list when doing live capture */
855 /*packet_list_thaw();*/
856 /* With the new packet list the first packet
857 * isn't automatically selected.
859 if (!cf->current_frame)
860 packet_list_select_first_row();
862 /* moving to the end of the packet list - if the user requested so and
863 we have some new packets. */
864 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
865 packet_list_moveto_end();
867 if (cf->state == FILE_READ_ABORTED) {
868 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
869 so that our caller can kill off the capture child process;
870 this will cause an EOF on the pipe from the child, so
871 "cf_finish_tail()" will be called, and it will clean up
873 return CF_READ_ABORTED;
874 } else if (*err != 0) {
875 /* We got an error reading the capture file.
876 XXX - pop up a dialog box instead? */
877 if (err_info != NULL) {
878 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
879 wtap_strerror(*err), cf->filename, err_info);
882 g_warning("Error \"%s\" while reading \"%s\"",
883 wtap_strerror(*err), cf->filename);
885 return CF_READ_ERROR;
891 cf_fake_continue_tail(capture_file *cf) {
892 cf->state = FILE_READ_DONE;
896 cf_finish_tail(capture_file *cf, int *err)
903 gboolean create_proto_tree;
907 /* Compile the current display filter.
908 * We assume this will not fail since cf->dfilter is only set in
909 * cf_filter IFF the filter was valid.
911 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
912 g_assert(!cf->dfilter || (compiled && dfcode));
914 /* Get the union of the flags for all tap listeners. */
915 tap_flags = union_of_tap_listener_flags();
916 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
918 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
920 if (cf->wth == NULL) {
922 return CF_READ_ERROR;
925 packet_list_check_end();
926 /* Don't freeze/thaw the list when doing live capture */
927 /*packet_list_freeze();*/
929 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
931 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
932 if (cf->state == FILE_READ_ABORTED) {
933 /* Well, the user decided to abort the read. Break out of the
934 loop, and let the code below (which is called even if there
935 aren't any packets left to read) exit. */
938 read_packet(cf, dfcode, &edt, cinfo, data_offset);
941 /* Cleanup and release all dfilter resources */
942 if (dfcode != NULL) {
943 dfilter_free(dfcode);
946 epan_dissect_cleanup(&edt);
948 /* Don't freeze/thaw the list when doing live capture */
949 /*packet_list_thaw();*/
951 if (cf->state == FILE_READ_ABORTED) {
952 /* Well, the user decided to abort the read. We're only called
953 when the child capture process closes the pipe to us (meaning
954 it's probably exited), so we can just close the capture
955 file; we return CF_READ_ABORTED so our caller can do whatever
956 is appropriate when that happens. */
958 return CF_READ_ABORTED;
961 if (auto_scroll_live && cf->count != 0)
962 packet_list_moveto_end();
964 /* We're done reading sequentially through the file. */
965 cf->state = FILE_READ_DONE;
967 /* We're done reading sequentially through the file; close the
968 sequential I/O side, to free up memory it requires. */
969 wtap_sequential_close(cf->wth);
971 /* Allow the protocol dissectors to free up memory that they
972 * don't need after the sequential run-through of the packets. */
973 postseq_cleanup_all_protocols();
975 /* Update the file encapsulation; it might have changed based on the
976 packets we've read. */
977 cf->lnk_t = wtap_file_encap(cf->wth);
979 /* Update the details in the file-set dialog, as the capture file
980 * has likely grown since we first stat-ed it */
981 fileset_update_file(cf->filename);
984 /* We got an error reading the capture file.
985 XXX - pop up a dialog box? */
986 if (err_info != NULL) {
987 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
988 wtap_strerror(*err), cf->filename, err_info);
991 g_warning("Error \"%s\" while reading \"%s\"",
992 wtap_strerror(*err), cf->filename);
994 return CF_READ_ERROR;
999 #endif /* HAVE_LIBPCAP */
1002 cf_get_display_name(capture_file *cf)
1006 /* Return a name to use in displays */
1007 if (!cf->is_tempfile) {
1008 /* Get the last component of the file name, and use that. */
1010 displayname = g_filename_display_basename(cf->filename);
1012 displayname=g_strdup("(No file)");
1015 /* The file we read is a temporary file from a live capture or
1016 a merge operation; we don't mention its name, but, if it's
1017 from a capture, give the source of the capture. */
1019 displayname = g_strdup(cf->source);
1021 displayname = g_strdup("(Untitled)");
1027 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1033 cf->source = g_strdup(source);
1035 cf->source = g_strdup("");
1039 const gchar *cf_get_tempfile_source(capture_file *cf) {
1047 /* XXX - use a macro instead? */
1049 cf_get_packet_count(capture_file *cf)
1054 /* XXX - use a macro instead? */
1056 cf_is_tempfile(capture_file *cf)
1058 return cf->is_tempfile;
1061 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1063 cf->is_tempfile = is_tempfile;
1067 /* XXX - use a macro instead? */
1068 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1070 cf->drops_known = drops_known;
1073 /* XXX - use a macro instead? */
1074 void cf_set_drops(capture_file *cf, guint32 drops)
1079 /* XXX - use a macro instead? */
1080 gboolean cf_get_drops_known(capture_file *cf)
1082 return cf->drops_known;
1085 /* XXX - use a macro instead? */
1086 guint32 cf_get_drops(capture_file *cf)
1091 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1093 cf->rfcode = rfcode;
1097 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1098 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1099 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1103 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1104 &cf->ref, cf->prev_dis);
1105 cf->prev_cap = fdata;
1107 if (dfcode != NULL) {
1108 epan_dissect_prime_dfilter(edt, dfcode);
1111 /* Prepare coloring rules, this ensures that display filter rules containing
1112 * frame.color_rule references are still processed.
1113 * TODO: actually detect that situation or maybe apply other optimizations? */
1114 if (edt->tree && color_filters_used()) {
1115 color_filters_prime_edt(edt);
1116 fdata->flags.need_colorize = 1;
1120 /* Dissect the frame. */
1121 epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1123 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1124 if (dfcode != NULL) {
1125 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1127 if (fdata->flags.passed_dfilter) {
1128 /* This frame passed the display filter but it may depend on other
1129 * (potentially not displayed) frames. Find those frames and mark them
1132 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
1135 fdata->flags.passed_dfilter = 1;
1137 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1138 cf->displayed_count++;
1140 if (add_to_packet_list) {
1141 /* We fill the needed columns from new_packet_list */
1142 row = packet_list_append(cinfo, fdata);
1145 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1147 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1148 cf->prev_dis = fdata;
1150 /* If we haven't yet seen the first frame, this is it. */
1151 if (cf->first_displayed == 0)
1152 cf->first_displayed = fdata->num;
1154 /* This is the last frame we've seen so far. */
1155 cf->last_displayed = fdata->num;
1158 epan_dissect_reset(edt);
1162 /* read in a new packet */
1163 /* returns the row of the new packet in the packet list or -1 if not displayed */
1165 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1166 column_info *cinfo, gint64 offset)
1168 struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1169 const guint8 *buf = wtap_buf_ptr(cf->wth);
1176 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1177 it's not already there.
1178 XXX - yes, this is O(N), so if every packet had a different
1179 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1180 there are probably going to be a small number of encapsulation types
1182 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1184 /* The frame number of this packet is one more than the count of
1185 frames in the file so far. */
1186 framenum = cf->count + 1;
1188 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1192 epan_dissect_t rf_edt;
1194 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1195 epan_dissect_prime_dfilter(&rf_edt, cf->rfcode);
1196 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1197 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1198 epan_dissect_cleanup(&rf_edt);
1202 /* This does a shallow copy of fdlocal, which is good enough. */
1203 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1206 if (phdr->opt_comment != NULL)
1207 cf->packet_comment_count++;
1208 cf->f_datalen = offset + fdlocal.cap_len;
1210 if (!cf->redissecting) {
1211 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1212 cinfo, phdr, buf, TRUE);
1220 typedef struct _callback_data_t {
1223 GTimeVal start_time;
1231 merge_callback(merge_event event, int num _U_,
1232 const merge_in_file_t in_files[], const guint in_file_count,
1236 callback_data_t *cb_data = (callback_data_t*) data;
1238 g_assert(cb_data != NULL);
1242 case MERGE_EVENT_INPUT_FILES_OPENED:
1246 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1250 case MERGE_EVENT_READY_TO_MERGE:
1251 /* Get the sum of the sizes of all the files. */
1252 for (i = 0; i < in_file_count; i++)
1253 cb_data->f_len += in_files[i].size;
1255 cb_data->prog_timer = g_timer_new();
1256 g_timer_start(cb_data->prog_timer);
1258 g_get_current_time(&cb_data->start_time);
1261 case MERGE_EVENT_PACKET_WAS_READ:
1263 gint64 data_offset = 0;
1265 /* Get the sum of the data offsets in all of the files. */
1267 for (i = 0; i < in_file_count; i++)
1268 data_offset += in_files[i].data_offset;
1270 /* Create the progress bar if necessary.
1271 We check on every iteration of the loop, so that it takes no
1272 longer than the standard time to create it (otherwise, for a
1273 large file, we might take considerably longer than that standard
1274 time in order to get to the next progress bar step). */
1275 if (cb_data->progbar == NULL) {
1276 cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1277 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1281 * Update the progress bar, but do it only after
1282 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1283 * and packets_bar_update will likely trigger UI paint events, which
1284 * might take a while depending on the platform and display. Reset
1285 * our timer *after* painting.
1287 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1289 gint64 file_pos = 0;
1290 /* Get the sum of the seek positions in all of the files. */
1291 for (i = 0; i < in_file_count; i++)
1292 file_pos += wtap_read_so_far(in_files[i].wth);
1294 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1295 if (progbar_val > 1.0f) {
1296 /* Some file probably grew while we were reading it.
1297 That "shouldn't happen", so we'll just clip the progress
1302 if (cb_data->progbar != NULL) {
1303 gchar status_str[100];
1304 g_snprintf(status_str, sizeof(status_str),
1305 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1306 file_pos / 1024, cb_data->f_len / 1024);
1307 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1309 g_timer_start(cb_data->prog_timer);
1314 case MERGE_EVENT_DONE:
1315 /* We're done merging the files; destroy the progress bar if it was created. */
1316 if (cb_data->progbar != NULL)
1317 destroy_progress_dlg(cb_data->progbar);
1318 g_timer_destroy(cb_data->prog_timer);
1322 return cb_data->stop_flag;
1328 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1329 int in_file_count, char *const *in_filenames,
1330 int file_type, gboolean do_append)
1333 gchar *err_info = NULL;
1335 merge_result status;
1336 merge_progress_callback_t cb;
1337 callback_data_t *cb_data = g_new0(callback_data_t, 1);
1339 /* prepare our callback routine */
1340 cb_data->pd_window = pd_window;
1341 cb.callback_func = merge_callback;
1344 cf_callback_invoke(cf_cb_file_merge_started, NULL);
1346 /* merge the files */
1347 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1348 (const char *const *) in_filenames,
1349 in_file_count, do_append,
1350 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1351 "Wireshark", &cb, &err, &err_info,
1360 case MERGE_USER_ABORTED:
1361 /* this isn't really an error, though we will return CF_ERROR later */
1364 case MERGE_ERR_CANT_OPEN_INFILE:
1365 cf_open_failure_alert_box(in_filenames[err_fileno], err, err_info,
1369 case MERGE_ERR_CANT_OPEN_OUTFILE:
1370 cf_open_failure_alert_box(*out_filenamep, err, err_info, TRUE,
1374 case MERGE_ERR_CANT_READ_INFILE: /* fall through */
1375 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1376 case MERGE_ERR_CANT_WRITE_OUTFILE:
1377 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1379 simple_error_message_box("%s", err_info ? err_info : "unknown error");
1385 cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1387 if (status != MERGE_OK) {
1388 /* Callers aren't expected to treat an error or an explicit abort
1389 differently - we put up error dialogs ourselves, so they don't
1397 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1399 const char *filter_new = dftext ? dftext : "";
1400 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1403 GTimeVal start_time;
1405 /* if new filter equals old one, do nothing unless told to do so */
1406 if (!force && strcmp(filter_new, filter_old) == 0) {
1412 if (dftext == NULL) {
1413 /* The new filter is an empty filter (i.e., display all packets).
1414 * so leave dfcode==NULL
1418 * We have a filter; make a copy of it (as we'll be saving it),
1419 * and try to compile it.
1421 dftext = g_strdup(dftext);
1422 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1423 /* The attempt failed; report an error. */
1424 simple_message_box(ESD_TYPE_ERROR, NULL,
1425 "See the help for a description of the display filter syntax.",
1426 "\"%s\" isn't a valid display filter: %s",
1434 if (dfcode == NULL) {
1435 /* Yes - free the filter text, and set it to null. */
1441 /* We have a valid filter. Replace the current filter. */
1442 g_free(cf->dfilter);
1443 cf->dfilter = dftext;
1444 g_get_current_time(&start_time);
1447 /* Now rescan the packet list, applying the new filter, but not
1448 throwing away information constructed on a previous pass. */
1449 if (cf->state != FILE_CLOSED) {
1450 if (dftext == NULL) {
1451 rescan_packets(cf, "Resetting", "Filter", FALSE);
1453 rescan_packets(cf, "Filtering", dftext, FALSE);
1457 /* Cleanup and release all dfilter resources */
1458 dfilter_free(dfcode);
1464 cf_reftime_packets(capture_file *cf)
1466 ref_time_packets(cf);
1470 cf_redissect_packets(capture_file *cf)
1472 if (cf->state != FILE_CLOSED) {
1473 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1478 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1479 struct wtap_pkthdr *phdr, Buffer *buf)
1483 gchar *display_basename;
1485 #ifdef WANT_PACKET_EDITOR
1486 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1487 if (G_UNLIKELY(fdata->file_off == -1)) {
1488 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1491 simple_error_message_box("fdata->file_off == -1, but can't find modified frame.");
1495 *phdr = frame->phdr;
1496 ws_buffer_assure_space(buf, frame->phdr.caplen);
1497 memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
1502 if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1503 display_basename = g_filename_display_basename(cf->filename);
1506 case WTAP_ERR_BAD_FILE:
1507 simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)",
1508 display_basename, wtap_strerror(err),
1509 err_info != NULL ? err_info : "no information supplied");
1514 simple_error_message_box(
1515 "An error occurred while reading from the file \"%s\": %s.",
1516 display_basename, wtap_strerror(err));
1519 g_free(display_basename);
1526 cf_read_record(capture_file *cf, frame_data *fdata)
1528 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1531 /* Rescan the list of packets, reconstructing the CList.
1533 "action" describes why we're doing this; it's used in the progress
1536 "action_item" describes what we're doing; it's used in the progress
1539 "redissect" is TRUE if we need to make the dissectors reconstruct
1540 any state information they have (because a preference that affects
1541 some dissector has changed, meaning some dissector might construct
1542 its state differently from the way it was constructed the last time). */
1544 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1546 /* Rescan packets new packet list */
1549 progdlg_t *progbar = NULL;
1550 GTimer *prog_timer = g_timer_new();
1552 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1553 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1554 gboolean selected_frame_seen;
1556 GTimeVal start_time;
1557 gchar status_str[100];
1561 gboolean create_proto_tree;
1563 gboolean add_to_packet_list = FALSE;
1565 guint32 frames_count;
1567 /* Compile the current display filter.
1568 * We assume this will not fail since cf->dfilter is only set in
1569 * cf_filter IFF the filter was valid.
1571 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1572 g_assert(!cf->dfilter || (compiled && dfcode));
1574 /* Get the union of the flags for all tap listeners. */
1575 tap_flags = union_of_tap_listener_flags();
1576 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1578 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
1580 reset_tap_listeners();
1581 /* Which frame, if any, is the currently selected frame?
1582 XXX - should the selected frame or the focus frame be the "current"
1583 frame, that frame being the one from which "Find Frame" searches
1585 selected_frame = cf->current_frame;
1587 /* Mark frame num as not found */
1588 selected_frame_num = -1;
1590 /* Freeze the packet list while we redo it, so we don't get any
1591 screen updates while it happens. */
1592 packet_list_freeze();
1595 /* We need to re-initialize all the state information that protocols
1596 keep, because some preference that controls a dissector has changed,
1597 which might cause the state information to be constructed differently
1598 by that dissector. */
1600 /* We might receive new packets while redissecting, and we don't
1601 want to dissect those before their time. */
1602 cf->redissecting = TRUE;
1604 /* 'reset' dissection session */
1605 epan_free(cf->epan);
1606 if (cf->edt && cf->edt->pi.fd) {
1607 /* All pointers in "per frame proto data" for the currently selected
1608 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1609 Free them here to avoid unintended usage in packet_list_clear(). */
1610 frame_data_destroy(cf->edt->pi.fd);
1612 cf->epan = ws_epan_new(cf);
1613 cf->cinfo.epan = cf->epan;
1615 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1616 called via epan_new() / init_dissection() when reloading Lua plugins. */
1617 if (!create_proto_tree && have_filtering_tap_listeners()) {
1618 create_proto_tree = TRUE;
1621 /* We need to redissect the packets so we have to discard our old
1622 * packet list store. */
1623 packet_list_clear();
1624 add_to_packet_list = TRUE;
1627 /* We don't yet know which will be the first and last frames displayed. */
1628 cf->first_displayed = 0;
1629 cf->last_displayed = 0;
1631 /* We currently don't display any packets */
1632 cf->displayed_count = 0;
1634 /* Iterate through the list of frames. Call a routine for each frame
1635 to check whether it should be displayed and, if so, add it to
1636 the display list. */
1638 cf->prev_dis = NULL;
1639 cf->prev_cap = NULL;
1642 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1644 g_timer_start(prog_timer);
1645 /* Count of packets at which we've looked. */
1647 /* Progress so far. */
1650 cf->stop_flag = FALSE;
1651 g_get_current_time(&start_time);
1653 /* no previous row yet */
1654 prev_frame_num = -1;
1657 preceding_frame_num = -1;
1658 preceding_frame = NULL;
1659 following_frame_num = -1;
1660 following_frame = NULL;
1662 selected_frame_seen = FALSE;
1664 frames_count = cf->count;
1666 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1668 for (framenum = 1; framenum <= frames_count; framenum++) {
1669 fdata = frame_data_sequence_find(cf->frames, framenum);
1671 /* Create the progress bar if necessary.
1672 We check on every iteration of the loop, so that it takes no
1673 longer than the standard time to create it (otherwise, for a
1674 large file, we might take considerably longer than that standard
1675 time in order to get to the next progress bar step). */
1676 if (progbar == NULL)
1677 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1683 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1684 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1685 * likely trigger UI paint events, which might take a while depending on
1686 * the platform and display. Reset our timer *after* painting.
1688 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1689 /* let's not divide by zero. I should never be started
1690 * with count == 0, so let's assert that
1692 g_assert(cf->count > 0);
1693 progbar_val = (gfloat) count / frames_count;
1695 if (progbar != NULL) {
1696 g_snprintf(status_str, sizeof(status_str),
1697 "%4u of %u frames", count, frames_count);
1698 update_progress_dlg(progbar, progbar_val, status_str);
1701 g_timer_start(prog_timer);
1704 if (cf->stop_flag) {
1705 /* Well, the user decided to abort the filtering. Just stop.
1707 XXX - go back to the previous filter? Users probably just
1708 want not to wait for a filtering operation to finish;
1709 unless we cancel by having no filter, reverting to the
1710 previous filter will probably be even more expensive than
1711 continuing the filtering, as it involves going back to the
1712 beginning and filtering, and even with no filter we currently
1713 have to re-generate the entire clist, which is also expensive.
1715 I'm not sure what Network Monitor does, but it doesn't appear
1716 to give you an unfiltered display if you cancel. */
1723 /* Since all state for the frame was destroyed, mark the frame
1724 * as not visited, free the GSList referring to the state
1725 * data (the per-frame data itself was freed by
1726 * "init_dissection()"), and null out the GSList pointer. */
1727 frame_data_reset(fdata);
1728 frames_count = cf->count;
1731 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1732 fdata->flags.dependent_of_displayed = 0;
1734 if (!cf_read_record(cf, fdata))
1735 break; /* error reading the frame */
1737 /* If the previous frame is displayed, and we haven't yet seen the
1738 selected frame, remember that frame - it's the closest one we've
1739 yet seen before the selected frame. */
1740 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1741 preceding_frame_num = prev_frame_num;
1742 preceding_frame = prev_frame;
1745 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1747 ws_buffer_start_ptr(&cf->buf),
1748 add_to_packet_list);
1750 /* If this frame is displayed, and this is the first frame we've
1751 seen displayed after the selected frame, remember this frame -
1752 it's the closest one we've yet seen at or after the selected
1754 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1755 following_frame_num = fdata->num;
1756 following_frame = fdata;
1758 if (fdata == selected_frame) {
1759 selected_frame_seen = TRUE;
1760 if (fdata->flags.passed_dfilter)
1761 selected_frame_num = fdata->num;
1764 /* Remember this frame - it'll be the previous frame
1765 on the next pass through the loop. */
1766 prev_frame_num = fdata->num;
1770 epan_dissect_cleanup(&edt);
1772 /* We are done redissecting the packet list. */
1773 cf->redissecting = FALSE;
1776 frames_count = cf->count;
1777 /* Clear out what remains of the visited flags and per-frame data
1780 XXX - that may cause various forms of bogosity when dissecting
1781 these frames, as they won't have been seen by this sequential
1782 pass, but the only alternative I see is to keep scanning them
1783 even though the user requested that the scan stop, and that
1784 would leave the user stuck with an Wireshark grinding on
1785 until it finishes. Should we just stick them with that? */
1786 for (; framenum <= frames_count; framenum++) {
1787 fdata = frame_data_sequence_find(cf->frames, framenum);
1788 frame_data_reset(fdata);
1792 /* We're done filtering the packets; destroy the progress bar if it
1794 if (progbar != NULL)
1795 destroy_progress_dlg(progbar);
1796 g_timer_destroy(prog_timer);
1798 /* Unfreeze the packet list. */
1799 if (!add_to_packet_list)
1800 packet_list_recreate_visible_rows();
1802 /* Compute the time it took to filter the file */
1803 compute_elapsed(cf, &start_time);
1807 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1809 if (selected_frame_num == -1) {
1810 /* The selected frame didn't pass the filter. */
1811 if (selected_frame == NULL) {
1812 /* That's because there *was* no selected frame. Make the first
1813 displayed frame the current frame. */
1814 selected_frame_num = 0;
1816 /* Find the nearest displayed frame to the selected frame (whether
1817 it's before or after that frame) and make that the current frame.
1818 If the next and previous displayed frames are equidistant from the
1819 selected frame, choose the next one. */
1820 g_assert(following_frame == NULL ||
1821 following_frame->num >= selected_frame->num);
1822 g_assert(preceding_frame == NULL ||
1823 preceding_frame->num <= selected_frame->num);
1824 if (following_frame == NULL) {
1825 /* No frame after the selected frame passed the filter, so we
1826 have to select the last displayed frame before the selected
1828 selected_frame_num = preceding_frame_num;
1829 selected_frame = preceding_frame;
1830 } else if (preceding_frame == NULL) {
1831 /* No frame before the selected frame passed the filter, so we
1832 have to select the first displayed frame after the selected
1834 selected_frame_num = following_frame_num;
1835 selected_frame = following_frame;
1837 /* Frames before and after the selected frame passed the filter, so
1838 we'll select the previous frame */
1839 selected_frame_num = preceding_frame_num;
1840 selected_frame = preceding_frame;
1845 if (selected_frame_num == -1) {
1846 /* There are no frames displayed at all. */
1847 cf_unselect_packet(cf);
1849 /* Either the frame that was selected passed the filter, or we've
1850 found the nearest displayed frame to that frame. Select it, make
1851 it the focus row, and make it visible. */
1852 /* Set to invalid to force update of packet list and packet details */
1853 cf->current_row = -1;
1854 if (selected_frame_num == 0) {
1855 packet_list_select_first_row();
1857 if (!packet_list_select_row_from_data(selected_frame)) {
1858 /* We didn't find a row corresponding to this frame.
1859 This means that the frame isn't being displayed currently,
1860 so we can't select it. */
1861 simple_message_box(ESD_TYPE_INFO, NULL,
1862 "The capture file is probably not fully dissected.",
1863 "End of capture exceeded.");
1868 /* Cleanup and release all dfilter resources */
1869 dfilter_free(dfcode);
1874 * Scan through all frame data and recalculate the ref time
1875 * without rereading the file.
1876 * XXX - do we need a progres bar or is this fast enough?
1879 ref_time_packets(capture_file *cf)
1886 cf->prev_dis = NULL;
1889 for (framenum = 1; framenum <= cf->count; framenum++) {
1890 fdata = frame_data_sequence_find(cf->frames, framenum);
1892 /* just add some value here until we know if it is being displayed or not */
1893 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1899 /* If we don't have the time stamp of the first packet in the
1900 capture, it's because this is the first packet. Save the time
1901 stamp of this packet as the time stamp of the first packet. */
1902 if (cf->ref == NULL)
1904 /* if this frames is marked as a reference time frame, reset
1905 firstsec and firstusec to this frame */
1906 if (fdata->flags.ref_time)
1909 /* If we don't have the time stamp of the previous displayed packet,
1910 it's because this is the first displayed packet. Save the time
1911 stamp of this packet as the time stamp of the previous displayed
1913 if (cf->prev_dis == NULL) {
1914 cf->prev_dis = fdata;
1917 /* Get the time elapsed between the first packet and this packet. */
1918 fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
1919 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
1921 /* If it's greater than the current elapsed time, set the elapsed time
1922 to it (we check for "greater than" so as not to be confused by
1923 time moving backwards). */
1924 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1925 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1926 cf->elapsed_time = rel_ts;
1929 /* If this frame is displayed, get the time elapsed between the
1930 previous displayed packet and this packet. */
1931 if ( fdata->flags.passed_dfilter ) {
1932 fdata->prev_dis_num = cf->prev_dis->num;
1933 cf->prev_dis = fdata;
1939 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1940 /* This frame either passed the display filter list or is marked as
1941 a time reference frame. All time reference frames are displayed
1942 even if they don't pass the display filter */
1943 if (fdata->flags.ref_time) {
1944 /* if this was a TIME REF frame we should reset the cum_bytes field */
1945 cf->cum_bytes = fdata->pkt_len;
1946 fdata->cum_bytes = cf->cum_bytes;
1948 /* increase cum_bytes with this packets length */
1949 cf->cum_bytes += fdata->pkt_len;
1962 process_specified_records(capture_file *cf, packet_range_t *range,
1963 const char *string1, const char *string2, gboolean terminate_is_stop,
1964 gboolean (*callback)(capture_file *, frame_data *,
1965 struct wtap_pkthdr *, const guint8 *, void *),
1966 void *callback_args,
1967 gboolean show_progress_bar)
1972 psp_return_t ret = PSP_FINISHED;
1974 progdlg_t *progbar = NULL;
1975 GTimer *prog_timer = g_timer_new();
1978 GTimeVal progbar_start_time;
1979 gchar progbar_status_str[100];
1980 range_process_e process_this;
1981 struct wtap_pkthdr phdr;
1983 wtap_phdr_init(&phdr);
1984 ws_buffer_init(&buf, 1500);
1986 g_timer_start(prog_timer);
1987 /* Count of packets at which we've looked. */
1989 /* Progress so far. */
1992 cf->stop_flag = FALSE;
1993 g_get_current_time(&progbar_start_time);
1996 packet_range_process_init(range);
1998 /* Iterate through all the packets, printing the packets that
1999 were selected by the current display filter. */
2000 for (framenum = 1; framenum <= cf->count; framenum++) {
2001 fdata = frame_data_sequence_find(cf->frames, framenum);
2003 /* Create the progress bar if necessary.
2004 We check on every iteration of the loop, so that it takes no
2005 longer than the standard time to create it (otherwise, for a
2006 large file, we might take considerably longer than that standard
2007 time in order to get to the next progress bar step). */
2008 if (show_progress_bar && progbar == NULL)
2009 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2012 &progbar_start_time,
2016 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
2017 * has elapsed. Calling update_progress_dlg and packets_bar_update will
2018 * likely trigger UI paint events, which might take a while depending on
2019 * the platform and display. Reset our timer *after* painting.
2021 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2022 /* let's not divide by zero. I should never be started
2023 * with count == 0, so let's assert that
2025 g_assert(cf->count > 0);
2026 progbar_val = (gfloat) progbar_count / cf->count;
2028 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2029 "%4u of %u packets", progbar_count, cf->count);
2030 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2032 g_timer_start(prog_timer);
2035 if (cf->stop_flag) {
2036 /* Well, the user decided to abort the operation. Just stop,
2037 and arrange to return PSP_STOPPED to our caller, so they know
2038 it was stopped explicitly. */
2045 if (range != NULL) {
2046 /* do we have to process this packet? */
2047 process_this = packet_range_process_packet(range, fdata);
2048 if (process_this == range_process_next) {
2049 /* this packet uninteresting, continue with next one */
2051 } else if (process_this == range_processing_finished) {
2052 /* all interesting packets processed, stop the loop */
2057 /* Get the packet */
2058 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2059 /* Attempt to get the packet failed. */
2063 /* Process the packet */
2064 if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2065 /* Callback failed. We assume it reported the error appropriately. */
2071 /* We're done printing the packets; destroy the progress bar if
2073 if (progbar != NULL)
2074 destroy_progress_dlg(progbar);
2075 g_timer_destroy(prog_timer);
2077 wtap_phdr_cleanup(&phdr);
2078 ws_buffer_free(&buf);
2086 } retap_callback_args_t;
2089 retap_packet(capture_file *cf, frame_data *fdata,
2090 struct wtap_pkthdr *phdr, const guint8 *pd,
2093 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2095 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2096 epan_dissect_reset(&args->edt);
2102 cf_retap_packets(capture_file *cf)
2104 packet_range_t range;
2105 retap_callback_args_t callback_args;
2106 gboolean construct_protocol_tree;
2107 gboolean filtering_tap_listeners;
2111 /* Presumably the user closed the capture file. */
2113 return CF_READ_ABORTED;
2116 cf_callback_invoke(cf_cb_file_retap_started, cf);
2118 /* Do we have any tap listeners with filters? */
2119 filtering_tap_listeners = have_filtering_tap_listeners();
2121 tap_flags = union_of_tap_listener_flags();
2123 /* If any tap listeners have filters, or require the protocol tree,
2124 construct the protocol tree. */
2125 construct_protocol_tree = filtering_tap_listeners ||
2126 (tap_flags & TL_REQUIRES_PROTO_TREE);
2128 /* If any tap listeners require the columns, construct them. */
2129 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2131 /* Reset the tap listeners. */
2132 reset_tap_listeners();
2134 epan_dissect_init(&callback_args.edt, cf->epan, construct_protocol_tree, FALSE);
2136 /* Iterate through the list of packets, dissecting all packets and
2137 re-running the taps. */
2138 packet_range_init(&range, cf);
2139 packet_range_process_init(&range);
2141 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2142 "all packets", TRUE, retap_packet,
2143 &callback_args, TRUE);
2145 epan_dissect_cleanup(&callback_args.edt);
2147 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2151 /* Completed successfully. */
2155 /* Well, the user decided to abort the refiltering.
2156 Return CF_READ_ABORTED so our caller knows they did that. */
2157 return CF_READ_ABORTED;
2160 /* Error while retapping. */
2161 return CF_READ_ERROR;
2164 g_assert_not_reached();
2169 print_args_t *print_args;
2170 gboolean print_header_line;
2171 char *header_line_buf;
2172 int header_line_buf_len;
2173 gboolean print_formfeed;
2174 gboolean print_separator;
2178 int num_visible_cols;
2181 } print_callback_args_t;
2184 print_packet(capture_file *cf, frame_data *fdata,
2185 struct wtap_pkthdr *phdr, const guint8 *pd,
2188 print_callback_args_t *args = (print_callback_args_t *)argsp;
2194 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2195 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2196 col_item_t* col_item;
2198 /* Fill in the column information if we're printing the summary
2200 if (args->print_args->print_summary) {
2201 col_custom_prime_edt(&args->edt, &cf->cinfo);
2202 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2203 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2205 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2207 if (args->print_formfeed) {
2208 if (!new_page(args->print_args->stream))
2211 if (args->print_separator) {
2212 if (!print_line(args->print_args->stream, 0, ""))
2218 * We generate bookmarks, if the output format supports them.
2219 * The name is "__frameN__".
2221 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2223 if (args->print_args->print_summary) {
2224 if (!args->print_args->print_col_headings)
2225 args->print_header_line = FALSE;
2226 if (args->print_header_line) {
2227 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2229 args->print_header_line = FALSE; /* we might not need to print any more */
2231 cp = &args->line_buf[0];
2233 for (i = 0; i < args->num_visible_cols; i++) {
2234 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2235 /* Find the length of the string for this column. */
2236 column_len = (int) strlen(col_item->col_data);
2237 if (args->col_widths[i] > column_len)
2238 column_len = args->col_widths[i];
2240 /* Make sure there's room in the line buffer for the column; if not,
2241 double its length. */
2242 line_len += column_len + 1; /* "+1" for space */
2243 if (line_len > args->line_buf_len) {
2244 cp_off = (int) (cp - args->line_buf);
2245 args->line_buf_len = 2 * line_len;
2246 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2247 cp = args->line_buf + cp_off;
2250 /* Right-justify the packet number column. */
2251 if (col_item->col_fmt == COL_NUMBER)
2252 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2254 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2256 if (i != args->num_visible_cols - 1)
2262 * Generate a bookmark, using the summary line as the title.
2264 if (!print_bookmark(args->print_args->stream, bookmark_name,
2268 if (!print_line(args->print_args->stream, 0, args->line_buf))
2272 * Generate a bookmark, using "Frame N" as the title, as we're not
2273 * printing the summary line.
2275 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2276 if (!print_bookmark(args->print_args->stream, bookmark_name,
2279 } /* if (print_summary) */
2281 if (args->print_args->print_dissections != print_dissections_none) {
2282 if (args->print_args->print_summary) {
2283 /* Separate the summary line from the tree with a blank line. */
2284 if (!print_line(args->print_args->stream, 0, ""))
2288 /* Print the information in that tree. */
2289 if (!proto_tree_print(args->print_args, &args->edt, NULL, args->print_args->stream))
2292 /* Print a blank line if we print anything after this (aka more than one packet). */
2293 args->print_separator = TRUE;
2295 /* Print a header line if we print any more packet summaries */
2296 if (args->print_args->print_col_headings)
2297 args->print_header_line = TRUE;
2300 if (args->print_args->print_hex) {
2301 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2302 if (!print_line(args->print_args->stream, 0, ""))
2305 /* Print the full packet data as hex. */
2306 if (!print_hex_data(args->print_args->stream, &args->edt))
2309 /* Print a blank line if we print anything after this (aka more than one packet). */
2310 args->print_separator = TRUE;
2312 /* Print a header line if we print any more packet summaries */
2313 if (args->print_args->print_col_headings)
2314 args->print_header_line = TRUE;
2315 } /* if (args->print_args->print_dissections != print_dissections_none) */
2317 epan_dissect_reset(&args->edt);
2319 /* do we want to have a formfeed between each packet from now on? */
2320 if (args->print_args->print_formfeed) {
2321 args->print_formfeed = TRUE;
2327 epan_dissect_reset(&args->edt);
2332 cf_print_packets(capture_file *cf, print_args_t *print_args,
2333 gboolean show_progress_bar)
2335 print_callback_args_t callback_args;
2338 int i, cp_off, column_len, line_len;
2339 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2343 gboolean proto_tree_needed;
2345 callback_args.print_args = print_args;
2346 callback_args.print_header_line = print_args->print_col_headings;
2347 callback_args.header_line_buf = NULL;
2348 callback_args.header_line_buf_len = 256;
2349 callback_args.print_formfeed = FALSE;
2350 callback_args.print_separator = FALSE;
2351 callback_args.line_buf = NULL;
2352 callback_args.line_buf_len = 256;
2353 callback_args.col_widths = NULL;
2354 callback_args.num_visible_cols = 0;
2355 callback_args.visible_cols = NULL;
2357 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2358 destroy_print_stream(print_args->stream);
2359 return CF_PRINT_WRITE_ERROR;
2362 if (print_args->print_summary) {
2363 /* We're printing packet summaries. Allocate the header line buffer
2364 and get the column widths. */
2365 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2367 /* Find the number of visible columns and the last visible column */
2368 for (i = 0; i < prefs.num_cols; i++) {
2370 clp = g_list_nth(prefs.col_list, i);
2371 if (clp == NULL) /* Sanity check, Invalid column requested */
2374 cfmt = (fmt_data *) clp->data;
2375 if (cfmt->visible) {
2377 last_visible_col = i;
2381 /* Find the widths for each of the columns - maximum of the
2382 width of the title and the width of the data - and construct
2383 a buffer with a line containing the column titles. */
2384 callback_args.num_visible_cols = num_visible_col;
2385 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2386 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2387 cp = &callback_args.header_line_buf[0];
2389 visible_col_count = 0;
2390 for (i = 0; i < cf->cinfo.num_cols; i++) {
2392 clp = g_list_nth(prefs.col_list, i);
2393 if (clp == NULL) /* Sanity check, Invalid column requested */
2396 cfmt = (fmt_data *) clp->data;
2397 if (cfmt->visible == FALSE)
2400 /* Save the order of visible columns */
2401 callback_args.visible_cols[visible_col_count] = i;
2403 /* Don't pad the last column. */
2404 if (i == last_visible_col)
2405 callback_args.col_widths[visible_col_count] = 0;
2407 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2408 data_width = get_column_char_width(get_column_format(i));
2409 if (data_width > callback_args.col_widths[visible_col_count])
2410 callback_args.col_widths[visible_col_count] = data_width;
2413 /* Find the length of the string for this column. */
2414 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2415 if (callback_args.col_widths[i] > column_len)
2416 column_len = callback_args.col_widths[visible_col_count];
2418 /* Make sure there's room in the line buffer for the column; if not,
2419 double its length. */
2420 line_len += column_len + 1; /* "+1" for space */
2421 if (line_len > callback_args.header_line_buf_len) {
2422 cp_off = (int) (cp - callback_args.header_line_buf);
2423 callback_args.header_line_buf_len = 2 * line_len;
2424 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2425 callback_args.header_line_buf_len + 1);
2426 cp = callback_args.header_line_buf + cp_off;
2429 /* Right-justify the packet number column. */
2430 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2431 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2433 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2435 if (i != cf->cinfo.num_cols - 1)
2438 visible_col_count++;
2442 /* Now start out the main line buffer with the same length as the
2443 header line buffer. */
2444 callback_args.line_buf_len = callback_args.header_line_buf_len;
2445 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2446 } /* if (print_summary) */
2448 /* Create the protocol tree, and make it visible, if we're printing
2449 the dissection or the hex data.
2450 XXX - do we need it if we're just printing the hex data? */
2452 callback_args.print_args->print_dissections != print_dissections_none ||
2453 callback_args.print_args->print_hex ||
2454 have_custom_cols(&cf->cinfo) || have_field_extractors();
2455 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2457 /* Iterate through the list of packets, printing the packets we were
2459 ret = process_specified_records(cf, &print_args->range, "Printing",
2460 "selected packets", TRUE, print_packet,
2461 &callback_args, show_progress_bar);
2462 epan_dissect_cleanup(&callback_args.edt);
2463 g_free(callback_args.header_line_buf);
2464 g_free(callback_args.line_buf);
2465 g_free(callback_args.col_widths);
2466 g_free(callback_args.visible_cols);
2471 /* Completed successfully. */
2475 /* Well, the user decided to abort the printing.
2477 XXX - note that what got generated before they did that
2478 will get printed if we're piping to a print program; we'd
2479 have to write to a file and then hand that to the print
2480 program to make it actually not print anything. */
2484 /* Error while printing.
2486 XXX - note that what got generated before they did that
2487 will get printed if we're piping to a print program; we'd
2488 have to write to a file and then hand that to the print
2489 program to make it actually not print anything. */
2490 destroy_print_stream(print_args->stream);
2491 return CF_PRINT_WRITE_ERROR;
2494 if (!print_finale(print_args->stream)) {
2495 destroy_print_stream(print_args->stream);
2496 return CF_PRINT_WRITE_ERROR;
2499 if (!destroy_print_stream(print_args->stream))
2500 return CF_PRINT_WRITE_ERROR;
2508 print_args_t *print_args;
2509 } write_packet_callback_args_t;
2512 write_pdml_packet(capture_file *cf, frame_data *fdata,
2513 struct wtap_pkthdr *phdr, const guint8 *pd,
2516 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2518 /* Create the protocol tree, but don't fill in the column information. */
2519 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2521 /* Write out the information in that tree. */
2522 write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, args->fh);
2524 epan_dissect_reset(&args->edt);
2526 return !ferror(args->fh);
2530 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2532 write_packet_callback_args_t callback_args;
2536 fh = ws_fopen(print_args->file, "w");
2538 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2540 write_pdml_preamble(fh, cf->filename);
2543 return CF_PRINT_WRITE_ERROR;
2546 callback_args.fh = fh;
2547 callback_args.print_args = print_args;
2548 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2550 /* Iterate through the list of packets, printing the packets we were
2552 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2553 "selected packets", TRUE,
2554 write_pdml_packet, &callback_args, TRUE);
2556 epan_dissect_cleanup(&callback_args.edt);
2561 /* Completed successfully. */
2565 /* Well, the user decided to abort the printing. */
2569 /* Error while printing. */
2571 return CF_PRINT_WRITE_ERROR;
2574 write_pdml_finale(fh);
2577 return CF_PRINT_WRITE_ERROR;
2580 /* XXX - check for an error */
2587 write_psml_packet(capture_file *cf, frame_data *fdata,
2588 struct wtap_pkthdr *phdr, const guint8 *pd,
2591 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2593 /* Fill in the column information */
2594 col_custom_prime_edt(&args->edt, &cf->cinfo);
2595 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2596 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2598 /* Write out the column information. */
2599 write_psml_columns(&args->edt, args->fh);
2601 epan_dissect_reset(&args->edt);
2603 return !ferror(args->fh);
2607 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2609 write_packet_callback_args_t callback_args;
2613 gboolean proto_tree_needed;
2615 fh = ws_fopen(print_args->file, "w");
2617 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2619 write_psml_preamble(&cf->cinfo, fh);
2622 return CF_PRINT_WRITE_ERROR;
2625 callback_args.fh = fh;
2626 callback_args.print_args = print_args;
2628 /* Fill in the column information, only create the protocol tree
2629 if having custom columns or field extractors. */
2630 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2631 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2633 /* Iterate through the list of packets, printing the packets we were
2635 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2636 "selected packets", TRUE,
2637 write_psml_packet, &callback_args, TRUE);
2639 epan_dissect_cleanup(&callback_args.edt);
2644 /* Completed successfully. */
2648 /* Well, the user decided to abort the printing. */
2652 /* Error while printing. */
2654 return CF_PRINT_WRITE_ERROR;
2657 write_psml_finale(fh);
2660 return CF_PRINT_WRITE_ERROR;
2663 /* XXX - check for an error */
2670 write_csv_packet(capture_file *cf, frame_data *fdata,
2671 struct wtap_pkthdr *phdr, const guint8 *pd,
2674 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2676 /* Fill in the column information */
2677 col_custom_prime_edt(&args->edt, &cf->cinfo);
2678 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2679 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2681 /* Write out the column information. */
2682 write_csv_columns(&args->edt, args->fh);
2684 epan_dissect_reset(&args->edt);
2686 return !ferror(args->fh);
2690 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2692 write_packet_callback_args_t callback_args;
2693 gboolean proto_tree_needed;
2697 fh = ws_fopen(print_args->file, "w");
2699 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2701 write_csv_column_titles(&cf->cinfo, fh);
2704 return CF_PRINT_WRITE_ERROR;
2707 callback_args.fh = fh;
2708 callback_args.print_args = print_args;
2710 /* only create the protocol tree if having custom columns or field extractors. */
2711 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2712 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2714 /* Iterate through the list of packets, printing the packets we were
2716 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2717 "selected packets", TRUE,
2718 write_csv_packet, &callback_args, TRUE);
2720 epan_dissect_cleanup(&callback_args.edt);
2725 /* Completed successfully. */
2729 /* Well, the user decided to abort the printing. */
2733 /* Error while printing. */
2735 return CF_PRINT_WRITE_ERROR;
2738 /* XXX - check for an error */
2745 carrays_write_packet(capture_file *cf, frame_data *fdata,
2746 struct wtap_pkthdr *phdr,
2747 const guint8 *pd, void *argsp)
2749 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2751 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2752 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2753 epan_dissect_reset(&args->edt);
2755 return !ferror(args->fh);
2759 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2761 write_packet_callback_args_t callback_args;
2765 fh = ws_fopen(print_args->file, "w");
2768 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2772 return CF_PRINT_WRITE_ERROR;
2775 callback_args.fh = fh;
2776 callback_args.print_args = print_args;
2777 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2779 /* Iterate through the list of packets, printing the packets we were
2781 ret = process_specified_records(cf, &print_args->range,
2783 "selected packets", TRUE,
2784 carrays_write_packet, &callback_args, TRUE);
2786 epan_dissect_cleanup(&callback_args.edt);
2790 /* Completed successfully. */
2793 /* Well, the user decided to abort the printing. */
2796 /* Error while printing. */
2798 return CF_PRINT_WRITE_ERROR;
2806 write_json_packet(capture_file *cf, frame_data *fdata,
2807 struct wtap_pkthdr *phdr, const guint8 *pd,
2810 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2812 /* Create the protocol tree, but don't fill in the column information. */
2813 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2815 /* Write out the information in that tree. */
2816 write_json_proto_tree(NULL, args->print_args, NULL, PF_NONE, &args->edt, args->fh);
2818 epan_dissect_reset(&args->edt);
2820 return !ferror(args->fh);
2824 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2826 write_packet_callback_args_t callback_args;
2830 fh = ws_fopen(print_args->file, "w");
2832 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2834 write_json_preamble(fh);
2837 return CF_PRINT_WRITE_ERROR;
2840 callback_args.fh = fh;
2841 callback_args.print_args = print_args;
2842 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2844 /* Iterate through the list of packets, printing the packets we were
2846 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2847 "selected packets", TRUE,
2848 write_json_packet, &callback_args, TRUE);
2850 epan_dissect_cleanup(&callback_args.edt);
2855 /* Completed successfully. */
2859 /* Well, the user decided to abort the printing. */
2863 /* Error while printing. */
2865 return CF_PRINT_WRITE_ERROR;
2868 write_json_finale(fh);
2871 return CF_PRINT_WRITE_ERROR;
2874 /* XXX - check for an error */
2881 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2882 search_direction dir)
2886 mdata.string = string;
2887 mdata.string_len = strlen(string);
2888 return find_packet(cf, match_protocol_tree, &mdata, dir);
2892 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2894 mdata->frame_matched = FALSE;
2895 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2896 mdata->string_len = strlen(mdata->string);
2898 /* Iterate through all the nodes looking for matching text */
2899 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2900 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2904 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2906 match_data *mdata = (match_data *)criterion;
2909 /* Load the frame's data. */
2910 if (!cf_read_record(cf, fdata)) {
2911 /* Attempt to get the packet failed. */
2915 /* Construct the protocol tree, including the displayed text */
2916 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2917 /* We don't need the column information */
2918 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
2920 /* Iterate through all the nodes, seeing if they have text that matches. */
2922 mdata->frame_matched = FALSE;
2923 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2924 epan_dissect_cleanup(&edt);
2925 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2929 match_subtree_text(proto_node *node, gpointer data)
2931 match_data *mdata = (match_data *) data;
2932 const gchar *string = mdata->string;
2933 size_t string_len = mdata->string_len;
2934 capture_file *cf = mdata->cf;
2935 field_info *fi = PNODE_FINFO(node);
2936 gchar label_str[ITEM_LABEL_LENGTH];
2943 /* dissection with an invisible proto tree? */
2946 if (mdata->frame_matched) {
2947 /* We already had a match; don't bother doing any more work. */
2951 /* Don't match invisible entries. */
2952 if (PROTO_ITEM_IS_HIDDEN(node))
2955 /* was a free format label produced? */
2957 label_ptr = fi->rep->representation;
2959 /* no, make a generic label */
2960 label_ptr = label_str;
2961 proto_item_fill_label(fi, label_str);
2965 if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
2966 mdata->frame_matched = TRUE;
2971 /* Does that label match? */
2972 label_len = strlen(label_ptr);
2973 for (i = 0; i < label_len; i++) {
2974 c_char = label_ptr[i];
2976 c_char = g_ascii_toupper(c_char);
2977 if (c_char == string[c_match]) {
2979 if (c_match == string_len) {
2980 /* No need to look further; we have a match */
2981 mdata->frame_matched = TRUE;
2990 /* Recurse into the subtree, if it exists */
2991 if (node->first_child != NULL)
2992 proto_tree_children_foreach(node, match_subtree_text, mdata);
2996 cf_find_packet_summary_line(capture_file *cf, const char *string,
2997 search_direction dir)
3001 mdata.string = string;
3002 mdata.string_len = strlen(string);
3003 return find_packet(cf, match_summary_line, &mdata, dir);
3007 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3009 match_data *mdata = (match_data *)criterion;
3010 const gchar *string = mdata->string;
3011 size_t string_len = mdata->string_len;
3013 const char *info_column;
3014 size_t info_column_len;
3015 match_result result = MR_NOTMATCHED;
3021 /* Load the frame's data. */
3022 if (!cf_read_record(cf, fdata)) {
3023 /* Attempt to get the packet failed. */
3027 /* Don't bother constructing the protocol tree */
3028 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3029 /* Get the column information */
3030 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
3033 /* Find the Info column */
3034 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3035 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3036 /* Found it. See if we match. */
3037 info_column = edt.pi.cinfo->columns[colx].col_data;
3038 info_column_len = strlen(info_column);
3040 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3041 result = MR_MATCHED;
3045 for (i = 0; i < info_column_len; i++) {
3046 c_char = info_column[i];
3048 c_char = g_ascii_toupper(c_char);
3049 if (c_char == string[c_match]) {
3051 if (c_match == string_len) {
3052 result = MR_MATCHED;
3062 epan_dissect_cleanup(&edt);
3069 } cbs_t; /* "Counted byte string" */
3073 * The current match_* routines only support ASCII case insensitivity and don't
3074 * convert UTF-8 inputs to UTF-16 for matching.
3076 * We could modify them to use the GLib Unicode routines or the International
3077 * Components for Unicode library but it's not apparent that we could do so
3078 * without consuming a lot more CPU and memory or that searching would be
3079 * significantly better.
3083 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3084 search_direction dir)
3089 info.data_len = string_size;
3091 /* Regex, String or hex search? */
3093 /* Regular Expression search */
3094 return find_packet(cf, match_regex, NULL, dir);
3095 } else if (cf->string) {
3096 /* String search - what type of string? */
3097 switch (cf->scs_type) {
3099 case SCS_NARROW_AND_WIDE:
3100 return find_packet(cf, match_narrow_and_wide, &info, dir);
3103 return find_packet(cf, match_narrow, &info, dir);
3106 return find_packet(cf, match_wide, &info, dir);
3109 g_assert_not_reached();
3113 return find_packet(cf, match_binary, &info, dir);
3117 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3119 cbs_t *info = (cbs_t *)criterion;
3120 const guint8 *ascii_text = info->data;
3121 size_t textlen = info->data_len;
3122 match_result result;
3129 /* Load the frame's data. */
3130 if (!cf_read_record(cf, fdata)) {
3131 /* Attempt to get the packet failed. */
3135 result = MR_NOTMATCHED;
3136 buf_len = fdata->cap_len;
3137 pd = ws_buffer_start_ptr(&cf->buf);
3139 while (i < buf_len) {
3142 c_char = g_ascii_toupper(c_char);
3143 if (c_char != '\0') {
3144 if (c_char == ascii_text[c_match]) {
3146 if (c_match == textlen) {
3147 result = MR_MATCHED;
3148 cf->search_pos = i; /* Save the position of the last character
3149 for highlighting the field. */
3150 cf->search_len = (guint32)textlen;
3155 g_assert(i>=c_match);
3156 i -= (guint32)c_match;
3166 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3169 cbs_t *info = (cbs_t *)criterion;
3170 const guint8 *ascii_text = info->data;
3171 size_t textlen = info->data_len;
3172 match_result result;
3178 /* Load the frame's data. */
3179 if (!cf_read_record(cf, fdata)) {
3180 /* Attempt to get the packet failed. */
3184 result = MR_NOTMATCHED;
3185 buf_len = fdata->cap_len;
3186 pd = ws_buffer_start_ptr(&cf->buf);
3188 while (i < buf_len) {
3191 c_char = g_ascii_toupper(c_char);
3192 if (c_char == ascii_text[c_match]) {
3194 if (c_match == textlen) {
3195 result = MR_MATCHED;
3196 cf->search_pos = i; /* Save the position of the last character
3197 for highlighting the field. */
3198 cf->search_len = (guint32)textlen;
3203 g_assert(i>=c_match);
3204 i -= (guint32)c_match;
3214 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3216 cbs_t *info = (cbs_t *)criterion;
3217 const guint8 *ascii_text = info->data;
3218 size_t textlen = info->data_len;
3219 match_result result;
3226 /* Load the frame's data. */
3227 if (!cf_read_record(cf, fdata)) {
3228 /* Attempt to get the packet failed. */
3232 result = MR_NOTMATCHED;
3233 buf_len = fdata->cap_len;
3234 pd = ws_buffer_start_ptr(&cf->buf);
3236 while (i < buf_len) {
3239 c_char = g_ascii_toupper(c_char);
3240 if (c_char == ascii_text[c_match]) {
3242 if (c_match == textlen) {
3243 result = MR_MATCHED;
3244 cf->search_pos = i; /* Save the position of the last character
3245 for highlighting the field. */
3246 cf->search_len = (guint32)textlen;
3252 g_assert(i>=(c_match*2));
3253 i -= (guint32)c_match*2;
3262 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3264 cbs_t *info = (cbs_t *)criterion;
3265 const guint8 *binary_data = info->data;
3266 size_t datalen = info->data_len;
3267 match_result result;
3273 /* Load the frame's data. */
3274 if (!cf_read_record(cf, fdata)) {
3275 /* Attempt to get the packet failed. */
3279 result = MR_NOTMATCHED;
3280 buf_len = fdata->cap_len;
3281 pd = ws_buffer_start_ptr(&cf->buf);
3283 while (i < buf_len) {
3284 if (pd[i] == binary_data[c_match]) {
3286 if (c_match == datalen) {
3287 result = MR_MATCHED;
3288 cf->search_pos = i; /* Save the position of the last character
3289 for highlighting the field. */
3290 cf->search_len = (guint32)datalen;
3295 g_assert(i>=c_match);
3296 i -= (guint32)c_match;
3305 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3307 match_result result = MR_NOTMATCHED;
3308 GMatchInfo *match_info = NULL;
3310 /* Load the frame's data. */
3311 if (!cf_read_record(cf, fdata)) {
3312 /* Attempt to get the packet failed. */
3316 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3317 0, (GRegexMatchFlags) 0, &match_info, NULL))
3319 gint start_pos = 0, end_pos = 0;
3320 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3321 cf->search_pos = end_pos - 1;
3322 cf->search_len = end_pos - start_pos;
3323 result = MR_MATCHED;
3329 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3330 search_direction dir)
3332 return find_packet(cf, match_dfilter, sfcode, dir);
3336 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3337 search_direction dir)
3342 if (!dfilter_compile(filter, &sfcode, NULL)) {
3344 * XXX - this shouldn't happen, as the filter string is machine
3349 if (sfcode == NULL) {
3351 * XXX - this shouldn't happen, as the filter string is machine
3356 result = find_packet(cf, match_dfilter, sfcode, dir);
3357 dfilter_free(sfcode);
3362 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3364 dfilter_t *sfcode = (dfilter_t *)criterion;
3366 match_result result;
3368 /* Load the frame's data. */
3369 if (!cf_read_record(cf, fdata)) {
3370 /* Attempt to get the packet failed. */
3374 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3375 epan_dissect_prime_dfilter(&edt, sfcode);
3376 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3377 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3378 epan_dissect_cleanup(&edt);
3383 cf_find_packet_marked(capture_file *cf, search_direction dir)
3385 return find_packet(cf, match_marked, NULL, dir);
3389 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3391 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3395 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3397 return find_packet(cf, match_time_reference, NULL, dir);
3401 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3403 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3407 find_packet(capture_file *cf,
3408 match_result (*match_function)(capture_file *, frame_data *, void *),
3409 void *criterion, search_direction dir)
3411 frame_data *start_fd;
3414 frame_data *new_fd = NULL;
3415 progdlg_t *progbar = NULL;
3416 GTimer *prog_timer = g_timer_new();
3420 GTimeVal start_time;
3421 gchar status_str[100];
3423 match_result result;
3425 start_fd = cf->current_frame;
3426 if (start_fd != NULL) {
3427 /* Iterate through the list of packets, starting at the packet we've
3428 picked, calling a routine to run the filter on the packet, see if
3429 it matches, and stop if so. */
3431 framenum = start_fd->num;
3433 g_timer_start(prog_timer);
3434 /* Progress so far. */
3437 cf->stop_flag = FALSE;
3438 g_get_current_time(&start_time);
3440 title = cf->sfilter?cf->sfilter:"";
3442 /* Create the progress bar if necessary.
3443 We check on every iteration of the loop, so that it takes no
3444 longer than the standard time to create it (otherwise, for a
3445 large file, we might take considerably longer than that standard
3446 time in order to get to the next progress bar step). */
3447 if (progbar == NULL)
3448 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3449 FALSE, &cf->stop_flag, &start_time, progbar_val);
3452 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3453 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3454 * likely trigger UI paint events, which might take a while depending on
3455 * the platform and display. Reset our timer *after* painting.
3457 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3458 /* let's not divide by zero. I should never be started
3459 * with count == 0, so let's assert that
3461 g_assert(cf->count > 0);
3463 progbar_val = (gfloat) count / cf->count;
3465 g_snprintf(status_str, sizeof(status_str),
3466 "%4u of %u packets", count, cf->count);
3467 update_progress_dlg(progbar, progbar_val, status_str);
3469 g_timer_start(prog_timer);
3472 if (cf->stop_flag) {
3473 /* Well, the user decided to abort the search. Go back to the
3474 frame where we started. */
3479 /* Go past the current frame. */
3480 if (dir == SD_BACKWARD) {
3481 /* Go on to the previous frame. */
3482 if (framenum == 1) {
3484 * XXX - other apps have a bit more of a detailed message
3485 * for this, and instead of offering "OK" and "Cancel",
3486 * they offer things such as "Continue" and "Cancel";
3487 * we need an API for popping up alert boxes with
3488 * {Verb} and "Cancel".
3491 if (prefs.gui_find_wrap)
3493 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3494 framenum = cf->count; /* wrap around */
3498 statusbar_push_temporary_msg("Search reached the beginning.");
3499 framenum = start_fd->num; /* stay on previous packet */
3504 /* Go on to the next frame. */
3505 if (framenum == cf->count) {
3506 if (prefs.gui_find_wrap)
3508 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3509 framenum = 1; /* wrap around */
3513 statusbar_push_temporary_msg("Search reached the end.");
3514 framenum = start_fd->num; /* stay on previous packet */
3519 fdata = frame_data_sequence_find(cf->frames, framenum);
3523 /* Is this packet in the display? */
3524 if (fdata->flags.passed_dfilter) {
3525 /* Yes. Does it match the search criterion? */
3526 result = (*match_function)(cf, fdata, criterion);
3527 if (result == MR_ERROR) {
3528 /* Error; our caller has reported the error. Go back to the frame
3529 where we started. */
3532 } else if (result == MR_MATCHED) {
3533 /* Yes. Go to the new frame. */
3539 if (fdata == start_fd) {
3540 /* We're back to the frame we were on originally, and that frame
3541 doesn't match the search filter. The search failed. */
3546 /* We're done scanning the packets; destroy the progress bar if it
3548 if (progbar != NULL)
3549 destroy_progress_dlg(progbar);
3550 g_timer_destroy(prog_timer);
3553 if (new_fd != NULL) {
3554 /* Find and select */
3555 cf->search_in_progress = TRUE;
3556 found = packet_list_select_row_from_data(new_fd);
3557 cf->search_in_progress = FALSE;
3558 cf->search_pos = 0; /* Reset the position */
3559 cf->search_len = 0; /* Reset length */
3561 /* We didn't find a row corresponding to this frame.
3562 This means that the frame isn't being displayed currently,
3563 so we can't select it. */
3564 simple_message_box(ESD_TYPE_INFO, NULL,
3565 "The capture file is probably not fully dissected.",
3566 "End of capture exceeded.");
3569 return TRUE; /* success */
3571 return FALSE; /* failure */
3575 cf_goto_frame(capture_file *cf, guint fnumber)
3579 if (cf == NULL || cf->frames == NULL) {
3580 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3581 statusbar_push_temporary_msg("There is no file loaded");
3582 return FALSE; /* we failed to go to that packet */
3585 fdata = frame_data_sequence_find(cf->frames, fnumber);
3587 if (fdata == NULL) {
3588 /* we didn't find a packet with that packet number */
3589 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3590 return FALSE; /* we failed to go to that packet */
3592 if (!fdata->flags.passed_dfilter) {
3593 /* that packet currently isn't displayed */
3594 /* XXX - add it to the set of displayed packets? */
3595 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3596 return FALSE; /* we failed to go to that packet */
3599 if (!packet_list_select_row_from_data(fdata)) {
3600 /* We didn't find a row corresponding to this frame.
3601 This means that the frame isn't being displayed currently,
3602 so we can't select it. */
3603 simple_message_box(ESD_TYPE_INFO, NULL,
3604 "The capture file is probably not fully dissected.",
3605 "End of capture exceeded.");
3608 return TRUE; /* we got to that packet */
3612 * Go to frame specified by currently selected protocol tree item.
3615 cf_goto_framenum(capture_file *cf)
3617 header_field_info *hfinfo;
3620 if (cf->finfo_selected) {
3621 hfinfo = cf->finfo_selected->hfinfo;
3623 if (hfinfo->type == FT_FRAMENUM) {
3624 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3626 return cf_goto_frame(cf, framenum);
3633 /* Select the packet on a given row. */
3635 cf_select_packet(capture_file *cf, int row)
3637 epan_dissect_t *old_edt;
3640 /* Get the frame data struct pointer for this frame */
3641 fdata = packet_list_get_row_data(row);
3643 if (fdata == NULL) {
3647 /* Get the data in that frame. */
3648 if (!cf_read_record (cf, fdata)) {
3652 /* Record that this frame is the current frame. */
3653 cf->current_frame = fdata;
3654 cf->current_row = row;
3657 /* Create the logical protocol tree. */
3658 /* We don't need the columns here. */
3659 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3661 tap_build_interesting(cf->edt);
3662 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3663 cf->current_frame, NULL);
3665 dfilter_macro_build_ftv_cache(cf->edt->tree);
3667 cf_callback_invoke(cf_cb_packet_selected, cf);
3669 if (old_edt != NULL)
3670 epan_dissect_free(old_edt);
3674 /* Unselect the selected packet, if any. */
3676 cf_unselect_packet(capture_file *cf)
3678 epan_dissect_t *old_edt = cf->edt;
3682 /* No packet is selected. */
3683 cf->current_frame = NULL;
3684 cf->current_row = 0;
3686 cf_callback_invoke(cf_cb_packet_unselected, cf);
3688 /* No protocol tree means no selected field. */
3689 cf_unselect_field(cf);
3691 /* Destroy the epan_dissect_t for the unselected packet. */
3692 if (old_edt != NULL)
3693 epan_dissect_free(old_edt);
3696 /* Unset the selected protocol tree field, if any. */
3698 cf_unselect_field(capture_file *cf)
3700 cf->finfo_selected = NULL;
3702 cf_callback_invoke(cf_cb_field_unselected, cf);
3706 * Mark a particular frame.
3709 cf_mark_frame(capture_file *cf, frame_data *frame)
3711 if (! frame->flags.marked) {
3712 frame->flags.marked = TRUE;
3713 if (cf->count > cf->marked_count)
3719 * Unmark a particular frame.
3722 cf_unmark_frame(capture_file *cf, frame_data *frame)
3724 if (frame->flags.marked) {
3725 frame->flags.marked = FALSE;
3726 if (cf->marked_count > 0)
3732 * Ignore a particular frame.
3735 cf_ignore_frame(capture_file *cf, frame_data *frame)
3737 if (! frame->flags.ignored) {
3738 frame->flags.ignored = TRUE;
3739 if (cf->count > cf->ignored_count)
3740 cf->ignored_count++;
3745 * Un-ignore a particular frame.
3748 cf_unignore_frame(capture_file *cf, frame_data *frame)
3750 if (frame->flags.ignored) {
3751 frame->flags.ignored = FALSE;
3752 if (cf->ignored_count > 0)
3753 cf->ignored_count--;
3758 * Read the comment in SHB block
3762 cf_read_shb_comment(capture_file *cf)
3764 wtap_block_t shb_inf;
3768 /* XXX - support multiple SHBs */
3769 shb_inf = wtap_file_get_shb(cf->wth);
3771 /* Get the first comment from the SHB. */
3772 /* XXX - support multiple comments */
3773 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3779 cf_update_capture_comment(capture_file *cf, gchar *comment)
3781 wtap_block_t shb_inf;
3785 /* XXX - support multiple SHBs */
3786 shb_inf = wtap_file_get_shb(cf->wth);
3788 /* Get the first comment from the SHB. */
3789 /* XXX - support multiple comments */
3790 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3791 /* There's no comment - add one. */
3792 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3794 /* See if the comment has changed or not */
3795 if (strcmp(shb_comment, comment) == 0) {
3800 /* The comment has changed, let's update it */
3801 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3803 /* Mark the file as having unsaved changes */
3804 cf->unsaved_changes = TRUE;
3808 cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
3810 if (cf->frames_user_comments)
3811 return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
3818 cf_get_comment(capture_file *cf, const frame_data *fd)
3822 /* fetch user comment */
3823 if (fd->flags.has_user_comment)
3824 return g_strdup(cf_get_user_packet_comment(cf, fd));
3826 /* fetch phdr comment */
3827 if (fd->flags.has_phdr_comment) {
3828 struct wtap_pkthdr phdr; /* Packet header */
3829 Buffer buf; /* Packet data */
3831 wtap_phdr_init(&phdr);
3832 ws_buffer_init(&buf, 1500);
3834 if (!cf_read_record_r(cf, fd, &phdr, &buf))
3835 { /* XXX, what we can do here? */ }
3837 comment = phdr.opt_comment;
3838 wtap_phdr_cleanup(&phdr);
3839 ws_buffer_free(&buf);
3846 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3848 const frame_data *fdata1 = (const frame_data *) a;
3849 const frame_data *fdata2 = (const frame_data *) b;
3851 return (fdata1->num < fdata2->num) ? -1 :
3852 (fdata1->num > fdata2->num) ? 1 :
3857 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3859 char *pkt_comment = cf_get_comment(cf, fd);
3861 /* Check if the comment has changed */
3862 if (!g_strcmp0(pkt_comment, new_comment)) {
3863 g_free(pkt_comment);
3866 g_free(pkt_comment);
3869 cf->packet_comment_count--;
3872 cf->packet_comment_count++;
3874 fd->flags.has_user_comment = TRUE;
3876 if (!cf->frames_user_comments)
3877 cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
3879 /* insert new packet comment */
3880 g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
3882 expert_update_comment_count(cf->packet_comment_count);
3884 /* OK, we have unsaved changes. */
3885 cf->unsaved_changes = TRUE;
3890 * What types of comments does this capture file have?
3893 cf_comment_types(capture_file *cf)
3895 guint32 comment_types = 0;
3897 if (cf_read_shb_comment(cf) != NULL)
3898 comment_types |= WTAP_COMMENT_PER_SECTION;
3899 if (cf->packet_comment_count != 0)
3900 comment_types |= WTAP_COMMENT_PER_PACKET;
3901 return comment_types;
3905 * Add a resolved address to this file's list of resolved addresses.
3908 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
3911 * XXX - support multiple resolved address lists, and add to the one
3912 * attached to this file?
3914 if (!add_ip_name_from_string(addr, name))
3917 /* OK, we have unsaved changes. */
3918 cf->unsaved_changes = TRUE;
3922 #ifdef WANT_PACKET_EDITOR
3924 g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3935 modified_frame_data_free(gpointer data)
3937 modified_frame_data *mfd = (modified_frame_data *)data;
3944 * Give a frame new, edited data.
3947 cf_set_frame_edited(capture_file *cf, frame_data *fd,
3948 struct wtap_pkthdr *phdr, guint8 *pd)
3950 modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data));
3953 mfd->pd = (char *)pd;
3955 if (cf->edited_frames == NULL)
3956 cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL,
3957 modified_frame_data_free);
3958 g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd);
3961 /* Mark the file as having unsaved changes */
3962 cf->unsaved_changes = TRUE;
3970 } save_callback_args_t;
3973 * Save a capture to a file, in a particular format, saving either
3974 * all packets, all currently-displayed packets, or all marked packets.
3976 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3977 * up a message box for the failure.
3980 save_record(capture_file *cf, frame_data *fdata,
3981 struct wtap_pkthdr *phdr, const guint8 *pd,
3984 save_callback_args_t *args = (save_callback_args_t *)argsp;
3985 struct wtap_pkthdr hdr;
3988 gchar *display_basename;
3989 const char *pkt_comment;
3991 if (fdata->flags.has_user_comment)
3992 pkt_comment = cf_get_user_packet_comment(cf, fdata);
3994 pkt_comment = phdr->opt_comment;
3996 /* init the wtap header for saving */
3997 /* TODO: reuse phdr */
3998 /* XXX - these are the only flags that correspond to data that we have
3999 in the frame_data structure and that matter on a per-packet basis.
4001 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
4002 and "on the wire" lengths, or it doesn't.
4004 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
4007 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
4008 from the packet flags. */
4009 hdr.rec_type = phdr->rec_type;
4010 hdr.presence_flags = 0;
4011 if (fdata->flags.has_ts)
4012 hdr.presence_flags |= WTAP_HAS_TS;
4013 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
4014 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
4015 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
4016 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
4018 hdr.caplen = phdr->caplen;
4019 hdr.len = phdr->len;
4020 hdr.pkt_encap = phdr->pkt_encap;
4022 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
4024 hdr.pack_flags = phdr->pack_flags;
4025 hdr.opt_comment = g_strdup(pkt_comment);
4028 hdr.pseudo_header = phdr->pseudo_header;
4031 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
4033 /* and save the packet */
4034 if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
4036 /* Wiretap error. */
4039 case WTAP_ERR_UNWRITABLE_ENCAP:
4041 * This is a problem with the particular frame we're writing and
4042 * the file type and subtype we're writing; note that, and report
4043 * the frame number and file type/subtype.
4045 simple_error_message_box(
4046 "Frame %u has a network type that can't be saved in a \"%s\" file.",
4047 fdata->num, wtap_file_type_subtype_string(args->file_type));
4050 case WTAP_ERR_PACKET_TOO_LARGE:
4052 * This is a problem with the particular frame we're writing and
4053 * the file type and subtype we're writing; note that, and report
4054 * the frame number and file type/subtype.
4056 simple_error_message_box(
4057 "Frame %u is larger than Wireshark supports in a \"%s\" file.",
4058 fdata->num, wtap_file_type_subtype_string(args->file_type));
4061 case WTAP_ERR_UNWRITABLE_REC_TYPE:
4063 * This is a problem with the particular record we're writing and
4064 * the file type and subtype we're writing; note that, and report
4065 * the record number and file type/subtype.
4067 simple_error_message_box(
4068 "Record %u has a record type that can't be saved in a \"%s\" file.",
4069 fdata->num, wtap_file_type_subtype_string(args->file_type));
4072 case WTAP_ERR_UNWRITABLE_REC_DATA:
4074 * This is a problem with the particular frame we're writing and
4075 * the file type and subtype we're writing; note that, and report
4076 * the frame number and file type/subtype.
4078 simple_error_message_box(
4079 "Record %u has data that can't be saved in a \"%s\" file.\n(%s)",
4080 fdata->num, wtap_file_type_subtype_string(args->file_type),
4081 err_info != NULL ? err_info : "no information supplied");
4086 display_basename = g_filename_display_basename(args->fname);
4087 simple_error_message_box(
4088 "An error occurred while writing to the file \"%s\": %s.",
4089 display_basename, wtap_strerror(err));
4090 g_free(display_basename);
4095 write_failure_alert_box(args->fname, err);
4100 g_free(hdr.opt_comment);
4105 * Can this capture file be written out in any format using Wiretap
4106 * rather than by copying the raw data?
4109 cf_can_write_with_wiretap(capture_file *cf)
4111 /* We don't care whether we support the comments in this file or not;
4112 if we can't, we'll offer the user the option of discarding the
4114 return wtap_dump_can_write(cf->linktypes, 0);
4118 * Should we let the user do a save?
4122 * the file has unsaved changes, and we can save it in some
4123 * format through Wiretap
4127 * the file is a temporary file and has no unsaved changes (so
4128 * that "saving" it just means copying it).
4130 * XXX - we shouldn't allow files to be edited if they can't be saved,
4131 * so cf->unsaved_changes should be true only if the file can be saved.
4133 * We don't care whether we support the comments in this file or not;
4134 * if we can't, we'll offer the user the option of discarding the
4138 cf_can_save(capture_file *cf)
4140 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4141 /* Saved changes, and we can write it out with Wiretap. */
4145 if (cf->is_tempfile && !cf->unsaved_changes) {
4147 * Temporary file with no unsaved changes, so we can just do a
4153 /* Nothing to save. */
4158 * Should we let the user do a "save as"?
4162 * we can save it in some format through Wiretap
4166 * the file is a temporary file and has no unsaved changes (so
4167 * that "saving" it just means copying it).
4169 * XXX - we shouldn't allow files to be edited if they can't be saved,
4170 * so cf->unsaved_changes should be true only if the file can be saved.
4172 * We don't care whether we support the comments in this file or not;
4173 * if we can't, we'll offer the user the option of discarding the
4177 cf_can_save_as(capture_file *cf)
4179 if (wtap_dump_can_write(cf->linktypes, 0)) {
4180 /* We can write it out with Wiretap. */
4184 if (cf->is_tempfile && !cf->unsaved_changes) {
4186 * Temporary file with no unsaved changes, so we can just do a
4192 /* Nothing to save. */
4197 * Does this file have unsaved data?
4200 cf_has_unsaved_data(capture_file *cf)
4203 * If this is a temporary file, or a file with unsaved changes, it
4206 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4210 * Quick scan to find packet offsets.
4212 static cf_read_status_t
4213 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
4215 const struct wtap_pkthdr *phdr;
4219 progdlg_t *progbar = NULL;
4220 GTimer *prog_timer = g_timer_new();
4223 GTimeVal start_time;
4224 gchar status_str[100];
4229 /* Close the old handle. */
4230 wtap_close(cf->wth);
4232 /* Open the new file. */
4233 /* XXX: this will go through all open_routines for a matching one. But right
4234 now rescan_file() is only used when a file is being saved to a different
4235 format than the original, and the user is not given a choice of which
4236 reader to use (only which format to save it in), so doing this makes
4238 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, err, &err_info, TRUE);
4239 if (cf->wth == NULL) {
4240 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
4241 return CF_READ_ERROR;
4244 /* We're scanning a file whose contents should be the same as what
4245 we had before, so we don't discard dissection state etc.. */
4248 /* Set the file name because we need it to set the follow stream filter.
4249 XXX - is that still true? We need it for other reasons, though,
4251 cf->filename = g_strdup(fname);
4253 /* Indicate whether it's a permanent or temporary file. */
4254 cf->is_tempfile = is_tempfile;
4256 /* No user changes yet. */
4257 cf->unsaved_changes = FALSE;
4259 cf->cd_t = wtap_file_type_subtype(cf->wth);
4260 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4262 cf->snap = wtap_snapshot_length(cf->wth);
4263 if (cf->snap == 0) {
4264 /* Snapshot length not known. */
4265 cf->has_snap = FALSE;
4266 cf->snap = WTAP_MAX_PACKET_SIZE;
4268 cf->has_snap = TRUE;
4270 name_ptr = g_filename_display_basename(cf->filename);
4272 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4274 /* Record whether the file is compressed.
4275 XXX - do we know this at open time? */
4276 cf->iscompressed = wtap_iscompressed(cf->wth);
4278 /* Find the size of the file. */
4279 size = wtap_file_size(cf->wth, NULL);
4281 g_timer_start(prog_timer);
4283 cf->stop_flag = FALSE;
4284 g_get_current_time(&start_time);
4287 phdr = wtap_phdr(cf->wth);
4288 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
4290 fdata = frame_data_sequence_find(cf->frames, framenum);
4291 fdata->file_off = data_offset;
4294 cf->f_datalen = wtap_read_so_far(cf->wth);
4296 /* Create the progress bar if necessary. */
4297 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4298 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4299 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4300 TRUE, &cf->stop_flag, &start_time, progbar_val);
4304 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4305 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4306 * likely trigger UI paint events, which might take a while depending on
4307 * the platform and display. Reset our timer *after* painting.
4309 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4310 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4311 /* update the packet bar content on the first run or frequently on very large files */
4312 update_progress_dlg(progbar, progbar_val, status_str);
4313 packets_bar_update();
4314 g_timer_start(prog_timer);
4318 if (cf->stop_flag) {
4319 /* Well, the user decided to abort the rescan. Sadly, as this
4320 isn't a reread, recovering is difficult, so we'll just
4321 close the current capture. */
4325 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4326 it's not already there.
4327 XXX - yes, this is O(N), so if every packet had a different
4328 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4329 there are probably going to be a small number of encapsulation types
4331 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4334 /* Free the display name */
4337 /* We're done reading the file; destroy the progress bar if it was created. */
4338 if (progbar != NULL)
4339 destroy_progress_dlg(progbar);
4340 g_timer_destroy(prog_timer);
4342 /* We're done reading sequentially through the file. */
4343 cf->state = FILE_READ_DONE;
4345 /* Close the sequential I/O side, to free up memory it requires. */
4346 wtap_sequential_close(cf->wth);
4348 /* compute the time it took to load the file */
4349 compute_elapsed(cf, &start_time);
4351 /* Set the file encapsulation type now; we don't know what it is until
4352 we've looked at all the packets, as we don't know until then whether
4353 there's more than one type (and thus whether it's
4354 WTAP_ENCAP_PER_PACKET). */
4355 cf->lnk_t = wtap_file_encap(cf->wth);
4357 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4359 if (cf->stop_flag) {
4360 /* Our caller will give up at this point. */
4361 return CF_READ_ABORTED;
4365 /* Put up a message box noting that the read failed somewhere along
4366 the line. Don't throw out the stuff we managed to read, though,
4370 case WTAP_ERR_UNSUPPORTED:
4371 simple_error_message_box(
4372 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
4373 err_info != NULL ? err_info : "no information supplied");
4377 case WTAP_ERR_SHORT_READ:
4378 simple_error_message_box(
4379 "The capture file appears to have been cut short"
4380 " in the middle of a packet.");
4383 case WTAP_ERR_BAD_FILE:
4384 simple_error_message_box(
4385 "The capture file appears to be damaged or corrupt.\n(%s)",
4386 err_info != NULL ? err_info : "no information supplied");
4390 case WTAP_ERR_DECOMPRESS:
4391 simple_error_message_box(
4392 "The compressed capture file appears to be damaged or corrupt.\n"
4394 err_info != NULL ? err_info : "no information supplied");
4399 simple_error_message_box(
4400 "An error occurred while reading the"
4401 " capture file: %s.", wtap_strerror(*err));
4404 return CF_READ_ERROR;
4410 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4411 gboolean compressed, gboolean discard_comments,
4412 gboolean dont_reopen)
4415 gchar *fname_new = NULL;
4418 addrinfo_lists_t *addr_lists;
4422 gchar *display_basename;
4429 save_callback_args_t callback_args;
4431 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4433 addr_lists = get_addrinfo_list();
4435 if (save_format == cf->cd_t && compressed == cf->iscompressed
4436 && !discard_comments && !cf->unsaved_changes
4437 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4438 /* We're saving in the format it's already in, and we're
4439 not discarding comments, and there are no changes we have
4440 in memory that aren't saved to the file, and we have no name
4441 resolution blocks to write, so we can just move or copy the raw data. */
4443 if (cf->is_tempfile) {
4444 /* The file being saved is a temporary file from a live
4445 capture, so it doesn't need to stay around under that name;
4446 first, try renaming the capture buffer file to the new name.
4447 This acts as a "safe save", in that, if the file already
4448 exists, the existing file will be removed only if the rename
4451 Sadly, on Windows, as we have the current capture file
4452 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4453 (to cause the rename to remove an existing target), as
4454 done by ws_stdio_rename() (ws_rename() is #defined to
4455 be ws_stdio_rename() on Windows) will fail.
4457 According to the MSDN documentation for CreateFile(), if,
4458 when we open a capture file, we were to directly do a CreateFile(),
4459 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4460 convert it to a file descriptor with _open_osfhandle(),
4461 that would allow the file to be renamed out from under us.
4463 However, that doesn't work in practice. Perhaps the problem
4464 is that the process doing the rename is the process that
4465 has the file open. */
4467 if (ws_rename(cf->filename, fname) == 0) {
4468 /* That succeeded - there's no need to copy the source file. */
4469 how_to_save = SAVE_WITH_MOVE;
4471 if (errno == EXDEV) {
4472 /* They're on different file systems, so we have to copy the
4474 how_to_save = SAVE_WITH_COPY;
4476 /* The rename failed, but not because they're on different
4477 file systems - put up an error message. (Or should we
4478 just punt and try to copy? The only reason why I'd
4479 expect the rename to fail and the copy to succeed would
4480 be if we didn't have permission to remove the file from
4481 the temporary directory, and that might be fixable - but
4482 is it worth requiring the user to go off and fix it?) */
4483 cf_rename_failure_alert_box(fname, errno);
4488 how_to_save = SAVE_WITH_COPY;
4491 /* It's a permanent file, so we should copy it, and not remove the
4493 how_to_save = SAVE_WITH_COPY;
4496 if (how_to_save == SAVE_WITH_COPY) {
4497 /* Copy the file, if we haven't moved it. If we're overwriting
4498 an existing file, we do it with a "safe save", by writing
4499 to a new file and, if the write succeeds, renaming the
4500 new file on top of the old file. */
4501 if (file_exists(fname)) {
4502 fname_new = g_strdup_printf("%s~", fname);
4503 if (!copy_file_binary_mode(cf->filename, fname_new))
4506 if (!copy_file_binary_mode(cf->filename, fname))
4511 /* Either we're saving in a different format or we're saving changes,
4512 such as added, modified, or removed comments, that haven't yet
4513 been written to the underlying file; we can't do that by copying
4514 or moving the capture file, we have to do it by writing the packets
4517 GArray *shb_hdrs = NULL;
4518 wtapng_iface_descriptions_t *idb_inf = NULL;
4519 GArray *nrb_hdrs = NULL;
4522 /* XXX: what free's this shb_hdr? */
4523 shb_hdrs = wtap_file_get_shb_for_new_file(cf->wth);
4524 idb_inf = wtap_file_get_idb_info(cf->wth);
4525 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
4527 /* Determine what file encapsulation type we should use. */
4528 encap = wtap_dump_file_encap_type(cf->linktypes);
4530 if (file_exists(fname)) {
4531 /* We're overwriting an existing file; write out to a new file,
4532 and, if that succeeds, rename the new file on top of the
4533 old file. That makes this a "safe save", so that we don't
4534 lose the old file if we have a problem writing out the new
4535 file. (If the existing file is the current capture file,
4536 we *HAVE* to do that, otherwise we're overwriting the file
4537 from which we're reading the packets that we're writing!) */
4538 fname_new = g_strdup_printf("%s~", fname);
4539 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4540 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4542 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4543 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4549 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4553 /* Add address resolution */
4554 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4556 /* Iterate through the list of packets, processing all the packets. */
4557 callback_args.pdh = pdh;
4558 callback_args.fname = fname;
4559 callback_args.file_type = save_format;
4560 switch (process_specified_records(cf, NULL, "Saving", "packets",
4561 TRUE, save_record, &callback_args, TRUE)) {
4564 /* Completed successfully. */
4568 /* The user decided to abort the saving.
4569 If we're writing to a temporary file, remove it.
4570 XXX - should we do so even if we're not writing to a
4572 wtap_dump_close(pdh, &err);
4573 if (fname_new != NULL)
4574 ws_unlink(fname_new);
4575 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4576 return CF_WRITE_ABORTED;
4579 /* Error while saving.
4580 If we're writing to a temporary file, remove it. */
4581 if (fname_new != NULL)
4582 ws_unlink(fname_new);
4583 wtap_dump_close(pdh, &err);
4587 if (!wtap_dump_close(pdh, &err)) {
4588 cf_close_failure_alert_box(fname, err);
4592 how_to_save = SAVE_WITH_WTAP;
4595 if (fname_new != NULL) {
4596 /* We wrote out to fname_new, and should rename it on top of
4597 fname. fname_new is now closed, so that should be possible even
4598 on Windows. However, on Windows, we first need to close whatever
4599 file descriptors we have open for fname. */
4601 wtap_fdclose(cf->wth);
4603 /* Now do the rename. */
4604 if (ws_rename(fname_new, fname) == -1) {
4605 /* Well, the rename failed. */
4606 cf_rename_failure_alert_box(fname, errno);
4608 /* Attempt to reopen the random file descriptor using the
4609 current file's filename. (At this point, the sequential
4610 file descriptor is closed.) */
4611 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4612 /* Oh, well, we're screwed. */
4613 display_basename = g_filename_display_basename(cf->filename);
4614 simple_error_message_box(
4615 file_open_error_message(err, FALSE), display_basename);
4616 g_free(display_basename);
4623 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4624 cf->unsaved_changes = FALSE;
4627 switch (how_to_save) {
4629 case SAVE_WITH_MOVE:
4630 /* We just moved the file, so the wtap structure refers to the
4631 new file, and all the information other than the filename
4632 and the "is temporary" status applies to the new file; just
4634 g_free(cf->filename);
4635 cf->filename = g_strdup(fname);
4636 cf->is_tempfile = FALSE;
4637 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4640 case SAVE_WITH_COPY:
4641 /* We just copied the file, s all the information other than
4642 the wtap structure, the filename, and the "is temporary"
4643 status applies to the new file; just update that. */
4644 wtap_close(cf->wth);
4645 /* Although we're just "copying" and then opening the copy, it will
4646 try all open_routine readers to open the copy, so we need to
4647 reset the cfile's open_type. */
4648 cf->open_type = WTAP_TYPE_AUTO;
4649 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4650 if (cf->wth == NULL) {
4651 cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
4654 g_free(cf->filename);
4655 cf->filename = g_strdup(fname);
4656 cf->is_tempfile = FALSE;
4658 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4661 case SAVE_WITH_WTAP:
4662 /* Open and read the file we saved to.
4664 XXX - this is somewhat of a waste; we already have the
4665 packets, all this gets us is updated file type information
4666 (which we could just stuff into "cf"), and having the new
4667 file be the one we have opened and from which we're reading
4668 the data, and it means we have to spend time opening and
4669 reading the file, which could be a significant amount of
4670 time if the file is large.
4672 If the capture-file-writing code were to return the
4673 seek offset of each packet it writes, we could save that
4674 in the frame_data structure for the frame, and just open
4675 the file without reading it again...
4677 ...as long as, for gzipped files, the process of writing
4678 out the file *also* generates the information needed to
4679 support fast random access to the compressed file. */
4680 /* rescan_file will cause us to try all open_routines, so
4681 reset cfile's open_type */
4682 cf->open_type = WTAP_TYPE_AUTO;
4683 if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) {
4684 /* The rescan failed; just close the file. Either
4685 a dialog was popped up for the failure, so the
4686 user knows what happened, or they stopped the
4687 rescan, in which case they know what happened. */
4693 /* If we were told to discard the comments, do so. */
4694 if (discard_comments) {
4695 /* Remove SHB comment, if any. */
4696 wtap_write_shb_comment(cf->wth, NULL);
4698 /* remove all user comments */
4699 for (framenum = 1; framenum <= cf->count; framenum++) {
4700 fdata = frame_data_sequence_find(cf->frames, framenum);
4702 fdata->flags.has_phdr_comment = FALSE;
4703 fdata->flags.has_user_comment = FALSE;
4706 if (cf->frames_user_comments) {
4707 g_tree_destroy(cf->frames_user_comments);
4708 cf->frames_user_comments = NULL;
4711 cf->packet_comment_count = 0;
4717 if (fname_new != NULL) {
4718 /* We were trying to write to a temporary file; get rid of it if it
4719 exists. (We don't care whether this fails, as, if it fails,
4720 there's not much we can do about it. I guess if it failed for
4721 a reason other than "it doesn't exist", we could report an
4722 error, so the user knows there's a junk file that they might
4723 want to clean up.) */
4724 ws_unlink(fname_new);
4727 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4728 return CF_WRITE_ERROR;
4732 cf_export_specified_packets(capture_file *cf, const char *fname,
4733 packet_range_t *range, guint save_format,
4734 gboolean compressed)
4736 gchar *fname_new = NULL;
4739 save_callback_args_t callback_args;
4740 GArray *shb_hdrs = NULL;
4741 wtapng_iface_descriptions_t *idb_inf = NULL;
4742 GArray *nrb_hdrs = NULL;
4745 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4747 packet_range_process_init(range);
4749 /* We're writing out specified packets from the specified capture
4750 file to another file. Even if all captured packets are to be
4751 written, don't special-case the operation - read each packet
4752 and then write it out if it's one of the specified ones. */
4754 /* XXX: what free's this shb_hdr? */
4755 shb_hdrs = wtap_file_get_shb_for_new_file(cf->wth);
4756 idb_inf = wtap_file_get_idb_info(cf->wth);
4757 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
4759 /* Determine what file encapsulation type we should use. */
4760 encap = wtap_dump_file_encap_type(cf->linktypes);
4762 if (file_exists(fname)) {
4763 /* We're overwriting an existing file; write out to a new file,
4764 and, if that succeeds, rename the new file on top of the
4765 old file. That makes this a "safe save", so that we don't
4766 lose the old file if we have a problem writing out the new
4767 file. (If the existing file is the current capture file,
4768 we *HAVE* to do that, otherwise we're overwriting the file
4769 from which we're reading the packets that we're writing!) */
4770 fname_new = g_strdup_printf("%s~", fname);
4771 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4772 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4774 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4775 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4781 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4785 /* Add address resolution */
4786 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4788 /* Iterate through the list of packets, processing the packets we were
4791 XXX - we've already called "packet_range_process_init(range)", but
4792 "process_specified_records()" will do it again. Fortunately,
4793 that's harmless in this case, as we haven't done anything to
4794 "range" since we initialized it. */
4795 callback_args.pdh = pdh;
4796 callback_args.fname = fname;
4797 callback_args.file_type = save_format;
4798 switch (process_specified_records(cf, range, "Writing", "specified records",
4799 TRUE, save_record, &callback_args, TRUE)) {
4802 /* Completed successfully. */
4806 /* The user decided to abort the saving.
4807 If we're writing to a temporary file, remove it.
4808 XXX - should we do so even if we're not writing to a
4810 wtap_dump_close(pdh, &err);
4811 if (fname_new != NULL)
4812 ws_unlink(fname_new);
4813 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4814 return CF_WRITE_ABORTED;
4818 /* Error while saving.
4819 If we're writing to a temporary file, remove it. */
4820 if (fname_new != NULL)
4821 ws_unlink(fname_new);
4822 wtap_dump_close(pdh, &err);
4826 if (!wtap_dump_close(pdh, &err)) {
4827 cf_close_failure_alert_box(fname, err);
4831 if (fname_new != NULL) {
4832 /* We wrote out to fname_new, and should rename it on top of
4833 fname; fname is now closed, so that should be possible even
4834 on Windows. Do the rename. */
4835 if (ws_rename(fname_new, fname) == -1) {
4836 /* Well, the rename failed. */
4837 cf_rename_failure_alert_box(fname, errno);
4842 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4846 if (fname_new != NULL) {
4847 /* We were trying to write to a temporary file; get rid of it if it
4848 exists. (We don't care whether this fails, as, if it fails,
4849 there's not much we can do about it. I guess if it failed for
4850 a reason other than "it doesn't exist", we could report an
4851 error, so the user knows there's a junk file that they might
4852 want to clean up.) */
4853 ws_unlink(fname_new);
4856 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4857 return CF_WRITE_ERROR;
4861 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
4862 gboolean for_writing, int file_type)
4864 gchar *display_basename;
4867 /* Wiretap error. */
4868 display_basename = g_filename_display_basename(filename);
4871 case WTAP_ERR_NOT_REGULAR_FILE:
4872 simple_error_message_box(
4873 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4877 case WTAP_ERR_RANDOM_OPEN_PIPE:
4878 /* Seen only when opening a capture file for reading. */
4879 simple_error_message_box(
4880 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.\n"
4881 "To capture from a pipe or FIFO use wireshark -i -",
4885 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
4886 /* Seen only when opening a capture file for reading. */
4887 simple_error_message_box(
4888 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
4892 case WTAP_ERR_UNSUPPORTED:
4893 /* Seen only when opening a capture file for reading. */
4894 simple_error_message_box(
4895 "The file \"%s\" contains record data that Wireshark doesn't support.\n"
4898 err_info != NULL ? err_info : "no information supplied");
4902 case WTAP_ERR_CANT_WRITE_TO_PIPE:
4903 /* Seen only when opening a capture file for writing. */
4904 simple_error_message_box(
4905 "The file \"%s\" is a pipe, and %s capture files can't be "
4906 "written to a pipe.",
4907 display_basename, wtap_file_type_subtype_string(file_type));
4910 case WTAP_ERR_UNWRITABLE_FILE_TYPE:
4911 /* Seen only when opening a capture file for writing. */
4912 simple_error_message_box(
4913 "Wireshark doesn't support writing capture files in that format.");
4916 case WTAP_ERR_UNWRITABLE_ENCAP:
4917 /* Seen only when opening a capture file for writing. */
4918 simple_error_message_box("Wireshark can't save this capture in that format.");
4921 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
4923 simple_error_message_box(
4924 "Wireshark can't save this capture in that format.");
4926 simple_error_message_box(
4927 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
4932 case WTAP_ERR_BAD_FILE:
4933 /* Seen only when opening a capture file for reading. */
4934 simple_error_message_box(
4935 "The file \"%s\" appears to be damaged or corrupt.\n"
4938 err_info != NULL ? err_info : "no information supplied");
4942 case WTAP_ERR_CANT_OPEN:
4944 simple_error_message_box(
4945 "The file \"%s\" could not be created for some unknown reason.",
4948 simple_error_message_box(
4949 "The file \"%s\" could not be opened for some unknown reason.",
4954 case WTAP_ERR_SHORT_READ:
4955 simple_error_message_box(
4956 "The file \"%s\" appears to have been cut short"
4957 " in the middle of a packet or other data.",
4961 case WTAP_ERR_SHORT_WRITE:
4962 simple_error_message_box(
4963 "A full header couldn't be written to the file \"%s\".",
4967 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4968 simple_error_message_box(
4969 "This file type cannot be written as a compressed file.");
4972 case WTAP_ERR_DECOMPRESS:
4973 simple_error_message_box(
4974 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
4975 "(%s)", display_basename,
4976 err_info != NULL ? err_info : "no information supplied");
4981 simple_error_message_box(
4982 "The file \"%s\" could not be %s: %s.",
4984 for_writing ? "created" : "opened",
4985 wtap_strerror(err));
4988 g_free(display_basename);
4991 open_failure_alert_box(filename, err, for_writing);
4996 * XXX - whether we mention the source pathname, the target pathname,
4997 * or both depends on the error and on what we find if we look for
4998 * one or both of them.
5001 cf_rename_failure_alert_box(const char *filename, int err)
5003 gchar *display_basename;
5005 display_basename = g_filename_display_basename(filename);
5009 /* XXX - should check whether the source exists and, if not,
5010 report it as the problem and, if so, report the destination
5012 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
5017 /* XXX - if we're doing a rename after a safe save, we should
5018 probably say something else. */
5019 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
5024 /* XXX - this should probably mention both the source and destination
5026 simple_error_message_box("The file \"%s\" could not be moved: %s.",
5027 display_basename, wtap_strerror(err));
5030 g_free(display_basename);
5033 /* Check for write errors - if the file is being written to an NFS server,
5034 a write error may not show up until the file is closed, as NFS clients
5035 might not send writes to the server until the "write()" call finishes,
5036 so that the write may fail on the server but the "write()" may succeed. */
5038 cf_close_failure_alert_box(const char *filename, int err)
5040 gchar *display_basename;
5043 /* Wiretap error. */
5044 display_basename = g_filename_display_basename(filename);
5047 case WTAP_ERR_CANT_CLOSE:
5048 simple_error_message_box(
5049 "The file \"%s\" couldn't be closed for some unknown reason.",
5053 case WTAP_ERR_SHORT_WRITE:
5054 simple_error_message_box(
5055 "Not all the packets could be written to the file \"%s\".",
5060 simple_error_message_box(
5061 "An error occurred while closing the file \"%s\": %s.",
5062 display_basename, wtap_strerror(err));
5065 g_free(display_basename);
5068 We assume that a close error from the OS is really a write error. */
5069 write_failure_alert_box(filename, err);
5073 /* Reload the current capture file. */
5075 cf_reload(capture_file *cf) {
5077 gboolean is_tempfile;
5080 /* If the file could be opened, "cf_open()" calls "cf_close()"
5081 to get rid of state for the old capture file before filling in state
5082 for the new capture file. "cf_close()" will remove the file if
5083 it's a temporary file; we don't want that to happen (for one thing,
5084 it'd prevent subsequent reopens from working). Remember whether it's
5085 a temporary file, mark it as not being a temporary file, and then
5086 reopen it as the type of file it was.
5088 Also, "cf_close()" will free "cf->filename", so we must make
5089 a copy of it first. */
5090 filename = g_strdup(cf->filename);
5091 is_tempfile = cf->is_tempfile;
5092 cf->is_tempfile = FALSE;
5093 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
5094 switch (cf_read(cf, TRUE)) {
5098 /* Just because we got an error, that doesn't mean we were unable
5099 to read any of the file; we handle what we could get from the
5103 case CF_READ_ABORTED:
5104 /* The user bailed out of re-reading the capture file; the
5105 capture file has been closed - just free the capture file name
5106 string and return (without changing the last containing
5112 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
5113 Instead, the file was left open, so we should restore "cf->is_tempfile"
5116 XXX - change the menu? Presumably "cf_open()" will do that;
5117 make sure it does! */
5118 cf->is_tempfile = is_tempfile;
5120 /* "cf_open()" made a copy of the file name we handed it, so
5121 we should free up our copy. */
5131 * indent-tabs-mode: nil
5134 * ex: set shiftwidth=2 tabstop=8 expandtab:
5135 * :indentSize=2:tabSize=8:noTabs=true: