4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
21 #include <wsutil/tempfile.h>
22 #include <wsutil/file_util.h>
23 #include <wsutil/filesystem.h>
24 #include <version_info.h>
26 #include <wiretap/merge.h>
28 #include <epan/exceptions.h>
29 #include <epan/epan.h>
30 #include <epan/column.h>
31 #include <epan/packet.h>
32 #include <epan/column-utils.h>
33 #include <epan/expert.h>
34 #include <epan/prefs.h>
35 #include <epan/dfilter/dfilter.h>
36 #include <epan/epan_dissect.h>
38 #include <epan/dissectors/packet-ber.h>
39 #include <epan/timestamp.h>
40 #include <epan/dfilter/dfilter-macro.h>
41 #include <epan/strutil.h>
42 #include <epan/addr_resolv.h>
43 #include <epan/color_filters.h>
48 #include "frame_tvbuff.h"
50 #include "ui/alert_box.h"
51 #include "ui/simple_dialog.h"
52 #include "ui/main_statusbar.h"
53 #include "ui/progress_dlg.h"
54 #include "ui/ws_ui_util.h"
56 /* Needed for addrinfo */
57 #ifdef HAVE_SYS_TYPES_H
58 # include <sys/types.h>
61 #ifdef HAVE_SYS_SOCKET_H
62 #include <sys/socket.h>
65 #ifdef HAVE_NETINET_IN_H
66 # include <netinet/in.h>
70 # include <winsock2.h>
71 # include <ws2tcpip.h>
74 static gboolean read_record(capture_file *cf, dfilter_t *dfcode,
75 epan_dissect_t *edt, column_info *cinfo, gint64 offset);
77 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
84 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
86 static void match_subtree_text(proto_node *node, gpointer data);
87 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
89 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
91 static match_result match_narrow(capture_file *cf, frame_data *fdata,
93 static match_result match_wide(capture_file *cf, frame_data *fdata,
95 static match_result match_binary(capture_file *cf, frame_data *fdata,
97 static match_result match_regex(capture_file *cf, frame_data *fdata,
99 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
101 static match_result match_marked(capture_file *cf, frame_data *fdata,
103 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
105 static gboolean find_packet(capture_file *cf,
106 match_result (*match_function)(capture_file *, frame_data *, void *),
107 void *criterion, search_direction dir);
109 static void cf_rename_failure_alert_box(const char *filename, int err);
110 static void ref_time_packets(capture_file *cf);
112 /* Seconds spent processing packets between pushing UI updates. */
113 #define PROGBAR_UPDATE_INTERVAL 0.150
115 /* Show the progress bar after this many seconds. */
116 #define PROGBAR_SHOW_DELAY 0.5
119 * We could probably use g_signal_...() instead of the callbacks below but that
120 * would require linking our CLI programs to libgobject and creating an object
121 * instance for the signals.
124 cf_callback_t cb_fct;
126 } cf_callback_data_t;
128 static GList *cf_callbacks = NULL;
131 cf_callback_invoke(int event, gpointer data)
133 cf_callback_data_t *cb;
134 GList *cb_item = cf_callbacks;
136 /* there should be at least one interested */
137 g_assert(cb_item != NULL);
139 while (cb_item != NULL) {
140 cb = (cf_callback_data_t *)cb_item->data;
141 cb->cb_fct(event, data, cb->user_data);
142 cb_item = g_list_next(cb_item);
148 cf_callback_add(cf_callback_t func, gpointer user_data)
150 cf_callback_data_t *cb;
152 cb = g_new(cf_callback_data_t,1);
154 cb->user_data = user_data;
156 cf_callbacks = g_list_prepend(cf_callbacks, cb);
160 cf_callback_remove(cf_callback_t func, gpointer user_data)
162 cf_callback_data_t *cb;
163 GList *cb_item = cf_callbacks;
165 while (cb_item != NULL) {
166 cb = (cf_callback_data_t *)cb_item->data;
167 if (cb->cb_fct == func && cb->user_data == user_data) {
168 cf_callbacks = g_list_remove(cf_callbacks, cb);
172 cb_item = g_list_next(cb_item);
175 g_assert_not_reached();
179 cf_timestamp_auto_precision(capture_file *cf)
183 /* don't try to get the file's precision if none is opened */
184 if (cf->state == FILE_CLOSED) {
188 /* Set the column widths of those columns that show the time in
189 "command-line-specified" format. */
190 for (i = 0; i < cf->cinfo.num_cols; i++) {
191 if (col_has_time_fmt(&cf->cinfo, i)) {
192 packet_list_resize_column(i);
198 cf_get_computed_elapsed(capture_file *cf)
200 return cf->computed_elapsed;
204 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
207 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
212 g_get_current_time(&time_now);
214 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
215 time_now.tv_usec - start_time->tv_usec;
217 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
220 static const nstime_t *
221 ws_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
223 if (prov->prev_dis && prov->prev_dis->num == frame_num)
224 return &prov->prev_dis->abs_ts;
226 if (prov->prev_cap && prov->prev_cap->num == frame_num)
227 return &prov->prev_cap->abs_ts;
230 frame_data *fd = frame_data_sequence_find(prov->frames, frame_num);
232 return (fd) ? &fd->abs_ts : NULL;
239 ws_epan_new(capture_file *cf)
241 static const struct packet_provider_funcs funcs = {
243 cap_file_provider_get_interface_name,
244 cap_file_provider_get_interface_description,
245 cap_file_provider_get_user_comment
248 return epan_new(&cf->provider, &funcs);
252 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
257 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
261 /* The open succeeded. Close whatever capture file we had open,
262 and fill in the information for this file. */
265 /* Initialize the record metadata. */
266 wtap_rec_init(&cf->rec);
268 /* XXX - we really want to initialize this after we've read all
269 the packets, so we know how much we'll ultimately need. */
270 ws_buffer_init(&cf->buf, 1500);
272 /* Create new epan session for dissection.
273 * (The old one was freed in cf_close().)
275 cf->epan = ws_epan_new(cf);
277 /* We're about to start reading the file. */
278 cf->state = FILE_READ_IN_PROGRESS;
280 cf->provider.wth = wth;
283 /* Set the file name because we need it to set the follow stream filter.
284 XXX - is that still true? We need it for other reasons, though,
286 cf->filename = g_strdup(fname);
288 /* Indicate whether it's a permanent or temporary file. */
289 cf->is_tempfile = is_tempfile;
291 /* No user changes yet. */
292 cf->unsaved_changes = FALSE;
294 cf->computed_elapsed = 0;
296 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
297 cf->open_type = type;
298 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
300 cf->packet_comment_count = 0;
301 cf->displayed_count = 0;
302 cf->marked_count = 0;
303 cf->ignored_count = 0;
304 cf->ref_time_count = 0;
305 cf->drops_known = FALSE;
307 cf->snap = wtap_snapshot_length(cf->provider.wth);
309 /* Allocate a frame_data_sequence for the frames in this file */
310 cf->provider.frames = new_frame_data_sequence();
312 nstime_set_zero(&cf->elapsed_time);
313 cf->provider.ref = NULL;
314 cf->provider.prev_dis = NULL;
315 cf->provider.prev_cap = NULL;
318 packet_list_queue_draw();
319 cf_callback_invoke(cf_cb_file_opened, cf);
321 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
322 /* tell the BER dissector the file name */
323 ber_set_filename(cf->filename);
326 wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name);
327 wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
332 cfile_open_failure_alert_box(fname, *err, err_info);
337 * Add an encapsulation type to cf->linktypes.
340 cf_add_encapsulation_type(capture_file *cf, int encap)
344 for (i = 0; i < cf->linktypes->len; i++) {
345 if (g_array_index(cf->linktypes, gint, i) == encap)
346 return; /* it's already there */
348 /* It's not already there - add it. */
349 g_array_append_val(cf->linktypes, encap);
352 /* Reset everything to a pristine state */
354 cf_close(capture_file *cf)
356 cf->stop_flag = FALSE;
357 if (cf->state == FILE_CLOSED)
358 return; /* Nothing to do */
360 /* Die if we're in the middle of reading a file. */
361 g_assert(cf->state != FILE_READ_IN_PROGRESS);
363 cf_callback_invoke(cf_cb_file_closing, cf);
365 /* close things, if not already closed before */
366 color_filters_cleanup();
368 if (cf->provider.wth) {
369 wtap_close(cf->provider.wth);
370 cf->provider.wth = NULL;
372 /* We have no file open... */
373 if (cf->filename != NULL) {
374 /* If it's a temporary file, remove it. */
376 ws_unlink(cf->filename);
377 g_free(cf->filename);
380 /* ...which means we have no changes to that file to save. */
381 cf->unsaved_changes = FALSE;
383 /* no open_routine type */
384 cf->open_type = WTAP_TYPE_AUTO;
386 /* Clean up the record metadata. */
387 wtap_rec_cleanup(&cf->rec);
389 /* Free up the packet buffer. */
390 ws_buffer_free(&cf->buf);
392 dfilter_free(cf->rfcode);
394 if (cf->provider.frames != NULL) {
395 free_frame_data_sequence(cf->provider.frames);
396 cf->provider.frames = NULL;
398 if (cf->provider.frames_user_comments) {
399 g_tree_destroy(cf->provider.frames_user_comments);
400 cf->provider.frames_user_comments = NULL;
402 cf_unselect_packet(cf); /* nothing to select */
403 cf->first_displayed = 0;
404 cf->last_displayed = 0;
406 /* No frames, no frame selected, no field in that frame selected. */
408 cf->current_frame = 0;
410 cf->finfo_selected = NULL;
412 /* No frame link-layer types, either. */
413 if (cf->linktypes != NULL) {
414 g_array_free(cf->linktypes, TRUE);
415 cf->linktypes = NULL;
418 /* Clear the packet list. */
419 packet_list_freeze();
424 nstime_set_zero(&cf->elapsed_time);
426 reset_tap_listeners();
431 /* We have no file open. */
432 cf->state = FILE_CLOSED;
434 cf_callback_invoke(cf_cb_file_closed, cf);
438 * TRUE if the progress dialog doesn't exist and it looks like we'll
439 * take > 2s to load, FALSE otherwise.
441 static inline gboolean
442 progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
446 if (progdlg) return FALSE;
447 elapsed = g_timer_elapsed(prog_timer, NULL);
448 if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
449 || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
456 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
460 progbar_val = (gfloat) file_pos / (gfloat) size;
461 if (progbar_val > 1.0) {
463 /* The file probably grew while we were reading it.
464 * Update file size, and try again.
466 size = wtap_file_size(cf->provider.wth, NULL);
469 progbar_val = (gfloat) file_pos / (gfloat) size;
471 /* If it's still > 1, either "wtap_file_size()" failed (in which
472 * case there's not much we can do about it), or the file
473 * *shrank* (in which case there's not much we can do about
474 * it); just clip the progress value at 1.0.
476 if (progbar_val > 1.0f)
480 g_snprintf(status_str, status_size,
481 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
482 file_pos / 1024, size / 1024);
488 cf_read(capture_file *cf, gboolean reloading)
491 gchar *err_info = NULL;
493 progdlg_t *volatile progbar = NULL;
494 GTimer *prog_timer = g_timer_new();
498 volatile gboolean create_proto_tree;
501 volatile gboolean is_read_aborted = FALSE;
503 /* Compile the current display filter.
504 * We assume this will not fail since cf->dfilter is only set in
505 * cf_filter IFF the filter was valid.
507 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
508 g_assert(!cf->dfilter || (compiled && dfcode));
510 /* Get the union of the flags for all tap listeners. */
511 tap_flags = union_of_tap_listener_flags();
514 * Determine whether we need to create a protocol tree.
517 * we're going to apply a display filter;
519 * one of the tap listeners is going to apply a filter;
521 * one of the tap listeners requires a protocol tree;
523 * a postdissector wants field values or protocols on
527 (dfcode != NULL || have_filtering_tap_listeners() ||
528 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
530 reset_tap_listeners();
532 name_ptr = g_filename_display_basename(cf->filename);
535 cf_callback_invoke(cf_cb_file_reload_started, cf);
537 cf_callback_invoke(cf_cb_file_read_started, cf);
539 /* Record whether the file is compressed.
540 XXX - do we know this at open time? */
541 cf->iscompressed = wtap_iscompressed(cf->provider.wth);
543 /* The packet list window will be empty until the file is completly loaded */
544 packet_list_freeze();
546 cf->stop_flag = FALSE;
547 g_get_current_time(&start_time);
549 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
559 gchar status_str[100];
563 /* If any tap listeners require the columns, construct them. */
564 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
566 /* Find the size of the file. */
567 size = wtap_file_size(cf->provider.wth, NULL);
569 g_timer_start(prog_timer);
571 while ((wtap_read(cf->provider.wth, &err, &err_info, &data_offset))) {
574 file_pos = wtap_read_so_far(cf->provider.wth);
576 /* Create the progress bar if necessary. */
577 if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
578 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
580 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
581 TRUE, &cf->stop_flag, &start_time, progbar_val);
583 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
584 TRUE, &cf->stop_flag, &start_time, progbar_val);
588 * Update the progress bar, but do it only after
589 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
590 * and packets_bar_update will likely trigger UI paint events, which
591 * might take a while depending on the platform and display. Reset
592 * our timer *after* painting.
594 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
595 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
596 /* update the packet bar content on the first run or frequently on very large files */
597 update_progress_dlg(progbar, progbar_val, status_str);
598 compute_elapsed(cf, &start_time);
599 packets_bar_update();
600 g_timer_start(prog_timer);
604 if (cf->state == FILE_READ_ABORTED) {
605 /* Well, the user decided to exit Wireshark. Break out of the
606 loop, and let the code below (which is called even if there
607 aren't any packets left to read) exit. */
608 is_read_aborted = TRUE;
612 /* Well, the user decided to abort the read. He/She will be warned and
613 it might be enough for him/her to work with the already loaded
615 This is especially true for very large capture files, where you don't
616 want to wait loading the whole file (which may last minutes or even
617 hours even on fast machines) just to see that it was the wrong file. */
620 read_record(cf, dfcode, &edt, cinfo, data_offset);
623 CATCH(OutOfMemoryError) {
624 simple_message_box(ESD_TYPE_ERROR, NULL,
625 "More information and workarounds can be found at\n"
626 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
627 "Sorry, but Wireshark has run out of memory and has to terminate now.");
629 /* Could we close the current capture and free up memory from that? */
631 /* we have to terminate, as we cannot recover from the memory error */
637 /* Free the display name */
640 /* Cleanup and release all dfilter resources */
641 dfilter_free(dfcode);
643 epan_dissect_cleanup(&edt);
645 /* We're done reading the file; destroy the progress bar if it was created. */
647 destroy_progress_dlg(progbar);
648 g_timer_destroy(prog_timer);
650 /* We're done reading sequentially through the file. */
651 cf->state = FILE_READ_DONE;
653 /* Close the sequential I/O side, to free up memory it requires. */
654 wtap_sequential_close(cf->provider.wth);
656 /* Allow the protocol dissectors to free up memory that they
657 * don't need after the sequential run-through of the packets. */
658 postseq_cleanup_all_protocols();
660 /* compute the time it took to load the file */
661 compute_elapsed(cf, &start_time);
663 /* Set the file encapsulation type now; we don't know what it is until
664 we've looked at all the packets, as we don't know until then whether
665 there's more than one type (and thus whether it's
666 WTAP_ENCAP_PER_PACKET). */
667 cf->lnk_t = wtap_file_encap(cf->provider.wth);
669 cf->current_frame = frame_data_sequence_find(cf->provider.frames, cf->first_displayed);
674 cf_callback_invoke(cf_cb_file_reload_finished, cf);
676 cf_callback_invoke(cf_cb_file_read_finished, cf);
678 /* If we have any displayed packets to select, select the first of those
679 packets by making the first row the selected row. */
680 if (cf->first_displayed != 0) {
681 packet_list_select_first_row();
684 if (is_read_aborted) {
686 * Well, the user decided to exit Wireshark while reading this *offline*
687 * capture file (Live captures are handled by something like
688 * cf_continue_tail). Clean up accordingly.
691 return CF_READ_ABORTED;
695 simple_message_box(ESD_TYPE_WARN, NULL,
696 "The remaining packets in the file were discarded.\n"
698 "As a lot of packets from the original file will be missing,\n"
699 "remember to be careful when saving the current content to a file.\n",
700 "File loading was cancelled.");
701 return CF_READ_ERROR;
705 /* Put up a message box noting that the read failed somewhere along
706 the line. Don't throw out the stuff we managed to read, though,
708 cfile_read_failure_alert_box(NULL, err, err_info);
709 return CF_READ_ERROR;
716 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
719 volatile int newly_displayed_packets = 0;
722 gboolean create_proto_tree;
726 /* Compile the current display filter.
727 * We assume this will not fail since cf->dfilter is only set in
728 * cf_filter IFF the filter was valid.
730 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
731 g_assert(!cf->dfilter || (compiled && dfcode));
733 /* Get the union of the flags for all tap listeners. */
734 tap_flags = union_of_tap_listener_flags();
737 * Determine whether we need to create a protocol tree.
740 * we're going to apply a display filter;
742 * one of the tap listeners is going to apply a filter;
744 * one of the tap listeners requires a protocol tree;
746 * a postdissector wants field values or protocols on
750 (dfcode != NULL || have_filtering_tap_listeners() ||
751 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
755 /* Don't freeze/thaw the list when doing live capture */
756 /*packet_list_freeze();*/
758 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
760 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
763 gint64 data_offset = 0;
766 /* If any tap listeners require the columns, construct them. */
767 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
769 while (to_read != 0) {
770 wtap_cleareof(cf->provider.wth);
771 if (!wtap_read(cf->provider.wth, err, &err_info, &data_offset)) {
774 if (cf->state == FILE_READ_ABORTED) {
775 /* Well, the user decided to exit Wireshark. Break out of the
776 loop, and let the code below (which is called even if there
777 aren't any packets left to read) exit. */
780 if (read_record(cf, dfcode, &edt, (column_info *) cinfo, data_offset)) {
781 newly_displayed_packets++;
786 CATCH(OutOfMemoryError) {
787 simple_message_box(ESD_TYPE_ERROR, NULL,
788 "More information and workarounds can be found at\n"
789 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
790 "Sorry, but Wireshark has run out of memory and has to terminate now.");
792 /* Could we close the current capture and free up memory from that? */
793 return CF_READ_ABORTED;
795 /* we have to terminate, as we cannot recover from the memory error */
801 /* Update the file encapsulation; it might have changed based on the
802 packets we've read. */
803 cf->lnk_t = wtap_file_encap(cf->provider.wth);
805 /* Cleanup and release all dfilter resources */
806 dfilter_free(dfcode);
808 epan_dissect_cleanup(&edt);
810 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
811 cf->count, cf->state, *err);*/
813 /* Don't freeze/thaw the list when doing live capture */
814 /*packet_list_thaw();*/
815 /* With the new packet list the first packet
816 * isn't automatically selected.
818 if (!cf->current_frame)
819 packet_list_select_first_row();
821 /* moving to the end of the packet list - if the user requested so and
822 we have some new packets. */
823 if (newly_displayed_packets && cf->count != 0)
824 packet_list_moveto_end();
826 if (cf->state == FILE_READ_ABORTED) {
827 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
828 so that our caller can kill off the capture child process;
829 this will cause an EOF on the pipe from the child, so
830 "cf_finish_tail()" will be called, and it will clean up
832 return CF_READ_ABORTED;
833 } else if (*err != 0) {
834 /* We got an error reading the capture file.
835 XXX - pop up a dialog box instead? */
836 if (err_info != NULL) {
837 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
838 wtap_strerror(*err), cf->filename, err_info);
841 g_warning("Error \"%s\" while reading \"%s\"",
842 wtap_strerror(*err), cf->filename);
844 return CF_READ_ERROR;
850 cf_fake_continue_tail(capture_file *cf) {
851 cf->state = FILE_READ_DONE;
855 cf_finish_tail(capture_file *cf, int *err)
862 gboolean create_proto_tree;
866 /* Compile the current display filter.
867 * We assume this will not fail since cf->dfilter is only set in
868 * cf_filter IFF the filter was valid.
870 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
871 g_assert(!cf->dfilter || (compiled && dfcode));
873 /* Get the union of the flags for all tap listeners. */
874 tap_flags = union_of_tap_listener_flags();
876 /* If any tap listeners require the columns, construct them. */
877 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
880 * Determine whether we need to create a protocol tree.
883 * we're going to apply a display filter;
885 * one of the tap listeners is going to apply a filter;
887 * one of the tap listeners requires a protocol tree;
889 * a postdissector wants field values or protocols on
893 (dfcode != NULL || have_filtering_tap_listeners() ||
894 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
896 if (cf->provider.wth == NULL) {
898 return CF_READ_ERROR;
901 /* Don't freeze/thaw the list when doing live capture */
902 /*packet_list_freeze();*/
904 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
906 while ((wtap_read(cf->provider.wth, err, &err_info, &data_offset))) {
907 if (cf->state == FILE_READ_ABORTED) {
908 /* Well, the user decided to abort the read. Break out of the
909 loop, and let the code below (which is called even if there
910 aren't any packets left to read) exit. */
913 read_record(cf, dfcode, &edt, cinfo, data_offset);
916 /* Cleanup and release all dfilter resources */
917 dfilter_free(dfcode);
919 epan_dissect_cleanup(&edt);
921 /* Don't freeze/thaw the list when doing live capture */
922 /*packet_list_thaw();*/
924 if (cf->state == FILE_READ_ABORTED) {
925 /* Well, the user decided to abort the read. We're only called
926 when the child capture process closes the pipe to us (meaning
927 it's probably exited), so we can just close the capture
928 file; we return CF_READ_ABORTED so our caller can do whatever
929 is appropriate when that happens. */
931 return CF_READ_ABORTED;
934 /* We're done reading sequentially through the file. */
935 cf->state = FILE_READ_DONE;
937 /* We're done reading sequentially through the file; close the
938 sequential I/O side, to free up memory it requires. */
939 wtap_sequential_close(cf->provider.wth);
941 /* Allow the protocol dissectors to free up memory that they
942 * don't need after the sequential run-through of the packets. */
943 postseq_cleanup_all_protocols();
945 /* Update the file encapsulation; it might have changed based on the
946 packets we've read. */
947 cf->lnk_t = wtap_file_encap(cf->provider.wth);
949 /* Update the details in the file-set dialog, as the capture file
950 * has likely grown since we first stat-ed it */
951 fileset_update_file(cf->filename);
954 /* We got an error reading the capture file.
955 XXX - pop up a dialog box? */
956 if (err_info != NULL) {
957 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
958 wtap_strerror(*err), cf->filename, err_info);
961 g_warning("Error \"%s\" while reading \"%s\"",
962 wtap_strerror(*err), cf->filename);
964 return CF_READ_ERROR;
969 #endif /* HAVE_LIBPCAP */
972 cf_get_display_name(capture_file *cf)
976 /* Return a name to use in displays */
977 if (!cf->is_tempfile) {
978 /* Get the last component of the file name, and use that. */
980 displayname = g_filename_display_basename(cf->filename);
982 displayname=g_strdup("(No file)");
985 /* The file we read is a temporary file from a live capture or
986 a merge operation; we don't mention its name, but, if it's
987 from a capture, give the source of the capture. */
989 displayname = g_strdup(cf->source);
991 displayname = g_strdup("(Untitled)");
997 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1003 cf->source = g_strdup(source);
1005 cf->source = g_strdup("");
1009 const gchar *cf_get_tempfile_source(capture_file *cf) {
1017 /* XXX - use a macro instead? */
1019 cf_get_packet_count(capture_file *cf)
1024 /* XXX - use a macro instead? */
1026 cf_is_tempfile(capture_file *cf)
1028 return cf->is_tempfile;
1031 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1033 cf->is_tempfile = is_tempfile;
1037 /* XXX - use a macro instead? */
1038 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1040 cf->drops_known = drops_known;
1043 /* XXX - use a macro instead? */
1044 void cf_set_drops(capture_file *cf, guint32 drops)
1049 /* XXX - use a macro instead? */
1050 gboolean cf_get_drops_known(capture_file *cf)
1052 return cf->drops_known;
1055 /* XXX - use a macro instead? */
1056 guint32 cf_get_drops(capture_file *cf)
1061 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1063 cf->rfcode = rfcode;
1067 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1068 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1069 wtap_rec *rec, const guint8 *buf, gboolean add_to_packet_list)
1071 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1072 &cf->provider.ref, cf->provider.prev_dis);
1073 cf->provider.prev_cap = fdata;
1075 if (dfcode != NULL) {
1076 epan_dissect_prime_with_dfilter(edt, dfcode);
1079 /* Prepare coloring rules, this ensures that display filter rules containing
1080 * frame.color_rule references are still processed.
1081 * TODO: actually detect that situation or maybe apply other optimizations? */
1082 if (edt->tree && color_filters_used()) {
1083 color_filters_prime_edt(edt);
1084 fdata->flags.need_colorize = 1;
1088 if (!fdata->flags.visited) {
1089 /* This is the first pass, so prime the epan_dissect_t with the
1090 hfids postdissectors want on the first pass. */
1091 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1094 /* Dissect the frame. */
1095 epan_dissect_run_with_taps(edt, cf->cd_t, rec,
1096 frame_tvbuff_new(&cf->provider, fdata, buf),
1099 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1100 if (dfcode != NULL) {
1101 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1103 if (fdata->flags.passed_dfilter) {
1104 /* This frame passed the display filter but it may depend on other
1105 * (potentially not displayed) frames. Find those frames and mark them
1108 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
1111 fdata->flags.passed_dfilter = 1;
1113 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1114 cf->displayed_count++;
1116 if (add_to_packet_list) {
1117 /* We fill the needed columns from new_packet_list */
1118 packet_list_append(cinfo, fdata);
1121 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1123 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1124 cf->provider.prev_dis = fdata;
1126 /* If we haven't yet seen the first frame, this is it. */
1127 if (cf->first_displayed == 0)
1128 cf->first_displayed = fdata->num;
1130 /* This is the last frame we've seen so far. */
1131 cf->last_displayed = fdata->num;
1134 epan_dissect_reset(edt);
1138 * Read in a new record.
1139 * Returns TRUE if the packet was added to the packet (record) list,
1143 read_record(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1144 column_info *cinfo, gint64 offset)
1146 wtap_rec *rec = wtap_get_rec(cf->provider.wth);
1147 const guint8 *buf = wtap_get_buf_ptr(cf->provider.wth);
1150 gboolean passed = TRUE;
1151 gboolean added = FALSE;
1153 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1154 it's not already there.
1155 XXX - yes, this is O(N), so if every packet had a different
1156 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1157 there are probably going to be a small number of encapsulation types
1159 if (rec->rec_type == REC_TYPE_PACKET) {
1160 cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap);
1163 /* The frame number of this packet, if we add it to the set of frames,
1164 would be one more than the count of frames in the file so far. */
1165 frame_data_init(&fdlocal, cf->count + 1, rec, offset, cf->cum_bytes);
1168 epan_dissect_t rf_edt;
1170 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1171 epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
1172 epan_dissect_run(&rf_edt, cf->cd_t, rec,
1173 frame_tvbuff_new(&cf->provider, &fdlocal, buf),
1175 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1176 epan_dissect_cleanup(&rf_edt);
1182 /* This does a shallow copy of fdlocal, which is good enough. */
1183 fdata = frame_data_sequence_add(cf->provider.frames, &fdlocal);
1186 if (rec->opt_comment != NULL)
1187 cf->packet_comment_count++;
1188 cf->f_datalen = offset + fdlocal.cap_len;
1190 if (!cf->redissecting) {
1191 add_packet_to_packet_list(fdata, cf, edt, dfcode,
1192 cinfo, rec, buf, TRUE);
1200 typedef struct _callback_data_t {
1203 GTimeVal start_time;
1211 merge_callback(merge_event event, int num _U_,
1212 const merge_in_file_t in_files[], const guint in_file_count,
1216 callback_data_t *cb_data = (callback_data_t*) data;
1218 g_assert(cb_data != NULL);
1222 case MERGE_EVENT_INPUT_FILES_OPENED:
1226 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1230 case MERGE_EVENT_READY_TO_MERGE:
1231 /* Get the sum of the sizes of all the files. */
1232 for (i = 0; i < in_file_count; i++)
1233 cb_data->f_len += in_files[i].size;
1235 cb_data->prog_timer = g_timer_new();
1236 g_timer_start(cb_data->prog_timer);
1238 g_get_current_time(&cb_data->start_time);
1241 case MERGE_EVENT_RECORD_WAS_READ:
1243 /* Create the progress bar if necessary.
1244 We check on every iteration of the loop, so that it takes no
1245 longer than the standard time to create it (otherwise, for a
1246 large file, we might take considerably longer than that standard
1247 time in order to get to the next progress bar step). */
1248 if (cb_data->progbar == NULL) {
1249 cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1250 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1254 * Update the progress bar, but do it only after
1255 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1256 * and packets_bar_update will likely trigger UI paint events, which
1257 * might take a while depending on the platform and display. Reset
1258 * our timer *after* painting.
1260 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1262 gint64 file_pos = 0;
1263 /* Get the sum of the seek positions in all of the files. */
1264 for (i = 0; i < in_file_count; i++)
1265 file_pos += wtap_read_so_far(in_files[i].wth);
1267 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1268 if (progbar_val > 1.0f) {
1269 /* Some file probably grew while we were reading it.
1270 That "shouldn't happen", so we'll just clip the progress
1275 if (cb_data->progbar != NULL) {
1276 gchar status_str[100];
1277 g_snprintf(status_str, sizeof(status_str),
1278 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1279 file_pos / 1024, cb_data->f_len / 1024);
1280 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1282 g_timer_start(cb_data->prog_timer);
1287 case MERGE_EVENT_DONE:
1288 /* We're done merging the files; destroy the progress bar if it was created. */
1289 if (cb_data->progbar != NULL)
1290 destroy_progress_dlg(cb_data->progbar);
1291 g_timer_destroy(cb_data->prog_timer);
1295 return cb_data->stop_flag;
1301 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1302 int in_file_count, char *const *in_filenames,
1303 int file_type, gboolean do_append)
1306 gchar *err_info = NULL;
1308 guint32 err_framenum;
1309 merge_result status;
1310 merge_progress_callback_t cb;
1311 callback_data_t *cb_data = g_new0(callback_data_t, 1);
1313 /* prepare our callback routine */
1314 cb_data->pd_window = pd_window;
1315 cb.callback_func = merge_callback;
1318 cf_callback_invoke(cf_cb_file_merge_started, NULL);
1320 /* merge the files */
1321 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1322 (const char *const *) in_filenames,
1323 in_file_count, do_append,
1324 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1325 "Wireshark", &cb, &err, &err_info,
1326 &err_fileno, &err_framenum);
1334 case MERGE_USER_ABORTED:
1335 /* this isn't really an error, though we will return CF_ERROR later */
1338 case MERGE_ERR_CANT_OPEN_INFILE:
1339 cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
1342 case MERGE_ERR_CANT_OPEN_OUTFILE:
1343 cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
1346 case MERGE_ERR_CANT_READ_INFILE:
1347 cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
1350 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1351 simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
1352 err_framenum, in_filenames[err_fileno]);
1355 case MERGE_ERR_CANT_WRITE_OUTFILE:
1356 cfile_write_failure_alert_box(in_filenames[err_fileno],
1357 *out_filenamep, err, err_info,
1358 err_framenum, file_type);
1361 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1362 cfile_close_failure_alert_box(*out_filenamep, err);
1366 simple_error_message_box("Unknown merge_files error %d", status);
1370 cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1372 if (status != MERGE_OK) {
1373 /* Callers aren't expected to treat an error or an explicit abort
1374 differently - we put up error dialogs ourselves, so they don't
1382 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1384 const char *filter_new = dftext ? dftext : "";
1385 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1388 GTimeVal start_time;
1390 /* if new filter equals old one, do nothing unless told to do so */
1391 if (!force && strcmp(filter_new, filter_old) == 0) {
1397 if (dftext == NULL) {
1398 /* The new filter is an empty filter (i.e., display all packets).
1399 * so leave dfcode==NULL
1403 * We have a filter; make a copy of it (as we'll be saving it),
1404 * and try to compile it.
1406 dftext = g_strdup(dftext);
1407 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1408 /* The attempt failed; report an error. */
1409 simple_message_box(ESD_TYPE_ERROR, NULL,
1410 "See the help for a description of the display filter syntax.",
1411 "\"%s\" isn't a valid display filter: %s",
1419 if (dfcode == NULL) {
1420 /* Yes - free the filter text, and set it to null. */
1426 /* We have a valid filter. Replace the current filter. */
1427 g_free(cf->dfilter);
1428 cf->dfilter = dftext;
1429 g_get_current_time(&start_time);
1432 /* Now rescan the packet list, applying the new filter, but not
1433 throwing away information constructed on a previous pass. */
1434 if (cf->state != FILE_CLOSED) {
1435 if (dftext == NULL) {
1436 rescan_packets(cf, "Resetting", "Filter", FALSE);
1438 rescan_packets(cf, "Filtering", dftext, FALSE);
1442 /* Cleanup and release all dfilter resources */
1443 dfilter_free(dfcode);
1449 cf_reftime_packets(capture_file *cf)
1451 ref_time_packets(cf);
1455 cf_redissect_packets(capture_file *cf)
1457 if (cf->state != FILE_CLOSED) {
1458 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1463 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1464 wtap_rec *rec, Buffer *buf)
1469 if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) {
1470 cfile_read_failure_alert_box(cf->filename, err, err_info);
1477 cf_read_record(capture_file *cf, frame_data *fdata)
1479 return cf_read_record_r(cf, fdata, &cf->rec, &cf->buf);
1482 /* Rescan the list of packets, reconstructing the CList.
1484 "action" describes why we're doing this; it's used in the progress
1487 "action_item" describes what we're doing; it's used in the progress
1490 "redissect" is TRUE if we need to make the dissectors reconstruct
1491 any state information they have (because a preference that affects
1492 some dissector has changed, meaning some dissector might construct
1493 its state differently from the way it was constructed the last time). */
1495 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1497 /* Rescan packets new packet list */
1500 progdlg_t *progbar = NULL;
1501 GTimer *prog_timer = g_timer_new();
1503 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1504 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1505 gboolean selected_frame_seen;
1507 GTimeVal start_time;
1508 gchar status_str[100];
1512 gboolean create_proto_tree;
1514 gboolean add_to_packet_list = FALSE;
1516 guint32 frames_count;
1518 /* Compile the current display filter.
1519 * We assume this will not fail since cf->dfilter is only set in
1520 * cf_filter IFF the filter was valid.
1522 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1523 g_assert(!cf->dfilter || (compiled && dfcode));
1525 /* Get the union of the flags for all tap listeners. */
1526 tap_flags = union_of_tap_listener_flags();
1528 /* If any tap listeners require the columns, construct them. */
1529 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1532 * Determine whether we need to create a protocol tree.
1535 * we're going to apply a display filter;
1537 * one of the tap listeners is going to apply a filter;
1539 * one of the tap listeners requires a protocol tree;
1541 * we're redissecting and a postdissector wants field
1542 * values or protocols on the first pass.
1545 (dfcode != NULL || have_filtering_tap_listeners() ||
1546 (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1547 (redissect && postdissectors_want_hfids()));
1549 reset_tap_listeners();
1550 /* Which frame, if any, is the currently selected frame?
1551 XXX - should the selected frame or the focus frame be the "current"
1552 frame, that frame being the one from which "Find Frame" searches
1554 selected_frame = cf->current_frame;
1556 /* Mark frame num as not found */
1557 selected_frame_num = -1;
1559 /* Freeze the packet list while we redo it, so we don't get any
1560 screen updates while it happens. */
1561 packet_list_freeze();
1564 /* We need to re-initialize all the state information that protocols
1565 keep, because some preference that controls a dissector has changed,
1566 which might cause the state information to be constructed differently
1567 by that dissector. */
1569 /* We might receive new packets while redissecting, and we don't
1570 want to dissect those before their time. */
1571 cf->redissecting = TRUE;
1573 /* 'reset' dissection session */
1574 epan_free(cf->epan);
1575 if (cf->edt && cf->edt->pi.fd) {
1576 /* All pointers in "per frame proto data" for the currently selected
1577 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1578 Free them here to avoid unintended usage in packet_list_clear(). */
1579 frame_data_destroy(cf->edt->pi.fd);
1581 cf->epan = ws_epan_new(cf);
1582 cf->cinfo.epan = cf->epan;
1584 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1585 called via epan_new() / init_dissection() when reloading Lua plugins. */
1586 if (!create_proto_tree && have_filtering_tap_listeners()) {
1587 create_proto_tree = TRUE;
1590 /* We need to redissect the packets so we have to discard our old
1591 * packet list store. */
1592 packet_list_clear();
1593 add_to_packet_list = TRUE;
1596 /* We don't yet know which will be the first and last frames displayed. */
1597 cf->first_displayed = 0;
1598 cf->last_displayed = 0;
1600 /* We currently don't display any packets */
1601 cf->displayed_count = 0;
1603 /* Iterate through the list of frames. Call a routine for each frame
1604 to check whether it should be displayed and, if so, add it to
1605 the display list. */
1606 cf->provider.ref = NULL;
1607 cf->provider.prev_dis = NULL;
1608 cf->provider.prev_cap = NULL;
1611 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1613 g_timer_start(prog_timer);
1614 /* Count of packets at which we've looked. */
1616 /* Progress so far. */
1619 cf->stop_flag = FALSE;
1620 g_get_current_time(&start_time);
1622 /* no previous row yet */
1623 prev_frame_num = -1;
1626 preceding_frame_num = -1;
1627 preceding_frame = NULL;
1628 following_frame_num = -1;
1629 following_frame = NULL;
1631 selected_frame_seen = FALSE;
1633 frames_count = cf->count;
1635 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1637 for (framenum = 1; framenum <= frames_count; framenum++) {
1638 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1640 /* Create the progress bar if necessary.
1641 We check on every iteration of the loop, so that it takes no
1642 longer than the standard time to create it (otherwise, for a
1643 large file, we might take considerably longer than that standard
1644 time in order to get to the next progress bar step). */
1645 if (progbar == NULL)
1646 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1652 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1653 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1654 * likely trigger UI paint events, which might take a while depending on
1655 * the platform and display. Reset our timer *after* painting.
1657 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1658 /* let's not divide by zero. I should never be started
1659 * with count == 0, so let's assert that
1661 g_assert(cf->count > 0);
1662 progbar_val = (gfloat) count / frames_count;
1664 if (progbar != NULL) {
1665 g_snprintf(status_str, sizeof(status_str),
1666 "%4u of %u frames", count, frames_count);
1667 update_progress_dlg(progbar, progbar_val, status_str);
1670 g_timer_start(prog_timer);
1673 if (cf->stop_flag) {
1674 /* Well, the user decided to abort the filtering. Just stop.
1676 XXX - go back to the previous filter? Users probably just
1677 want not to wait for a filtering operation to finish;
1678 unless we cancel by having no filter, reverting to the
1679 previous filter will probably be even more expensive than
1680 continuing the filtering, as it involves going back to the
1681 beginning and filtering, and even with no filter we currently
1682 have to re-generate the entire clist, which is also expensive.
1684 I'm not sure what Network Monitor does, but it doesn't appear
1685 to give you an unfiltered display if you cancel. */
1692 /* Since all state for the frame was destroyed, mark the frame
1693 * as not visited, free the GSList referring to the state
1694 * data (the per-frame data itself was freed by
1695 * "init_dissection()"), and null out the GSList pointer. */
1696 frame_data_reset(fdata);
1697 frames_count = cf->count;
1700 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1701 fdata->flags.dependent_of_displayed = 0;
1703 if (!cf_read_record(cf, fdata))
1704 break; /* error reading the frame */
1706 /* If the previous frame is displayed, and we haven't yet seen the
1707 selected frame, remember that frame - it's the closest one we've
1708 yet seen before the selected frame. */
1709 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1710 preceding_frame_num = prev_frame_num;
1711 preceding_frame = prev_frame;
1714 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1716 ws_buffer_start_ptr(&cf->buf),
1717 add_to_packet_list);
1719 /* If this frame is displayed, and this is the first frame we've
1720 seen displayed after the selected frame, remember this frame -
1721 it's the closest one we've yet seen at or after the selected
1723 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1724 following_frame_num = fdata->num;
1725 following_frame = fdata;
1727 if (fdata == selected_frame) {
1728 selected_frame_seen = TRUE;
1729 if (fdata->flags.passed_dfilter)
1730 selected_frame_num = fdata->num;
1733 /* Remember this frame - it'll be the previous frame
1734 on the next pass through the loop. */
1735 prev_frame_num = fdata->num;
1739 epan_dissect_cleanup(&edt);
1741 /* We are done redissecting the packet list. */
1742 cf->redissecting = FALSE;
1745 frames_count = cf->count;
1746 /* Clear out what remains of the visited flags and per-frame data
1749 XXX - that may cause various forms of bogosity when dissecting
1750 these frames, as they won't have been seen by this sequential
1751 pass, but the only alternative I see is to keep scanning them
1752 even though the user requested that the scan stop, and that
1753 would leave the user stuck with an Wireshark grinding on
1754 until it finishes. Should we just stick them with that? */
1755 for (; framenum <= frames_count; framenum++) {
1756 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1757 frame_data_reset(fdata);
1761 /* We're done filtering the packets; destroy the progress bar if it
1763 if (progbar != NULL)
1764 destroy_progress_dlg(progbar);
1765 g_timer_destroy(prog_timer);
1767 /* Unfreeze the packet list. */
1768 if (!add_to_packet_list)
1769 packet_list_recreate_visible_rows();
1771 /* Compute the time it took to filter the file */
1772 compute_elapsed(cf, &start_time);
1776 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1778 if (selected_frame_num == -1) {
1779 /* The selected frame didn't pass the filter. */
1780 if (selected_frame == NULL) {
1781 /* That's because there *was* no selected frame. Make the first
1782 displayed frame the current frame. */
1783 selected_frame_num = 0;
1785 /* Find the nearest displayed frame to the selected frame (whether
1786 it's before or after that frame) and make that the current frame.
1787 If the next and previous displayed frames are equidistant from the
1788 selected frame, choose the next one. */
1789 g_assert(following_frame == NULL ||
1790 following_frame->num >= selected_frame->num);
1791 g_assert(preceding_frame == NULL ||
1792 preceding_frame->num <= selected_frame->num);
1793 if (following_frame == NULL) {
1794 /* No frame after the selected frame passed the filter, so we
1795 have to select the last displayed frame before the selected
1797 selected_frame_num = preceding_frame_num;
1798 selected_frame = preceding_frame;
1799 } else if (preceding_frame == NULL) {
1800 /* No frame before the selected frame passed the filter, so we
1801 have to select the first displayed frame after the selected
1803 selected_frame_num = following_frame_num;
1804 selected_frame = following_frame;
1806 /* Frames before and after the selected frame passed the filter, so
1807 we'll select the previous frame */
1808 selected_frame_num = preceding_frame_num;
1809 selected_frame = preceding_frame;
1814 if (selected_frame_num == -1) {
1815 /* There are no frames displayed at all. */
1816 cf_unselect_packet(cf);
1818 /* Either the frame that was selected passed the filter, or we've
1819 found the nearest displayed frame to that frame. Select it, make
1820 it the focus row, and make it visible. */
1821 /* Set to invalid to force update of packet list and packet details */
1822 cf->current_row = -1;
1823 if (selected_frame_num == 0) {
1824 packet_list_select_first_row();
1826 if (!packet_list_select_row_from_data(selected_frame)) {
1827 /* We didn't find a row corresponding to this frame.
1828 This means that the frame isn't being displayed currently,
1829 so we can't select it. */
1830 simple_message_box(ESD_TYPE_INFO, NULL,
1831 "The capture file is probably not fully dissected.",
1832 "End of capture exceeded.");
1837 /* Cleanup and release all dfilter resources */
1838 dfilter_free(dfcode);
1843 * Scan through all frame data and recalculate the ref time
1844 * without rereading the file.
1845 * XXX - do we need a progres bar or is this fast enough?
1848 ref_time_packets(capture_file *cf)
1854 cf->provider.ref = NULL;
1855 cf->provider.prev_dis = NULL;
1858 for (framenum = 1; framenum <= cf->count; framenum++) {
1859 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1861 /* just add some value here until we know if it is being displayed or not */
1862 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1868 /* If we don't have the time stamp of the first packet in the
1869 capture, it's because this is the first packet. Save the time
1870 stamp of this packet as the time stamp of the first packet. */
1871 if (cf->provider.ref == NULL)
1872 cf->provider.ref = fdata;
1873 /* if this frames is marked as a reference time frame, reset
1874 firstsec and firstusec to this frame */
1875 if (fdata->flags.ref_time)
1876 cf->provider.ref = fdata;
1878 /* If we don't have the time stamp of the previous displayed packet,
1879 it's because this is the first displayed packet. Save the time
1880 stamp of this packet as the time stamp of the previous displayed
1882 if (cf->provider.prev_dis == NULL) {
1883 cf->provider.prev_dis = fdata;
1886 /* Get the time elapsed between the first packet and this packet. */
1887 fdata->frame_ref_num = (fdata != cf->provider.ref) ? cf->provider.ref->num : 0;
1888 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->provider.ref->abs_ts);
1890 /* If it's greater than the current elapsed time, set the elapsed time
1891 to it (we check for "greater than" so as not to be confused by
1892 time moving backwards). */
1893 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1894 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1895 cf->elapsed_time = rel_ts;
1898 /* If this frame is displayed, get the time elapsed between the
1899 previous displayed packet and this packet. */
1900 if ( fdata->flags.passed_dfilter ) {
1901 fdata->prev_dis_num = cf->provider.prev_dis->num;
1902 cf->provider.prev_dis = fdata;
1908 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1909 /* This frame either passed the display filter list or is marked as
1910 a time reference frame. All time reference frames are displayed
1911 even if they don't pass the display filter */
1912 if (fdata->flags.ref_time) {
1913 /* if this was a TIME REF frame we should reset the cum_bytes field */
1914 cf->cum_bytes = fdata->pkt_len;
1915 fdata->cum_bytes = cf->cum_bytes;
1917 /* increase cum_bytes with this packets length */
1918 cf->cum_bytes += fdata->pkt_len;
1931 process_specified_records(capture_file *cf, packet_range_t *range,
1932 const char *string1, const char *string2, gboolean terminate_is_stop,
1933 gboolean (*callback)(capture_file *, frame_data *,
1934 wtap_rec *, const guint8 *, void *),
1935 void *callback_args,
1936 gboolean show_progress_bar)
1941 psp_return_t ret = PSP_FINISHED;
1943 progdlg_t *progbar = NULL;
1944 GTimer *prog_timer = g_timer_new();
1947 GTimeVal progbar_start_time;
1948 gchar progbar_status_str[100];
1949 range_process_e process_this;
1952 wtap_rec_init(&rec);
1953 ws_buffer_init(&buf, 1500);
1955 g_timer_start(prog_timer);
1956 /* Count of packets at which we've looked. */
1958 /* Progress so far. */
1961 cf->stop_flag = FALSE;
1962 g_get_current_time(&progbar_start_time);
1965 packet_range_process_init(range);
1967 /* Iterate through all the packets, printing the packets that
1968 were selected by the current display filter. */
1969 for (framenum = 1; framenum <= cf->count; framenum++) {
1970 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1972 /* Create the progress bar if necessary.
1973 We check on every iteration of the loop, so that it takes no
1974 longer than the standard time to create it (otherwise, for a
1975 large file, we might take considerably longer than that standard
1976 time in order to get to the next progress bar step). */
1977 if (show_progress_bar && progbar == NULL)
1978 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
1981 &progbar_start_time,
1985 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1986 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1987 * likely trigger UI paint events, which might take a while depending on
1988 * the platform and display. Reset our timer *after* painting.
1990 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1991 /* let's not divide by zero. I should never be started
1992 * with count == 0, so let's assert that
1994 g_assert(cf->count > 0);
1995 progbar_val = (gfloat) progbar_count / cf->count;
1997 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1998 "%4u of %u packets", progbar_count, cf->count);
1999 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2001 g_timer_start(prog_timer);
2004 if (cf->stop_flag) {
2005 /* Well, the user decided to abort the operation. Just stop,
2006 and arrange to return PSP_STOPPED to our caller, so they know
2007 it was stopped explicitly. */
2014 if (range != NULL) {
2015 /* do we have to process this packet? */
2016 process_this = packet_range_process_packet(range, fdata);
2017 if (process_this == range_process_next) {
2018 /* this packet uninteresting, continue with next one */
2020 } else if (process_this == range_processing_finished) {
2021 /* all interesting packets processed, stop the loop */
2026 /* Get the packet */
2027 if (!cf_read_record_r(cf, fdata, &rec, &buf)) {
2028 /* Attempt to get the packet failed. */
2032 /* Process the packet */
2033 if (!callback(cf, fdata, &rec, ws_buffer_start_ptr(&buf), callback_args)) {
2034 /* Callback failed. We assume it reported the error appropriately. */
2040 /* We're done printing the packets; destroy the progress bar if
2042 if (progbar != NULL)
2043 destroy_progress_dlg(progbar);
2044 g_timer_destroy(prog_timer);
2046 wtap_rec_cleanup(&rec);
2047 ws_buffer_free(&buf);
2055 } retap_callback_args_t;
2058 retap_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2059 const guint8 *pd, void *argsp)
2061 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2063 epan_dissect_run_with_taps(&args->edt, cf->cd_t, rec,
2064 frame_tvbuff_new(&cf->provider, fdata, pd),
2065 fdata, args->cinfo);
2066 epan_dissect_reset(&args->edt);
2072 cf_retap_packets(capture_file *cf)
2074 packet_range_t range;
2075 retap_callback_args_t callback_args;
2076 gboolean create_proto_tree;
2080 /* Presumably the user closed the capture file. */
2082 return CF_READ_ABORTED;
2085 cf_callback_invoke(cf_cb_file_retap_started, cf);
2087 /* Get the union of the flags for all tap listeners. */
2088 tap_flags = union_of_tap_listener_flags();
2090 /* If any tap listeners require the columns, construct them. */
2091 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2094 * Determine whether we need to create a protocol tree.
2097 * one of the tap listeners is going to apply a filter;
2099 * one of the tap listeners requires a protocol tree.
2102 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2104 /* Reset the tap listeners. */
2105 reset_tap_listeners();
2107 epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2109 /* Iterate through the list of packets, dissecting all packets and
2110 re-running the taps. */
2111 packet_range_init(&range, cf);
2112 packet_range_process_init(&range);
2114 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2115 "all packets", TRUE, retap_packet,
2116 &callback_args, TRUE);
2118 epan_dissect_cleanup(&callback_args.edt);
2120 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2124 /* Completed successfully. */
2128 /* Well, the user decided to abort the refiltering.
2129 Return CF_READ_ABORTED so our caller knows they did that. */
2130 return CF_READ_ABORTED;
2133 /* Error while retapping. */
2134 return CF_READ_ERROR;
2137 g_assert_not_reached();
2142 print_args_t *print_args;
2143 gboolean print_header_line;
2144 char *header_line_buf;
2145 int header_line_buf_len;
2146 gboolean print_formfeed;
2147 gboolean print_separator;
2151 int num_visible_cols;
2154 } print_callback_args_t;
2157 print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2158 const guint8 *pd, void *argsp)
2160 print_callback_args_t *args = (print_callback_args_t *)argsp;
2166 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2167 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2168 col_item_t* col_item;
2170 /* Fill in the column information if we're printing the summary
2172 if (args->print_args->print_summary) {
2173 col_custom_prime_edt(&args->edt, &cf->cinfo);
2174 epan_dissect_run(&args->edt, cf->cd_t, rec,
2175 frame_tvbuff_new(&cf->provider, fdata, pd),
2177 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2179 epan_dissect_run(&args->edt, cf->cd_t, rec,
2180 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2182 if (args->print_formfeed) {
2183 if (!new_page(args->print_args->stream))
2186 if (args->print_separator) {
2187 if (!print_line(args->print_args->stream, 0, ""))
2193 * We generate bookmarks, if the output format supports them.
2194 * The name is "__frameN__".
2196 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2198 if (args->print_args->print_summary) {
2199 if (!args->print_args->print_col_headings)
2200 args->print_header_line = FALSE;
2201 if (args->print_header_line) {
2202 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2204 args->print_header_line = FALSE; /* we might not need to print any more */
2206 cp = &args->line_buf[0];
2208 for (i = 0; i < args->num_visible_cols; i++) {
2209 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2210 /* Find the length of the string for this column. */
2211 column_len = (int) strlen(col_item->col_data);
2212 if (args->col_widths[i] > column_len)
2213 column_len = args->col_widths[i];
2215 /* Make sure there's room in the line buffer for the column; if not,
2216 double its length. */
2217 line_len += column_len + 1; /* "+1" for space */
2218 if (line_len > args->line_buf_len) {
2219 cp_off = (int) (cp - args->line_buf);
2220 args->line_buf_len = 2 * line_len;
2221 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2222 cp = args->line_buf + cp_off;
2225 /* Right-justify the packet number column. */
2226 if (col_item->col_fmt == COL_NUMBER)
2227 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2229 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2231 if (i != args->num_visible_cols - 1)
2237 * Generate a bookmark, using the summary line as the title.
2239 if (!print_bookmark(args->print_args->stream, bookmark_name,
2243 if (!print_line(args->print_args->stream, 0, args->line_buf))
2247 * Generate a bookmark, using "Frame N" as the title, as we're not
2248 * printing the summary line.
2250 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2251 if (!print_bookmark(args->print_args->stream, bookmark_name,
2254 } /* if (print_summary) */
2256 if (args->print_args->print_dissections != print_dissections_none) {
2257 if (args->print_args->print_summary) {
2258 /* Separate the summary line from the tree with a blank line. */
2259 if (!print_line(args->print_args->stream, 0, ""))
2263 /* Print the information in that tree. */
2264 if (!proto_tree_print(args->print_args->print_dissections,
2265 args->print_args->print_hex, &args->edt, NULL,
2266 args->print_args->stream))
2269 /* Print a blank line if we print anything after this (aka more than one packet). */
2270 args->print_separator = TRUE;
2272 /* Print a header line if we print any more packet summaries */
2273 if (args->print_args->print_col_headings)
2274 args->print_header_line = TRUE;
2277 if (args->print_args->print_hex) {
2278 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2279 if (!print_line(args->print_args->stream, 0, ""))
2282 /* Print the full packet data as hex. */
2283 if (!print_hex_data(args->print_args->stream, &args->edt))
2286 /* Print a blank line if we print anything after this (aka more than one packet). */
2287 args->print_separator = TRUE;
2289 /* Print a header line if we print any more packet summaries */
2290 if (args->print_args->print_col_headings)
2291 args->print_header_line = TRUE;
2292 } /* if (args->print_args->print_dissections != print_dissections_none) */
2294 epan_dissect_reset(&args->edt);
2296 /* do we want to have a formfeed between each packet from now on? */
2297 if (args->print_args->print_formfeed) {
2298 args->print_formfeed = TRUE;
2304 epan_dissect_reset(&args->edt);
2309 cf_print_packets(capture_file *cf, print_args_t *print_args,
2310 gboolean show_progress_bar)
2312 print_callback_args_t callback_args;
2315 int i, cp_off, column_len, line_len;
2316 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2320 gboolean proto_tree_needed;
2322 callback_args.print_args = print_args;
2323 callback_args.print_header_line = print_args->print_col_headings;
2324 callback_args.header_line_buf = NULL;
2325 callback_args.header_line_buf_len = 256;
2326 callback_args.print_formfeed = FALSE;
2327 callback_args.print_separator = FALSE;
2328 callback_args.line_buf = NULL;
2329 callback_args.line_buf_len = 256;
2330 callback_args.col_widths = NULL;
2331 callback_args.num_visible_cols = 0;
2332 callback_args.visible_cols = NULL;
2334 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2335 destroy_print_stream(print_args->stream);
2336 return CF_PRINT_WRITE_ERROR;
2339 if (print_args->print_summary) {
2340 /* We're printing packet summaries. Allocate the header line buffer
2341 and get the column widths. */
2342 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2344 /* Find the number of visible columns and the last visible column */
2345 for (i = 0; i < prefs.num_cols; i++) {
2347 clp = g_list_nth(prefs.col_list, i);
2348 if (clp == NULL) /* Sanity check, Invalid column requested */
2351 cfmt = (fmt_data *) clp->data;
2352 if (cfmt->visible) {
2354 last_visible_col = i;
2358 /* if num_visible_col is 0, we are done */
2359 if (num_visible_col == 0) {
2360 g_free(callback_args.header_line_buf);
2364 /* Find the widths for each of the columns - maximum of the
2365 width of the title and the width of the data - and construct
2366 a buffer with a line containing the column titles. */
2367 callback_args.num_visible_cols = num_visible_col;
2368 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2369 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2370 cp = &callback_args.header_line_buf[0];
2372 visible_col_count = 0;
2373 for (i = 0; i < cf->cinfo.num_cols; i++) {
2375 clp = g_list_nth(prefs.col_list, i);
2376 if (clp == NULL) /* Sanity check, Invalid column requested */
2379 cfmt = (fmt_data *) clp->data;
2380 if (cfmt->visible == FALSE)
2383 /* Save the order of visible columns */
2384 callback_args.visible_cols[visible_col_count] = i;
2386 /* Don't pad the last column. */
2387 if (i == last_visible_col)
2388 callback_args.col_widths[visible_col_count] = 0;
2390 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2391 data_width = get_column_char_width(get_column_format(i));
2392 if (data_width > callback_args.col_widths[visible_col_count])
2393 callback_args.col_widths[visible_col_count] = data_width;
2396 /* Find the length of the string for this column. */
2397 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2398 if (callback_args.col_widths[visible_col_count] > column_len)
2399 column_len = callback_args.col_widths[visible_col_count];
2401 /* Make sure there's room in the line buffer for the column; if not,
2402 double its length. */
2403 line_len += column_len + 1; /* "+1" for space */
2404 if (line_len > callback_args.header_line_buf_len) {
2405 cp_off = (int) (cp - callback_args.header_line_buf);
2406 callback_args.header_line_buf_len = 2 * line_len;
2407 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2408 callback_args.header_line_buf_len + 1);
2409 cp = callback_args.header_line_buf + cp_off;
2412 /* Right-justify the packet number column. */
2413 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2414 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2416 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2418 if (i != cf->cinfo.num_cols - 1)
2421 visible_col_count++;
2425 /* Now start out the main line buffer with the same length as the
2426 header line buffer. */
2427 callback_args.line_buf_len = callback_args.header_line_buf_len;
2428 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2429 } /* if (print_summary) */
2431 /* Create the protocol tree, and make it visible, if we're printing
2432 the dissection or the hex data.
2433 XXX - do we need it if we're just printing the hex data? */
2435 callback_args.print_args->print_dissections != print_dissections_none ||
2436 callback_args.print_args->print_hex ||
2437 have_custom_cols(&cf->cinfo) || have_field_extractors();
2438 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2440 /* Iterate through the list of packets, printing the packets we were
2442 ret = process_specified_records(cf, &print_args->range, "Printing",
2443 "selected packets", TRUE, print_packet,
2444 &callback_args, show_progress_bar);
2445 epan_dissect_cleanup(&callback_args.edt);
2446 g_free(callback_args.header_line_buf);
2447 g_free(callback_args.line_buf);
2448 g_free(callback_args.col_widths);
2449 g_free(callback_args.visible_cols);
2454 /* Completed successfully. */
2458 /* Well, the user decided to abort the printing.
2460 XXX - note that what got generated before they did that
2461 will get printed if we're piping to a print program; we'd
2462 have to write to a file and then hand that to the print
2463 program to make it actually not print anything. */
2467 /* Error while printing.
2469 XXX - note that what got generated before they did that
2470 will get printed if we're piping to a print program; we'd
2471 have to write to a file and then hand that to the print
2472 program to make it actually not print anything. */
2473 destroy_print_stream(print_args->stream);
2474 return CF_PRINT_WRITE_ERROR;
2477 if (!print_finale(print_args->stream)) {
2478 destroy_print_stream(print_args->stream);
2479 return CF_PRINT_WRITE_ERROR;
2482 if (!destroy_print_stream(print_args->stream))
2483 return CF_PRINT_WRITE_ERROR;
2491 print_args_t *print_args;
2492 } write_packet_callback_args_t;
2495 write_pdml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2496 const guint8 *pd, void *argsp)
2498 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2500 /* Create the protocol tree, but don't fill in the column information. */
2501 epan_dissect_run(&args->edt, cf->cd_t, rec,
2502 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2504 /* Write out the information in that tree. */
2505 write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, &cf->cinfo, args->fh, FALSE);
2507 epan_dissect_reset(&args->edt);
2509 return !ferror(args->fh);
2513 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2515 write_packet_callback_args_t callback_args;
2519 fh = ws_fopen(print_args->file, "w");
2521 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2523 write_pdml_preamble(fh, cf->filename);
2526 return CF_PRINT_WRITE_ERROR;
2529 callback_args.fh = fh;
2530 callback_args.print_args = print_args;
2531 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2533 /* Iterate through the list of packets, printing the packets we were
2535 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2536 "selected packets", TRUE,
2537 write_pdml_packet, &callback_args, TRUE);
2539 epan_dissect_cleanup(&callback_args.edt);
2544 /* Completed successfully. */
2548 /* Well, the user decided to abort the printing. */
2552 /* Error while printing. */
2554 return CF_PRINT_WRITE_ERROR;
2557 write_pdml_finale(fh);
2560 return CF_PRINT_WRITE_ERROR;
2563 /* XXX - check for an error */
2570 write_psml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2571 const guint8 *pd, void *argsp)
2573 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2575 /* Fill in the column information */
2576 col_custom_prime_edt(&args->edt, &cf->cinfo);
2577 epan_dissect_run(&args->edt, cf->cd_t, rec,
2578 frame_tvbuff_new(&cf->provider, fdata, pd),
2580 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2582 /* Write out the column information. */
2583 write_psml_columns(&args->edt, args->fh, FALSE);
2585 epan_dissect_reset(&args->edt);
2587 return !ferror(args->fh);
2591 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2593 write_packet_callback_args_t callback_args;
2597 gboolean proto_tree_needed;
2599 fh = ws_fopen(print_args->file, "w");
2601 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2603 write_psml_preamble(&cf->cinfo, fh);
2606 return CF_PRINT_WRITE_ERROR;
2609 callback_args.fh = fh;
2610 callback_args.print_args = print_args;
2612 /* Fill in the column information, only create the protocol tree
2613 if having custom columns or field extractors. */
2614 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2615 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2617 /* Iterate through the list of packets, printing the packets we were
2619 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2620 "selected packets", TRUE,
2621 write_psml_packet, &callback_args, TRUE);
2623 epan_dissect_cleanup(&callback_args.edt);
2628 /* Completed successfully. */
2632 /* Well, the user decided to abort the printing. */
2636 /* Error while printing. */
2638 return CF_PRINT_WRITE_ERROR;
2641 write_psml_finale(fh);
2644 return CF_PRINT_WRITE_ERROR;
2647 /* XXX - check for an error */
2654 write_csv_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2655 const guint8 *pd, void *argsp)
2657 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2659 /* Fill in the column information */
2660 col_custom_prime_edt(&args->edt, &cf->cinfo);
2661 epan_dissect_run(&args->edt, cf->cd_t, rec,
2662 frame_tvbuff_new(&cf->provider, fdata, pd),
2664 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2666 /* Write out the column information. */
2667 write_csv_columns(&args->edt, args->fh);
2669 epan_dissect_reset(&args->edt);
2671 return !ferror(args->fh);
2675 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2677 write_packet_callback_args_t callback_args;
2678 gboolean proto_tree_needed;
2682 fh = ws_fopen(print_args->file, "w");
2684 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2686 write_csv_column_titles(&cf->cinfo, fh);
2689 return CF_PRINT_WRITE_ERROR;
2692 callback_args.fh = fh;
2693 callback_args.print_args = print_args;
2695 /* only create the protocol tree if having custom columns or field extractors. */
2696 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2697 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2699 /* Iterate through the list of packets, printing the packets we were
2701 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2702 "selected packets", TRUE,
2703 write_csv_packet, &callback_args, TRUE);
2705 epan_dissect_cleanup(&callback_args.edt);
2710 /* Completed successfully. */
2714 /* Well, the user decided to abort the printing. */
2718 /* Error while printing. */
2720 return CF_PRINT_WRITE_ERROR;
2723 /* XXX - check for an error */
2730 carrays_write_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2731 const guint8 *pd, void *argsp)
2733 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2735 epan_dissect_run(&args->edt, cf->cd_t, rec,
2736 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2737 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2738 epan_dissect_reset(&args->edt);
2740 return !ferror(args->fh);
2744 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2746 write_packet_callback_args_t callback_args;
2750 fh = ws_fopen(print_args->file, "w");
2753 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2757 return CF_PRINT_WRITE_ERROR;
2760 callback_args.fh = fh;
2761 callback_args.print_args = print_args;
2762 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2764 /* Iterate through the list of packets, printing the packets we were
2766 ret = process_specified_records(cf, &print_args->range,
2768 "selected packets", TRUE,
2769 carrays_write_packet, &callback_args, TRUE);
2771 epan_dissect_cleanup(&callback_args.edt);
2775 /* Completed successfully. */
2778 /* Well, the user decided to abort the printing. */
2781 /* Error while printing. */
2783 return CF_PRINT_WRITE_ERROR;
2791 write_json_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2792 const guint8 *pd, void *argsp)
2794 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2796 /* Create the protocol tree, but don't fill in the column information. */
2797 epan_dissect_run(&args->edt, cf->cd_t, rec,
2798 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2800 /* Write out the information in that tree. */
2801 write_json_proto_tree(NULL, args->print_args->print_dissections,
2802 args->print_args->print_hex, NULL, PF_NONE,
2803 &args->edt, &cf->cinfo, proto_node_group_children_by_unique, args->fh);
2805 epan_dissect_reset(&args->edt);
2807 return !ferror(args->fh);
2811 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2813 write_packet_callback_args_t callback_args;
2817 fh = ws_fopen(print_args->file, "w");
2819 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2821 write_json_preamble(fh);
2824 return CF_PRINT_WRITE_ERROR;
2827 callback_args.fh = fh;
2828 callback_args.print_args = print_args;
2829 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2831 /* Iterate through the list of packets, printing the packets we were
2833 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2834 "selected packets", TRUE,
2835 write_json_packet, &callback_args, TRUE);
2837 epan_dissect_cleanup(&callback_args.edt);
2842 /* Completed successfully. */
2846 /* Well, the user decided to abort the printing. */
2850 /* Error while printing. */
2852 return CF_PRINT_WRITE_ERROR;
2855 write_json_finale(fh);
2858 return CF_PRINT_WRITE_ERROR;
2861 /* XXX - check for an error */
2868 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2869 search_direction dir)
2873 mdata.string = string;
2874 mdata.string_len = strlen(string);
2875 return find_packet(cf, match_protocol_tree, &mdata, dir);
2879 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2881 mdata->frame_matched = FALSE;
2882 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2883 mdata->string_len = strlen(mdata->string);
2885 /* Iterate through all the nodes looking for matching text */
2886 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2887 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2891 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2893 match_data *mdata = (match_data *)criterion;
2896 /* Load the frame's data. */
2897 if (!cf_read_record(cf, fdata)) {
2898 /* Attempt to get the packet failed. */
2902 /* Construct the protocol tree, including the displayed text */
2903 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2904 /* We don't need the column information */
2905 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
2906 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
2909 /* Iterate through all the nodes, seeing if they have text that matches. */
2911 mdata->frame_matched = FALSE;
2912 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2913 epan_dissect_cleanup(&edt);
2914 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2918 match_subtree_text(proto_node *node, gpointer data)
2920 match_data *mdata = (match_data *) data;
2921 const gchar *string = mdata->string;
2922 size_t string_len = mdata->string_len;
2923 capture_file *cf = mdata->cf;
2924 field_info *fi = PNODE_FINFO(node);
2925 gchar label_str[ITEM_LABEL_LENGTH];
2932 /* dissection with an invisible proto tree? */
2935 if (mdata->frame_matched) {
2936 /* We already had a match; don't bother doing any more work. */
2940 /* Don't match invisible entries. */
2941 if (PROTO_ITEM_IS_HIDDEN(node))
2944 /* was a free format label produced? */
2946 label_ptr = fi->rep->representation;
2948 /* no, make a generic label */
2949 label_ptr = label_str;
2950 proto_item_fill_label(fi, label_str);
2954 if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
2955 mdata->frame_matched = TRUE;
2960 /* Does that label match? */
2961 label_len = strlen(label_ptr);
2962 for (i = 0; i < label_len; i++) {
2963 c_char = label_ptr[i];
2965 c_char = g_ascii_toupper(c_char);
2966 if (c_char == string[c_match]) {
2968 if (c_match == string_len) {
2969 /* No need to look further; we have a match */
2970 mdata->frame_matched = TRUE;
2979 /* Recurse into the subtree, if it exists */
2980 if (node->first_child != NULL)
2981 proto_tree_children_foreach(node, match_subtree_text, mdata);
2985 cf_find_packet_summary_line(capture_file *cf, const char *string,
2986 search_direction dir)
2990 mdata.string = string;
2991 mdata.string_len = strlen(string);
2992 return find_packet(cf, match_summary_line, &mdata, dir);
2996 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2998 match_data *mdata = (match_data *)criterion;
2999 const gchar *string = mdata->string;
3000 size_t string_len = mdata->string_len;
3002 const char *info_column;
3003 size_t info_column_len;
3004 match_result result = MR_NOTMATCHED;
3010 /* Load the frame's data. */
3011 if (!cf_read_record(cf, fdata)) {
3012 /* Attempt to get the packet failed. */
3016 /* Don't bother constructing the protocol tree */
3017 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3018 /* Get the column information */
3019 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3020 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3023 /* Find the Info column */
3024 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3025 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3026 /* Found it. See if we match. */
3027 info_column = edt.pi.cinfo->columns[colx].col_data;
3028 info_column_len = strlen(info_column);
3030 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3031 result = MR_MATCHED;
3035 for (i = 0; i < info_column_len; i++) {
3036 c_char = info_column[i];
3038 c_char = g_ascii_toupper(c_char);
3039 if (c_char == string[c_match]) {
3041 if (c_match == string_len) {
3042 result = MR_MATCHED;
3052 epan_dissect_cleanup(&edt);
3059 } cbs_t; /* "Counted byte string" */
3063 * The current match_* routines only support ASCII case insensitivity and don't
3064 * convert UTF-8 inputs to UTF-16 for matching.
3066 * We could modify them to use the GLib Unicode routines or the International
3067 * Components for Unicode library but it's not apparent that we could do so
3068 * without consuming a lot more CPU and memory or that searching would be
3069 * significantly better.
3073 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3074 search_direction dir)
3079 info.data_len = string_size;
3081 /* Regex, String or hex search? */
3083 /* Regular Expression search */
3084 return find_packet(cf, match_regex, NULL, dir);
3085 } else if (cf->string) {
3086 /* String search - what type of string? */
3087 switch (cf->scs_type) {
3089 case SCS_NARROW_AND_WIDE:
3090 return find_packet(cf, match_narrow_and_wide, &info, dir);
3093 return find_packet(cf, match_narrow, &info, dir);
3096 return find_packet(cf, match_wide, &info, dir);
3099 g_assert_not_reached();
3103 return find_packet(cf, match_binary, &info, dir);
3107 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3109 cbs_t *info = (cbs_t *)criterion;
3110 const guint8 *ascii_text = info->data;
3111 size_t textlen = info->data_len;
3112 match_result result;
3119 /* Load the frame's data. */
3120 if (!cf_read_record(cf, fdata)) {
3121 /* Attempt to get the packet failed. */
3125 result = MR_NOTMATCHED;
3126 buf_len = fdata->cap_len;
3127 pd = ws_buffer_start_ptr(&cf->buf);
3129 while (i < buf_len) {
3132 c_char = g_ascii_toupper(c_char);
3133 if (c_char != '\0') {
3134 if (c_char == ascii_text[c_match]) {
3136 if (c_match == textlen) {
3137 result = MR_MATCHED;
3138 cf->search_pos = i; /* Save the position of the last character
3139 for highlighting the field. */
3140 cf->search_len = (guint32)textlen;
3145 g_assert(i>=c_match);
3146 i -= (guint32)c_match;
3156 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3159 cbs_t *info = (cbs_t *)criterion;
3160 const guint8 *ascii_text = info->data;
3161 size_t textlen = info->data_len;
3162 match_result result;
3168 /* Load the frame's data. */
3169 if (!cf_read_record(cf, fdata)) {
3170 /* Attempt to get the packet failed. */
3174 result = MR_NOTMATCHED;
3175 buf_len = fdata->cap_len;
3176 pd = ws_buffer_start_ptr(&cf->buf);
3178 while (i < buf_len) {
3181 c_char = g_ascii_toupper(c_char);
3182 if (c_char == ascii_text[c_match]) {
3184 if (c_match == textlen) {
3185 result = MR_MATCHED;
3186 cf->search_pos = i; /* Save the position of the last character
3187 for highlighting the field. */
3188 cf->search_len = (guint32)textlen;
3193 g_assert(i>=c_match);
3194 i -= (guint32)c_match;
3204 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3206 cbs_t *info = (cbs_t *)criterion;
3207 const guint8 *ascii_text = info->data;
3208 size_t textlen = info->data_len;
3209 match_result result;
3216 /* Load the frame's data. */
3217 if (!cf_read_record(cf, fdata)) {
3218 /* Attempt to get the packet failed. */
3222 result = MR_NOTMATCHED;
3223 buf_len = fdata->cap_len;
3224 pd = ws_buffer_start_ptr(&cf->buf);
3226 while (i < buf_len) {
3229 c_char = g_ascii_toupper(c_char);
3230 if (c_char == ascii_text[c_match]) {
3232 if (c_match == textlen) {
3233 result = MR_MATCHED;
3234 cf->search_pos = i; /* Save the position of the last character
3235 for highlighting the field. */
3236 cf->search_len = (guint32)textlen;
3242 g_assert(i>=(c_match*2));
3243 i -= (guint32)c_match*2;
3252 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3254 cbs_t *info = (cbs_t *)criterion;
3255 const guint8 *binary_data = info->data;
3256 size_t datalen = info->data_len;
3257 match_result result;
3263 /* Load the frame's data. */
3264 if (!cf_read_record(cf, fdata)) {
3265 /* Attempt to get the packet failed. */
3269 result = MR_NOTMATCHED;
3270 buf_len = fdata->cap_len;
3271 pd = ws_buffer_start_ptr(&cf->buf);
3273 while (i < buf_len) {
3274 if (pd[i] == binary_data[c_match]) {
3276 if (c_match == datalen) {
3277 result = MR_MATCHED;
3278 cf->search_pos = i; /* Save the position of the last character
3279 for highlighting the field. */
3280 cf->search_len = (guint32)datalen;
3285 g_assert(i>=c_match);
3286 i -= (guint32)c_match;
3295 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3297 match_result result = MR_NOTMATCHED;
3298 GMatchInfo *match_info = NULL;
3300 /* Load the frame's data. */
3301 if (!cf_read_record(cf, fdata)) {
3302 /* Attempt to get the packet failed. */
3306 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3307 0, (GRegexMatchFlags) 0, &match_info, NULL))
3309 gint start_pos = 0, end_pos = 0;
3310 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3311 cf->search_pos = end_pos - 1;
3312 cf->search_len = end_pos - start_pos;
3313 result = MR_MATCHED;
3319 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3320 search_direction dir)
3322 return find_packet(cf, match_dfilter, sfcode, dir);
3326 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3327 search_direction dir)
3332 if (!dfilter_compile(filter, &sfcode, NULL)) {
3334 * XXX - this shouldn't happen, as the filter string is machine
3339 if (sfcode == NULL) {
3341 * XXX - this shouldn't happen, as the filter string is machine
3346 result = find_packet(cf, match_dfilter, sfcode, dir);
3347 dfilter_free(sfcode);
3352 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3354 dfilter_t *sfcode = (dfilter_t *)criterion;
3356 match_result result;
3358 /* Load the frame's data. */
3359 if (!cf_read_record(cf, fdata)) {
3360 /* Attempt to get the packet failed. */
3364 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3365 epan_dissect_prime_with_dfilter(&edt, sfcode);
3366 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3367 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3369 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3370 epan_dissect_cleanup(&edt);
3375 cf_find_packet_marked(capture_file *cf, search_direction dir)
3377 return find_packet(cf, match_marked, NULL, dir);
3381 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3383 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3387 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3389 return find_packet(cf, match_time_reference, NULL, dir);
3393 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3395 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3399 find_packet(capture_file *cf,
3400 match_result (*match_function)(capture_file *, frame_data *, void *),
3401 void *criterion, search_direction dir)
3403 frame_data *start_fd;
3406 frame_data *new_fd = NULL;
3407 progdlg_t *progbar = NULL;
3408 GTimer *prog_timer = g_timer_new();
3412 GTimeVal start_time;
3413 gchar status_str[100];
3415 match_result result;
3417 start_fd = cf->current_frame;
3418 if (start_fd != NULL) {
3419 /* Iterate through the list of packets, starting at the packet we've
3420 picked, calling a routine to run the filter on the packet, see if
3421 it matches, and stop if so. */
3423 framenum = start_fd->num;
3425 g_timer_start(prog_timer);
3426 /* Progress so far. */
3429 cf->stop_flag = FALSE;
3430 g_get_current_time(&start_time);
3432 title = cf->sfilter?cf->sfilter:"";
3434 /* Create the progress bar if necessary.
3435 We check on every iteration of the loop, so that it takes no
3436 longer than the standard time to create it (otherwise, for a
3437 large file, we might take considerably longer than that standard
3438 time in order to get to the next progress bar step). */
3439 if (progbar == NULL)
3440 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3441 FALSE, &cf->stop_flag, &start_time, progbar_val);
3444 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3445 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3446 * likely trigger UI paint events, which might take a while depending on
3447 * the platform and display. Reset our timer *after* painting.
3449 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3450 /* let's not divide by zero. I should never be started
3451 * with count == 0, so let's assert that
3453 g_assert(cf->count > 0);
3455 progbar_val = (gfloat) count / cf->count;
3457 g_snprintf(status_str, sizeof(status_str),
3458 "%4u of %u packets", count, cf->count);
3459 update_progress_dlg(progbar, progbar_val, status_str);
3461 g_timer_start(prog_timer);
3464 if (cf->stop_flag) {
3465 /* Well, the user decided to abort the search. Go back to the
3466 frame where we started. */
3471 /* Go past the current frame. */
3472 if (dir == SD_BACKWARD) {
3473 /* Go on to the previous frame. */
3474 if (framenum == 1) {
3476 * XXX - other apps have a bit more of a detailed message
3477 * for this, and instead of offering "OK" and "Cancel",
3478 * they offer things such as "Continue" and "Cancel";
3479 * we need an API for popping up alert boxes with
3480 * {Verb} and "Cancel".
3483 if (prefs.gui_find_wrap)
3485 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3486 framenum = cf->count; /* wrap around */
3490 statusbar_push_temporary_msg("Search reached the beginning.");
3491 framenum = start_fd->num; /* stay on previous packet */
3496 /* Go on to the next frame. */
3497 if (framenum == cf->count) {
3498 if (prefs.gui_find_wrap)
3500 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3501 framenum = 1; /* wrap around */
3505 statusbar_push_temporary_msg("Search reached the end.");
3506 framenum = start_fd->num; /* stay on previous packet */
3511 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
3515 /* Is this packet in the display? */
3516 if (fdata->flags.passed_dfilter) {
3517 /* Yes. Does it match the search criterion? */
3518 result = (*match_function)(cf, fdata, criterion);
3519 if (result == MR_ERROR) {
3520 /* Error; our caller has reported the error. Go back to the frame
3521 where we started. */
3524 } else if (result == MR_MATCHED) {
3525 /* Yes. Go to the new frame. */
3531 if (fdata == start_fd) {
3532 /* We're back to the frame we were on originally, and that frame
3533 doesn't match the search filter. The search failed. */
3538 /* We're done scanning the packets; destroy the progress bar if it
3540 if (progbar != NULL)
3541 destroy_progress_dlg(progbar);
3542 g_timer_destroy(prog_timer);
3545 if (new_fd != NULL) {
3546 /* Find and select */
3547 cf->search_in_progress = TRUE;
3548 found = packet_list_select_row_from_data(new_fd);
3549 cf->search_in_progress = FALSE;
3550 cf->search_pos = 0; /* Reset the position */
3551 cf->search_len = 0; /* Reset length */
3553 /* We didn't find a row corresponding to this frame.
3554 This means that the frame isn't being displayed currently,
3555 so we can't select it. */
3556 simple_message_box(ESD_TYPE_INFO, NULL,
3557 "The capture file is probably not fully dissected.",
3558 "End of capture exceeded.");
3561 return TRUE; /* success */
3563 return FALSE; /* failure */
3567 cf_goto_frame(capture_file *cf, guint fnumber)
3571 if (cf == NULL || cf->provider.frames == NULL) {
3572 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3573 statusbar_push_temporary_msg("There is no file loaded");
3574 return FALSE; /* we failed to go to that packet */
3577 fdata = frame_data_sequence_find(cf->provider.frames, fnumber);
3579 if (fdata == NULL) {
3580 /* we didn't find a packet with that packet number */
3581 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3582 return FALSE; /* we failed to go to that packet */
3584 if (!fdata->flags.passed_dfilter) {
3585 /* that packet currently isn't displayed */
3586 /* XXX - add it to the set of displayed packets? */
3587 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3588 return FALSE; /* we failed to go to that packet */
3591 if (!packet_list_select_row_from_data(fdata)) {
3592 /* We didn't find a row corresponding to this frame.
3593 This means that the frame isn't being displayed currently,
3594 so we can't select it. */
3595 simple_message_box(ESD_TYPE_INFO, NULL,
3596 "The capture file is probably not fully dissected.",
3597 "End of capture exceeded.");
3600 return TRUE; /* we got to that packet */
3604 * Go to frame specified by currently selected protocol tree item.
3607 cf_goto_framenum(capture_file *cf)
3609 header_field_info *hfinfo;
3612 if (cf->finfo_selected) {
3613 hfinfo = cf->finfo_selected->hfinfo;
3615 if (hfinfo->type == FT_FRAMENUM) {
3616 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3618 return cf_goto_frame(cf, framenum);
3625 /* Select the packet on a given row. */
3627 cf_select_packet(capture_file *cf, int row)
3629 epan_dissect_t *old_edt;
3632 /* Get the frame data struct pointer for this frame */
3633 fdata = packet_list_get_row_data(row);
3635 if (fdata == NULL) {
3639 /* Get the data in that frame. */
3640 if (!cf_read_record (cf, fdata)) {
3644 /* Record that this frame is the current frame. */
3645 cf->current_frame = fdata;
3646 cf->current_row = row;
3649 /* Create the logical protocol tree. */
3650 /* We don't need the columns here. */
3651 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3653 tap_build_interesting(cf->edt);
3654 epan_dissect_run(cf->edt, cf->cd_t, &cf->rec,
3655 frame_tvbuff_new_buffer(&cf->provider, cf->current_frame, &cf->buf),
3656 cf->current_frame, NULL);
3658 dfilter_macro_build_ftv_cache(cf->edt->tree);
3660 if (old_edt != NULL)
3661 epan_dissect_free(old_edt);
3665 /* Unselect the selected packet, if any. */
3667 cf_unselect_packet(capture_file *cf)
3669 epan_dissect_t *old_edt = cf->edt;
3673 /* No packet is selected. */
3674 cf->current_frame = NULL;
3675 cf->current_row = 0;
3677 /* Destroy the epan_dissect_t for the unselected packet. */
3678 if (old_edt != NULL)
3679 epan_dissect_free(old_edt);
3683 * Mark a particular frame.
3686 cf_mark_frame(capture_file *cf, frame_data *frame)
3688 if (! frame->flags.marked) {
3689 frame->flags.marked = TRUE;
3690 if (cf->count > cf->marked_count)
3696 * Unmark a particular frame.
3699 cf_unmark_frame(capture_file *cf, frame_data *frame)
3701 if (frame->flags.marked) {
3702 frame->flags.marked = FALSE;
3703 if (cf->marked_count > 0)
3709 * Ignore a particular frame.
3712 cf_ignore_frame(capture_file *cf, frame_data *frame)
3714 if (! frame->flags.ignored) {
3715 frame->flags.ignored = TRUE;
3716 if (cf->count > cf->ignored_count)
3717 cf->ignored_count++;
3722 * Un-ignore a particular frame.
3725 cf_unignore_frame(capture_file *cf, frame_data *frame)
3727 if (frame->flags.ignored) {
3728 frame->flags.ignored = FALSE;
3729 if (cf->ignored_count > 0)
3730 cf->ignored_count--;
3735 * Read the section comment.
3738 cf_read_section_comment(capture_file *cf)
3740 wtap_block_t shb_inf;
3744 /* XXX - support multiple SHBs */
3745 shb_inf = wtap_file_get_shb(cf->provider.wth);
3747 /* Get the first comment from the SHB. */
3748 /* XXX - support multiple comments */
3749 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3755 * Modify the section comment.
3758 cf_update_section_comment(capture_file *cf, gchar *comment)
3760 wtap_block_t shb_inf;
3764 /* XXX - support multiple SHBs */
3765 shb_inf = wtap_file_get_shb(cf->provider.wth);
3767 /* Get the first comment from the SHB. */
3768 /* XXX - support multiple comments */
3769 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3770 /* There's no comment - add one. */
3771 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3773 /* See if the comment has changed or not */
3774 if (strcmp(shb_comment, comment) == 0) {
3779 /* The comment has changed, let's update it */
3780 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3782 /* Mark the file as having unsaved changes */
3783 cf->unsaved_changes = TRUE;
3787 * Get the comment on a packet (record).
3788 * If the comment has been edited, it returns the result of the edit,
3789 * otherwise it returns the comment from the file.
3792 cf_get_packet_comment(capture_file *cf, const frame_data *fd)
3796 /* fetch user comment */
3797 if (fd->flags.has_user_comment)
3798 return g_strdup(cap_file_provider_get_user_comment(&cf->provider, fd));
3800 /* fetch phdr comment */
3801 if (fd->flags.has_phdr_comment) {
3802 wtap_rec rec; /* Record metadata */
3803 Buffer buf; /* Record data */
3805 wtap_rec_init(&rec);
3806 ws_buffer_init(&buf, 1500);
3808 if (!cf_read_record_r(cf, fd, &rec, &buf))
3809 { /* XXX, what we can do here? */ }
3811 comment = rec.opt_comment;
3812 wtap_rec_cleanup(&rec);
3813 ws_buffer_free(&buf);
3820 * Update(replace) the comment on a capture from a frame
3823 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3825 char *pkt_comment = cf_get_packet_comment(cf, fd);
3827 /* Check if the comment has changed */
3828 if (!g_strcmp0(pkt_comment, new_comment)) {
3829 g_free(pkt_comment);
3832 g_free(pkt_comment);
3835 cf->packet_comment_count--;
3838 cf->packet_comment_count++;
3840 cap_file_provider_set_user_comment(&cf->provider, fd, new_comment);
3842 expert_update_comment_count(cf->packet_comment_count);
3844 /* OK, we have unsaved changes. */
3845 cf->unsaved_changes = TRUE;
3850 * What types of comments does this capture file have?
3853 cf_comment_types(capture_file *cf)
3855 guint32 comment_types = 0;
3857 if (cf_read_section_comment(cf) != NULL)
3858 comment_types |= WTAP_COMMENT_PER_SECTION;
3859 if (cf->packet_comment_count != 0)
3860 comment_types |= WTAP_COMMENT_PER_PACKET;
3861 return comment_types;
3865 * Add a resolved address to this file's list of resolved addresses.
3868 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
3871 * XXX - support multiple resolved address lists, and add to the one
3872 * attached to this file?
3874 if (!add_ip_name_from_string(addr, name))
3877 /* OK, we have unsaved changes. */
3878 cf->unsaved_changes = TRUE;
3886 } save_callback_args_t;
3889 * Save a capture to a file, in a particular format, saving either
3890 * all packets, all currently-displayed packets, or all marked packets.
3892 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3893 * up a message box for the failure.
3896 save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec,
3897 const guint8 *pd, void *argsp)
3899 save_callback_args_t *args = (save_callback_args_t *)argsp;
3903 const char *pkt_comment;
3905 /* Copy the record information from what was read in from the file. */
3908 /* Make changes based on anything that the user has done but that
3909 hasn't been saved yet. */
3910 if (fdata->flags.has_user_comment)
3911 pkt_comment = cap_file_provider_get_user_comment(&cf->provider, fdata);
3913 pkt_comment = rec->opt_comment;
3914 new_rec.opt_comment = g_strdup(pkt_comment);
3915 new_rec.has_comment_changed = fdata->flags.has_user_comment ? TRUE : FALSE;
3916 /* XXX - what if times have been shifted? */
3918 /* and save the packet */
3919 if (!wtap_dump(args->pdh, &new_rec, pd, &err, &err_info)) {
3920 cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
3925 g_free(new_rec.opt_comment);
3930 * Can this capture file be written out in any format using Wiretap
3931 * rather than by copying the raw data?
3934 cf_can_write_with_wiretap(capture_file *cf)
3936 /* We don't care whether we support the comments in this file or not;
3937 if we can't, we'll offer the user the option of discarding the
3939 return wtap_dump_can_write(cf->linktypes, 0);
3943 * Should we let the user do a save?
3947 * the file has unsaved changes, and we can save it in some
3948 * format through Wiretap
3952 * the file is a temporary file and has no unsaved changes (so
3953 * that "saving" it just means copying it).
3955 * XXX - we shouldn't allow files to be edited if they can't be saved,
3956 * so cf->unsaved_changes should be true only if the file can be saved.
3958 * We don't care whether we support the comments in this file or not;
3959 * if we can't, we'll offer the user the option of discarding the
3963 cf_can_save(capture_file *cf)
3965 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
3966 /* Saved changes, and we can write it out with Wiretap. */
3970 if (cf->is_tempfile && !cf->unsaved_changes) {
3972 * Temporary file with no unsaved changes, so we can just do a
3978 /* Nothing to save. */
3983 * Should we let the user do a "save as"?
3987 * we can save it in some format through Wiretap
3991 * the file is a temporary file and has no unsaved changes (so
3992 * that "saving" it just means copying it).
3994 * XXX - we shouldn't allow files to be edited if they can't be saved,
3995 * so cf->unsaved_changes should be true only if the file can be saved.
3997 * We don't care whether we support the comments in this file or not;
3998 * if we can't, we'll offer the user the option of discarding the
4002 cf_can_save_as(capture_file *cf)
4004 if (wtap_dump_can_write(cf->linktypes, 0)) {
4005 /* We can write it out with Wiretap. */
4009 if (cf->is_tempfile && !cf->unsaved_changes) {
4011 * Temporary file with no unsaved changes, so we can just do a
4017 /* Nothing to save. */
4022 * Does this file have unsaved data?
4025 cf_has_unsaved_data(capture_file *cf)
4028 * If this is a temporary file, or a file with unsaved changes, it
4031 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4035 * Quick scan to find packet offsets.
4037 static cf_read_status_t
4038 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4040 const wtap_rec *rec;
4045 progdlg_t *progbar = NULL;
4046 GTimer *prog_timer = g_timer_new();
4049 GTimeVal start_time;
4050 gchar status_str[100];
4055 /* Close the old handle. */
4056 wtap_close(cf->provider.wth);
4058 /* Open the new file. */
4059 /* XXX: this will go through all open_routines for a matching one. But right
4060 now rescan_file() is only used when a file is being saved to a different
4061 format than the original, and the user is not given a choice of which
4062 reader to use (only which format to save it in), so doing this makes
4064 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4065 if (cf->provider.wth == NULL) {
4066 cfile_open_failure_alert_box(fname, err, err_info);
4067 return CF_READ_ERROR;
4070 /* We're scanning a file whose contents should be the same as what
4071 we had before, so we don't discard dissection state etc.. */
4074 /* Set the file name because we need it to set the follow stream filter.
4075 XXX - is that still true? We need it for other reasons, though,
4077 cf->filename = g_strdup(fname);
4079 /* Indicate whether it's a permanent or temporary file. */
4080 cf->is_tempfile = is_tempfile;
4082 /* No user changes yet. */
4083 cf->unsaved_changes = FALSE;
4085 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
4086 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4088 cf->snap = wtap_snapshot_length(cf->provider.wth);
4090 name_ptr = g_filename_display_basename(cf->filename);
4092 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4094 /* Record whether the file is compressed.
4095 XXX - do we know this at open time? */
4096 cf->iscompressed = wtap_iscompressed(cf->provider.wth);
4098 /* Find the size of the file. */
4099 size = wtap_file_size(cf->provider.wth, NULL);
4101 g_timer_start(prog_timer);
4103 cf->stop_flag = FALSE;
4104 g_get_current_time(&start_time);
4107 rec = wtap_get_rec(cf->provider.wth);
4108 while ((wtap_read(cf->provider.wth, &err, &err_info, &data_offset))) {
4110 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4111 fdata->file_off = data_offset;
4114 cf->f_datalen = wtap_read_so_far(cf->provider.wth);
4116 /* Create the progress bar if necessary. */
4117 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4118 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4119 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4120 TRUE, &cf->stop_flag, &start_time, progbar_val);
4124 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4125 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4126 * likely trigger UI paint events, which might take a while depending on
4127 * the platform and display. Reset our timer *after* painting.
4129 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4130 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4131 /* update the packet bar content on the first run or frequently on very large files */
4132 update_progress_dlg(progbar, progbar_val, status_str);
4133 compute_elapsed(cf, &start_time);
4134 packets_bar_update();
4135 g_timer_start(prog_timer);
4139 if (cf->stop_flag) {
4140 /* Well, the user decided to abort the rescan. Sadly, as this
4141 isn't a reread, recovering is difficult, so we'll just
4142 close the current capture. */
4146 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4147 it's not already there.
4148 XXX - yes, this is O(N), so if every packet had a different
4149 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4150 there are probably going to be a small number of encapsulation types
4152 if (rec->rec_type == REC_TYPE_PACKET) {
4153 cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap);
4157 /* Free the display name */
4160 /* We're done reading the file; destroy the progress bar if it was created. */
4161 if (progbar != NULL)
4162 destroy_progress_dlg(progbar);
4163 g_timer_destroy(prog_timer);
4165 /* We're done reading sequentially through the file. */
4166 cf->state = FILE_READ_DONE;
4168 /* Close the sequential I/O side, to free up memory it requires. */
4169 wtap_sequential_close(cf->provider.wth);
4171 /* compute the time it took to load the file */
4172 compute_elapsed(cf, &start_time);
4174 /* Set the file encapsulation type now; we don't know what it is until
4175 we've looked at all the packets, as we don't know until then whether
4176 there's more than one type (and thus whether it's
4177 WTAP_ENCAP_PER_PACKET). */
4178 cf->lnk_t = wtap_file_encap(cf->provider.wth);
4180 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4182 if (cf->stop_flag) {
4183 /* Our caller will give up at this point. */
4184 return CF_READ_ABORTED;
4188 /* Put up a message box noting that the read failed somewhere along
4189 the line. Don't throw out the stuff we managed to read, though,
4191 cfile_read_failure_alert_box(NULL, err, err_info);
4192 return CF_READ_ERROR;
4198 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4199 gboolean compressed, gboolean discard_comments,
4200 gboolean dont_reopen)
4203 gchar *fname_new = NULL;
4206 addrinfo_lists_t *addr_lists;
4210 gchar *display_basename;
4217 save_callback_args_t callback_args;
4218 gboolean needs_reload = FALSE;
4220 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4222 addr_lists = get_addrinfo_list();
4224 if (save_format == cf->cd_t && compressed == cf->iscompressed
4225 && !discard_comments && !cf->unsaved_changes
4226 && (wtap_addrinfo_list_empty(addr_lists) || !wtap_dump_has_name_resolution(save_format))) {
4227 /* We're saving in the format it's already in, and we're not discarding
4228 comments, and there are no changes we have in memory that aren't saved
4229 to the file, and we have no name resolution information to write or
4230 the file format we're saving in doesn't support writing name
4231 resolution information, so we can just move or copy the raw data. */
4233 if (cf->is_tempfile) {
4234 /* The file being saved is a temporary file from a live
4235 capture, so it doesn't need to stay around under that name;
4236 first, try renaming the capture buffer file to the new name.
4237 This acts as a "safe save", in that, if the file already
4238 exists, the existing file will be removed only if the rename
4241 Sadly, on Windows, as we have the current capture file
4242 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4243 (to cause the rename to remove an existing target), as
4244 done by ws_stdio_rename() (ws_rename() is #defined to
4245 be ws_stdio_rename() on Windows) will fail.
4247 According to the MSDN documentation for CreateFile(), if,
4248 when we open a capture file, we were to directly do a CreateFile(),
4249 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4250 convert it to a file descriptor with _open_osfhandle(),
4251 that would allow the file to be renamed out from under us.
4253 However, that doesn't work in practice. Perhaps the problem
4254 is that the process doing the rename is the process that
4255 has the file open. */
4257 if (ws_rename(cf->filename, fname) == 0) {
4258 /* That succeeded - there's no need to copy the source file. */
4259 how_to_save = SAVE_WITH_MOVE;
4261 if (errno == EXDEV) {
4262 /* They're on different file systems, so we have to copy the
4264 how_to_save = SAVE_WITH_COPY;
4266 /* The rename failed, but not because they're on different
4267 file systems - put up an error message. (Or should we
4268 just punt and try to copy? The only reason why I'd
4269 expect the rename to fail and the copy to succeed would
4270 be if we didn't have permission to remove the file from
4271 the temporary directory, and that might be fixable - but
4272 is it worth requiring the user to go off and fix it?) */
4273 cf_rename_failure_alert_box(fname, errno);
4278 /* Windows - copy the file to its new location. */
4279 how_to_save = SAVE_WITH_COPY;
4282 /* It's a permanent file, so we should copy it, and not remove the
4284 how_to_save = SAVE_WITH_COPY;
4287 if (how_to_save == SAVE_WITH_COPY) {
4288 /* Copy the file, if we haven't moved it. If we're overwriting
4289 an existing file, we do it with a "safe save", by writing
4290 to a new file and, if the write succeeds, renaming the
4291 new file on top of the old file. */
4292 if (file_exists(fname)) {
4293 fname_new = g_strdup_printf("%s~", fname);
4294 if (!copy_file_binary_mode(cf->filename, fname_new))
4297 if (!copy_file_binary_mode(cf->filename, fname))
4302 /* Either we're saving in a different format or we're saving changes,
4303 such as added, modified, or removed comments, that haven't yet
4304 been written to the underlying file; we can't do that by copying
4305 or moving the capture file, we have to do it by writing the packets
4308 GArray *shb_hdrs = NULL;
4309 wtapng_iface_descriptions_t *idb_inf = NULL;
4310 GArray *nrb_hdrs = NULL;
4313 /* XXX: what free's this shb_hdr? */
4314 shb_hdrs = wtap_file_get_shb_for_new_file(cf->provider.wth);
4315 idb_inf = wtap_file_get_idb_info(cf->provider.wth);
4316 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->provider.wth);
4318 /* Determine what file encapsulation type we should use. */
4319 encap = wtap_dump_file_encap_type(cf->linktypes);
4321 if (file_exists(fname)) {
4322 /* We're overwriting an existing file; write out to a new file,
4323 and, if that succeeds, rename the new file on top of the
4324 old file. That makes this a "safe save", so that we don't
4325 lose the old file if we have a problem writing out the new
4326 file. (If the existing file is the current capture file,
4327 we *HAVE* to do that, otherwise we're overwriting the file
4328 from which we're reading the packets that we're writing!) */
4329 fname_new = g_strdup_printf("%s~", fname);
4330 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4331 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4333 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4334 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4340 cfile_dump_open_failure_alert_box(fname, err, save_format);
4344 /* Add address resolution */
4345 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4347 /* Iterate through the list of packets, processing all the packets. */
4348 callback_args.pdh = pdh;
4349 callback_args.fname = fname;
4350 callback_args.file_type = save_format;
4351 switch (process_specified_records(cf, NULL, "Saving", "packets",
4352 TRUE, save_record, &callback_args, TRUE)) {
4355 /* Completed successfully. */
4359 /* The user decided to abort the saving.
4360 If we're writing to a temporary file, remove it.
4361 XXX - should we do so even if we're not writing to a
4363 wtap_dump_close(pdh, &err);
4364 if (fname_new != NULL)
4365 ws_unlink(fname_new);
4366 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4367 return CF_WRITE_ABORTED;
4370 /* Error while saving.
4371 If we're writing to a temporary file, remove it. */
4372 if (fname_new != NULL)
4373 ws_unlink(fname_new);
4374 wtap_dump_close(pdh, &err);
4378 needs_reload = wtap_dump_get_needs_reload(pdh);
4380 if (!wtap_dump_close(pdh, &err)) {
4381 cfile_close_failure_alert_box(fname, err);
4385 how_to_save = SAVE_WITH_WTAP;
4388 if (fname_new != NULL) {
4389 /* We wrote out to fname_new, and should rename it on top of
4390 fname. fname_new is now closed, so that should be possible even
4391 on Windows. However, on Windows, we first need to close whatever
4392 file descriptors we have open for fname. */
4394 wtap_fdclose(cf->provider.wth);
4396 /* Now do the rename. */
4397 if (ws_rename(fname_new, fname) == -1) {
4398 /* Well, the rename failed. */
4399 cf_rename_failure_alert_box(fname, errno);
4401 /* Attempt to reopen the random file descriptor using the
4402 current file's filename. (At this point, the sequential
4403 file descriptor is closed.) */
4404 if (!wtap_fdreopen(cf->provider.wth, cf->filename, &err)) {
4405 /* Oh, well, we're screwed. */
4406 display_basename = g_filename_display_basename(cf->filename);
4407 simple_error_message_box(
4408 file_open_error_message(err, FALSE), display_basename);
4409 g_free(display_basename);
4416 /* If this was a temporary file, and we didn't do the save by doing
4417 a move, so the tempoary file is still around under its old name,
4419 if (cf->is_tempfile && how_to_save != SAVE_WITH_MOVE) {
4420 /* If this fails, there's not much we can do, so just ignore errors. */
4421 ws_unlink(cf->filename);
4424 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4425 cf->unsaved_changes = FALSE;
4428 switch (how_to_save) {
4430 case SAVE_WITH_MOVE:
4431 /* We just moved the file, so the wtap structure refers to the
4432 new file, and all the information other than the filename
4433 and the "is temporary" status applies to the new file; just
4435 g_free(cf->filename);
4436 cf->filename = g_strdup(fname);
4437 cf->is_tempfile = FALSE;
4438 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4441 case SAVE_WITH_COPY:
4442 /* We just copied the file, so all the information other than
4443 the wtap structure, the filename, and the "is temporary"
4444 status applies to the new file; just update that. */
4445 wtap_close(cf->provider.wth);
4446 /* Although we're just "copying" and then opening the copy, it will
4447 try all open_routine readers to open the copy, so we need to
4448 reset the cfile's open_type. */
4449 cf->open_type = WTAP_TYPE_AUTO;
4450 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4451 if (cf->provider.wth == NULL) {
4452 cfile_open_failure_alert_box(fname, err, err_info);
4455 g_free(cf->filename);
4456 cf->filename = g_strdup(fname);
4457 cf->is_tempfile = FALSE;
4459 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4462 case SAVE_WITH_WTAP:
4463 /* Open and read the file we saved to.
4465 XXX - this is somewhat of a waste; we already have the
4466 packets, all this gets us is updated file type information
4467 (which we could just stuff into "cf"), and having the new
4468 file be the one we have opened and from which we're reading
4469 the data, and it means we have to spend time opening and
4470 reading the file, which could be a significant amount of
4471 time if the file is large.
4473 If the capture-file-writing code were to return the
4474 seek offset of each packet it writes, we could save that
4475 in the frame_data structure for the frame, and just open
4476 the file without reading it again...
4478 ...as long as, for gzipped files, the process of writing
4479 out the file *also* generates the information needed to
4480 support fast random access to the compressed file. */
4481 /* rescan_file will cause us to try all open_routines, so
4482 reset cfile's open_type */
4483 cf->open_type = WTAP_TYPE_AUTO;
4484 /* There are cases when SAVE_WITH_WTAP can result in new packets
4485 being written to the file, e.g ERF records
4486 In that case, we need to reload the whole file */
4488 if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) {
4489 if (cf_read(cf, TRUE) != CF_READ_OK) {
4490 /* The rescan failed; just close the file. Either
4491 a dialog was popped up for the failure, so the
4492 user knows what happened, or they stopped the
4493 rescan, in which case they know what happened. */
4494 /* XXX: This is inconsistent with normal open/reload behaviour. */
4500 if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4501 /* The rescan failed; just close the file. Either
4502 a dialog was popped up for the failure, so the
4503 user knows what happened, or they stopped the
4504 rescan, in which case they know what happened. */
4511 /* If we were told to discard the comments, do so. */
4512 if (discard_comments) {
4513 /* Remove SHB comment, if any. */
4514 wtap_write_shb_comment(cf->provider.wth, NULL);
4516 /* remove all user comments */
4517 for (framenum = 1; framenum <= cf->count; framenum++) {
4518 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4520 fdata->flags.has_phdr_comment = FALSE;
4521 fdata->flags.has_user_comment = FALSE;
4524 if (cf->provider.frames_user_comments) {
4525 g_tree_destroy(cf->provider.frames_user_comments);
4526 cf->provider.frames_user_comments = NULL;
4529 cf->packet_comment_count = 0;
4535 if (fname_new != NULL) {
4536 /* We were trying to write to a temporary file; get rid of it if it
4537 exists. (We don't care whether this fails, as, if it fails,
4538 there's not much we can do about it. I guess if it failed for
4539 a reason other than "it doesn't exist", we could report an
4540 error, so the user knows there's a junk file that they might
4541 want to clean up.) */
4542 ws_unlink(fname_new);
4545 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4546 return CF_WRITE_ERROR;
4550 cf_export_specified_packets(capture_file *cf, const char *fname,
4551 packet_range_t *range, guint save_format,
4552 gboolean compressed)
4554 gchar *fname_new = NULL;
4557 save_callback_args_t callback_args;
4558 GArray *shb_hdrs = NULL;
4559 wtapng_iface_descriptions_t *idb_inf = NULL;
4560 GArray *nrb_hdrs = NULL;
4563 packet_range_process_init(range);
4565 /* We're writing out specified packets from the specified capture
4566 file to another file. Even if all captured packets are to be
4567 written, don't special-case the operation - read each packet
4568 and then write it out if it's one of the specified ones. */
4570 /* XXX: what free's this shb_hdr? */
4571 shb_hdrs = wtap_file_get_shb_for_new_file(cf->provider.wth);
4572 idb_inf = wtap_file_get_idb_info(cf->provider.wth);
4573 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->provider.wth);
4575 /* Determine what file encapsulation type we should use. */
4576 encap = wtap_dump_file_encap_type(cf->linktypes);
4578 if (file_exists(fname)) {
4579 /* We're overwriting an existing file; write out to a new file,
4580 and, if that succeeds, rename the new file on top of the
4581 old file. That makes this a "safe save", so that we don't
4582 lose the old file if we have a problem writing out the new
4583 file. (If the existing file is the current capture file,
4584 we *HAVE* to do that, otherwise we're overwriting the file
4585 from which we're reading the packets that we're writing!) */
4586 fname_new = g_strdup_printf("%s~", fname);
4587 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4588 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4590 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4591 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4597 cfile_dump_open_failure_alert_box(fname, err, save_format);
4601 /* Add address resolution */
4602 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4604 /* Iterate through the list of packets, processing the packets we were
4607 XXX - we've already called "packet_range_process_init(range)", but
4608 "process_specified_records()" will do it again. Fortunately,
4609 that's harmless in this case, as we haven't done anything to
4610 "range" since we initialized it. */
4611 callback_args.pdh = pdh;
4612 callback_args.fname = fname;
4613 callback_args.file_type = save_format;
4614 switch (process_specified_records(cf, range, "Writing", "specified records",
4615 TRUE, save_record, &callback_args, TRUE)) {
4618 /* Completed successfully. */
4622 /* The user decided to abort the saving.
4623 If we're writing to a temporary file, remove it.
4624 XXX - should we do so even if we're not writing to a
4626 wtap_dump_close(pdh, &err);
4627 if (fname_new != NULL)
4628 ws_unlink(fname_new);
4629 return CF_WRITE_ABORTED;
4633 /* Error while saving.
4634 If we're writing to a temporary file, remove it. */
4635 if (fname_new != NULL)
4636 ws_unlink(fname_new);
4637 wtap_dump_close(pdh, &err);
4641 if (!wtap_dump_close(pdh, &err)) {
4642 cfile_close_failure_alert_box(fname, err);
4646 if (fname_new != NULL) {
4647 /* We wrote out to fname_new, and should rename it on top of
4648 fname; fname is now closed, so that should be possible even
4649 on Windows. Do the rename. */
4650 if (ws_rename(fname_new, fname) == -1) {
4651 /* Well, the rename failed. */
4652 cf_rename_failure_alert_box(fname, errno);
4660 if (fname_new != NULL) {
4661 /* We were trying to write to a temporary file; get rid of it if it
4662 exists. (We don't care whether this fails, as, if it fails,
4663 there's not much we can do about it. I guess if it failed for
4664 a reason other than "it doesn't exist", we could report an
4665 error, so the user knows there's a junk file that they might
4666 want to clean up.) */
4667 ws_unlink(fname_new);
4670 return CF_WRITE_ERROR;
4674 * XXX - whether we mention the source pathname, the target pathname,
4675 * or both depends on the error and on what we find if we look for
4676 * one or both of them.
4679 cf_rename_failure_alert_box(const char *filename, int err)
4681 gchar *display_basename;
4683 display_basename = g_filename_display_basename(filename);
4687 /* XXX - should check whether the source exists and, if not,
4688 report it as the problem and, if so, report the destination
4690 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4695 /* XXX - if we're doing a rename after a safe save, we should
4696 probably say something else. */
4697 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4702 /* XXX - this should probably mention both the source and destination
4704 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4705 display_basename, wtap_strerror(err));
4708 g_free(display_basename);
4711 /* Reload the current capture file. */
4713 cf_reload(capture_file *cf) {
4715 gboolean is_tempfile;
4718 /* If the file could be opened, "cf_open()" calls "cf_close()"
4719 to get rid of state for the old capture file before filling in state
4720 for the new capture file. "cf_close()" will remove the file if
4721 it's a temporary file; we don't want that to happen (for one thing,
4722 it'd prevent subsequent reopens from working). Remember whether it's
4723 a temporary file, mark it as not being a temporary file, and then
4724 reopen it as the type of file it was.
4726 Also, "cf_close()" will free "cf->filename", so we must make
4727 a copy of it first. */
4728 filename = g_strdup(cf->filename);
4729 is_tempfile = cf->is_tempfile;
4730 cf->is_tempfile = FALSE;
4731 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4732 switch (cf_read(cf, TRUE)) {
4736 /* Just because we got an error, that doesn't mean we were unable
4737 to read any of the file; we handle what we could get from the
4741 case CF_READ_ABORTED:
4742 /* The user bailed out of re-reading the capture file; the
4743 capture file has been closed - just free the capture file name
4744 string and return (without changing the last containing
4750 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4751 Instead, the file was left open, so we should restore "cf->is_tempfile"
4754 XXX - change the menu? Presumably "cf_open()" will do that;
4755 make sure it does! */
4756 cf->is_tempfile = is_tempfile;
4758 /* "cf_open()" made a copy of the file name we handed it, so
4759 we should free up our copy. */
4769 * indent-tabs-mode: nil
4772 * ex: set shiftwidth=2 tabstop=8 expandtab:
4773 * :indentSize=2:tabSize=8:noTabs=true: