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 #include <sys/types.h>
59 #ifdef HAVE_SYS_SOCKET_H
60 #include <sys/socket.h>
63 #ifdef HAVE_NETINET_IN_H
64 # include <netinet/in.h>
68 # include <winsock2.h>
69 # include <ws2tcpip.h>
72 static gboolean read_record(capture_file *cf, dfilter_t *dfcode,
73 epan_dissect_t *edt, column_info *cinfo, gint64 offset);
75 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
82 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
84 static void match_subtree_text(proto_node *node, gpointer data);
85 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
87 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
89 static match_result match_narrow(capture_file *cf, frame_data *fdata,
91 static match_result match_wide(capture_file *cf, frame_data *fdata,
93 static match_result match_binary(capture_file *cf, frame_data *fdata,
95 static match_result match_regex(capture_file *cf, frame_data *fdata,
97 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
99 static match_result match_marked(capture_file *cf, frame_data *fdata,
101 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
103 static gboolean find_packet(capture_file *cf,
104 match_result (*match_function)(capture_file *, frame_data *, void *),
105 void *criterion, search_direction dir);
107 static void cf_rename_failure_alert_box(const char *filename, int err);
108 static void ref_time_packets(capture_file *cf);
110 /* Seconds spent processing packets between pushing UI updates. */
111 #define PROGBAR_UPDATE_INTERVAL 0.150
113 /* Show the progress bar after this many seconds. */
114 #define PROGBAR_SHOW_DELAY 0.5
117 * We could probably use g_signal_...() instead of the callbacks below but that
118 * would require linking our CLI programs to libgobject and creating an object
119 * instance for the signals.
122 cf_callback_t cb_fct;
124 } cf_callback_data_t;
126 static GList *cf_callbacks = NULL;
129 cf_callback_invoke(int event, gpointer data)
131 cf_callback_data_t *cb;
132 GList *cb_item = cf_callbacks;
134 /* there should be at least one interested */
135 g_assert(cb_item != NULL);
137 while (cb_item != NULL) {
138 cb = (cf_callback_data_t *)cb_item->data;
139 cb->cb_fct(event, data, cb->user_data);
140 cb_item = g_list_next(cb_item);
146 cf_callback_add(cf_callback_t func, gpointer user_data)
148 cf_callback_data_t *cb;
150 cb = g_new(cf_callback_data_t,1);
152 cb->user_data = user_data;
154 cf_callbacks = g_list_prepend(cf_callbacks, cb);
158 cf_callback_remove(cf_callback_t func, gpointer user_data)
160 cf_callback_data_t *cb;
161 GList *cb_item = cf_callbacks;
163 while (cb_item != NULL) {
164 cb = (cf_callback_data_t *)cb_item->data;
165 if (cb->cb_fct == func && cb->user_data == user_data) {
166 cf_callbacks = g_list_remove(cf_callbacks, cb);
170 cb_item = g_list_next(cb_item);
173 g_assert_not_reached();
177 cf_timestamp_auto_precision(capture_file *cf)
181 /* don't try to get the file's precision if none is opened */
182 if (cf->state == FILE_CLOSED) {
186 /* Set the column widths of those columns that show the time in
187 "command-line-specified" format. */
188 for (i = 0; i < cf->cinfo.num_cols; i++) {
189 if (col_has_time_fmt(&cf->cinfo, i)) {
190 packet_list_resize_column(i);
196 cf_get_computed_elapsed(capture_file *cf)
198 return cf->computed_elapsed;
202 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
205 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
210 g_get_current_time(&time_now);
212 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
213 time_now.tv_usec - start_time->tv_usec;
215 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
218 static const nstime_t *
219 ws_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
221 if (prov->prev_dis && prov->prev_dis->num == frame_num)
222 return &prov->prev_dis->abs_ts;
224 if (prov->prev_cap && prov->prev_cap->num == frame_num)
225 return &prov->prev_cap->abs_ts;
228 frame_data *fd = frame_data_sequence_find(prov->frames, frame_num);
230 return (fd) ? &fd->abs_ts : NULL;
237 ws_epan_new(capture_file *cf)
239 static const struct packet_provider_funcs funcs = {
241 cap_file_provider_get_interface_name,
242 cap_file_provider_get_interface_description,
243 cap_file_provider_get_user_comment
246 return epan_new(&cf->provider, &funcs);
250 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
255 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
259 /* The open succeeded. Close whatever capture file we had open,
260 and fill in the information for this file. */
263 /* Initialize the record metadata. */
264 wtap_rec_init(&cf->rec);
266 /* XXX - we really want to initialize this after we've read all
267 the packets, so we know how much we'll ultimately need. */
268 ws_buffer_init(&cf->buf, 1500);
270 /* Create new epan session for dissection.
271 * (The old one was freed in cf_close().)
273 cf->epan = ws_epan_new(cf);
275 /* We're about to start reading the file. */
276 cf->state = FILE_READ_IN_PROGRESS;
278 cf->provider.wth = wth;
281 /* Set the file name because we need it to set the follow stream filter.
282 XXX - is that still true? We need it for other reasons, though,
284 cf->filename = g_strdup(fname);
286 /* Indicate whether it's a permanent or temporary file. */
287 cf->is_tempfile = is_tempfile;
289 /* No user changes yet. */
290 cf->unsaved_changes = FALSE;
292 cf->computed_elapsed = 0;
294 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
295 cf->open_type = type;
296 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
298 cf->packet_comment_count = 0;
299 cf->displayed_count = 0;
300 cf->marked_count = 0;
301 cf->ignored_count = 0;
302 cf->ref_time_count = 0;
303 cf->drops_known = FALSE;
305 cf->snap = wtap_snapshot_length(cf->provider.wth);
307 /* Allocate a frame_data_sequence for the frames in this file */
308 cf->provider.frames = new_frame_data_sequence();
310 nstime_set_zero(&cf->elapsed_time);
311 cf->provider.ref = NULL;
312 cf->provider.prev_dis = NULL;
313 cf->provider.prev_cap = NULL;
316 packet_list_queue_draw();
317 cf_callback_invoke(cf_cb_file_opened, cf);
319 if ((cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER)
320 || (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_PEM)) {
321 /* tell the BER dissector the file name */
322 ber_set_filename(cf->filename);
325 wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name);
326 wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
331 cfile_open_failure_alert_box(fname, *err, err_info);
336 * Add an encapsulation type to cf->linktypes.
339 cf_add_encapsulation_type(capture_file *cf, int encap)
343 for (i = 0; i < cf->linktypes->len; i++) {
344 if (g_array_index(cf->linktypes, gint, i) == encap)
345 return; /* it's already there */
347 /* It's not already there - add it. */
348 g_array_append_val(cf->linktypes, encap);
351 /* Reset everything to a pristine state */
353 cf_close(capture_file *cf)
355 cf->stop_flag = FALSE;
356 if (cf->state == FILE_CLOSED)
357 return; /* Nothing to do */
359 /* Die if we're in the middle of reading a file. */
360 g_assert(cf->state != FILE_READ_IN_PROGRESS);
362 cf_callback_invoke(cf_cb_file_closing, cf);
364 /* close things, if not already closed before */
365 color_filters_cleanup();
367 if (cf->provider.wth) {
368 wtap_close(cf->provider.wth);
369 cf->provider.wth = NULL;
371 /* We have no file open... */
372 if (cf->filename != NULL) {
373 /* If it's a temporary file, remove it. */
375 ws_unlink(cf->filename);
376 g_free(cf->filename);
379 /* ...which means we have no changes to that file to save. */
380 cf->unsaved_changes = FALSE;
382 /* no open_routine type */
383 cf->open_type = WTAP_TYPE_AUTO;
385 /* Clean up the record metadata. */
386 wtap_rec_cleanup(&cf->rec);
388 /* Free up the packet buffer. */
389 ws_buffer_free(&cf->buf);
391 dfilter_free(cf->rfcode);
393 if (cf->provider.frames != NULL) {
394 free_frame_data_sequence(cf->provider.frames);
395 cf->provider.frames = NULL;
397 if (cf->provider.frames_user_comments) {
398 g_tree_destroy(cf->provider.frames_user_comments);
399 cf->provider.frames_user_comments = NULL;
401 cf_unselect_packet(cf); /* nothing to select */
402 cf->first_displayed = 0;
403 cf->last_displayed = 0;
405 /* No frames, no frame selected, no field in that frame selected. */
407 cf->current_frame = 0;
409 cf->finfo_selected = NULL;
411 /* No frame link-layer types, either. */
412 if (cf->linktypes != NULL) {
413 g_array_free(cf->linktypes, TRUE);
414 cf->linktypes = NULL;
417 /* Clear the packet list. */
418 packet_list_freeze();
423 nstime_set_zero(&cf->elapsed_time);
425 reset_tap_listeners();
430 /* We have no file open. */
431 cf->state = FILE_CLOSED;
433 cf_callback_invoke(cf_cb_file_closed, cf);
437 * TRUE if the progress dialog doesn't exist and it looks like we'll
438 * take > 2s to load, FALSE otherwise.
440 static inline gboolean
441 progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
445 if (progdlg) return FALSE;
446 elapsed = g_timer_elapsed(prog_timer, NULL);
447 if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
448 || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
455 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
459 progbar_val = (gfloat) file_pos / (gfloat) size;
460 if (progbar_val > 1.0) {
462 /* The file probably grew while we were reading it.
463 * Update file size, and try again.
465 size = wtap_file_size(cf->provider.wth, NULL);
468 progbar_val = (gfloat) file_pos / (gfloat) size;
470 /* If it's still > 1, either "wtap_file_size()" failed (in which
471 * case there's not much we can do about it), or the file
472 * *shrank* (in which case there's not much we can do about
473 * it); just clip the progress value at 1.0.
475 if (progbar_val > 1.0f)
479 g_snprintf(status_str, status_size,
480 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
481 file_pos / 1024, size / 1024);
487 cf_read(capture_file *cf, gboolean reloading)
490 gchar *err_info = NULL;
492 progdlg_t *volatile progbar = NULL;
493 GTimer *prog_timer = g_timer_new();
497 volatile gboolean create_proto_tree;
500 volatile gboolean is_read_aborted = FALSE;
502 /* Compile the current display filter.
503 * We assume this will not fail since cf->dfilter is only set in
504 * cf_filter IFF the filter was valid.
506 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
507 g_assert(!cf->dfilter || (compiled && dfcode));
509 /* Get the union of the flags for all tap listeners. */
510 tap_flags = union_of_tap_listener_flags();
513 * Determine whether we need to create a protocol tree.
516 * we're going to apply a display filter;
518 * one of the tap listeners is going to apply a filter;
520 * one of the tap listeners requires a protocol tree;
522 * a postdissector wants field values or protocols on
526 (dfcode != NULL || have_filtering_tap_listeners() ||
527 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
529 reset_tap_listeners();
531 name_ptr = g_filename_display_basename(cf->filename);
534 cf_callback_invoke(cf_cb_file_reload_started, cf);
536 cf_callback_invoke(cf_cb_file_read_started, cf);
538 /* Record whether the file is compressed.
539 XXX - do we know this at open time? */
540 cf->iscompressed = wtap_iscompressed(cf->provider.wth);
542 /* The packet list window will be empty until the file is completly loaded */
543 packet_list_freeze();
545 cf->stop_flag = FALSE;
546 g_get_current_time(&start_time);
548 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
558 gchar status_str[100];
562 /* If any tap listeners require the columns, construct them. */
563 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
565 /* Find the size of the file. */
566 size = wtap_file_size(cf->provider.wth, NULL);
568 g_timer_start(prog_timer);
570 while ((wtap_read(cf->provider.wth, &err, &err_info, &data_offset))) {
573 file_pos = wtap_read_so_far(cf->provider.wth);
575 /* Create the progress bar if necessary. */
576 if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
577 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
579 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
580 TRUE, &cf->stop_flag, &start_time, progbar_val);
582 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
583 TRUE, &cf->stop_flag, &start_time, progbar_val);
587 * Update the progress bar, but do it only after
588 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
589 * and packets_bar_update will likely trigger UI paint events, which
590 * might take a while depending on the platform and display. Reset
591 * our timer *after* painting.
593 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
594 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
595 /* update the packet bar content on the first run or frequently on very large files */
596 update_progress_dlg(progbar, progbar_val, status_str);
597 compute_elapsed(cf, &start_time);
598 packets_bar_update();
599 g_timer_start(prog_timer);
603 if (cf->state == FILE_READ_ABORTED) {
604 /* Well, the user decided to exit Wireshark. Break out of the
605 loop, and let the code below (which is called even if there
606 aren't any packets left to read) exit. */
607 is_read_aborted = TRUE;
611 /* Well, the user decided to abort the read. He/She will be warned and
612 it might be enough for him/her to work with the already loaded
614 This is especially true for very large capture files, where you don't
615 want to wait loading the whole file (which may last minutes or even
616 hours even on fast machines) just to see that it was the wrong file. */
619 read_record(cf, dfcode, &edt, cinfo, data_offset);
622 CATCH(OutOfMemoryError) {
623 simple_message_box(ESD_TYPE_ERROR, NULL,
624 "More information and workarounds can be found at\n"
625 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
626 "Sorry, but Wireshark has run out of memory and has to terminate now.");
628 /* Could we close the current capture and free up memory from that? */
630 /* we have to terminate, as we cannot recover from the memory error */
636 /* Free the display name */
639 /* Cleanup and release all dfilter resources */
640 dfilter_free(dfcode);
642 epan_dissect_cleanup(&edt);
644 /* We're done reading the file; destroy the progress bar if it was created. */
646 destroy_progress_dlg(progbar);
647 g_timer_destroy(prog_timer);
649 /* We're done reading sequentially through the file. */
650 cf->state = FILE_READ_DONE;
652 /* Close the sequential I/O side, to free up memory it requires. */
653 wtap_sequential_close(cf->provider.wth);
655 /* Allow the protocol dissectors to free up memory that they
656 * don't need after the sequential run-through of the packets. */
657 postseq_cleanup_all_protocols();
659 /* compute the time it took to load the file */
660 compute_elapsed(cf, &start_time);
662 /* Set the file encapsulation type now; we don't know what it is until
663 we've looked at all the packets, as we don't know until then whether
664 there's more than one type (and thus whether it's
665 WTAP_ENCAP_PER_PACKET). */
666 cf->lnk_t = wtap_file_encap(cf->provider.wth);
668 cf->current_frame = frame_data_sequence_find(cf->provider.frames, cf->first_displayed);
673 cf_callback_invoke(cf_cb_file_reload_finished, cf);
675 cf_callback_invoke(cf_cb_file_read_finished, cf);
677 /* If we have any displayed packets to select, select the first of those
678 packets by making the first row the selected row. */
679 if (cf->first_displayed != 0) {
680 packet_list_select_first_row();
683 if (is_read_aborted) {
685 * Well, the user decided to exit Wireshark while reading this *offline*
686 * capture file (Live captures are handled by something like
687 * cf_continue_tail). Clean up accordingly.
690 return CF_READ_ABORTED;
694 simple_message_box(ESD_TYPE_WARN, NULL,
695 "The remaining packets in the file were discarded.\n"
697 "As a lot of packets from the original file will be missing,\n"
698 "remember to be careful when saving the current content to a file.\n",
699 "File loading was cancelled.");
700 return CF_READ_ERROR;
704 /* Put up a message box noting that the read failed somewhere along
705 the line. Don't throw out the stuff we managed to read, though,
707 cfile_read_failure_alert_box(NULL, err, err_info);
708 return CF_READ_ERROR;
715 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
718 volatile int newly_displayed_packets = 0;
721 gboolean create_proto_tree;
725 /* Compile the current display filter.
726 * We assume this will not fail since cf->dfilter is only set in
727 * cf_filter IFF the filter was valid.
729 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
730 g_assert(!cf->dfilter || (compiled && dfcode));
732 /* Get the union of the flags for all tap listeners. */
733 tap_flags = union_of_tap_listener_flags();
736 * Determine whether we need to create a protocol tree.
739 * we're going to apply a display filter;
741 * one of the tap listeners is going to apply a filter;
743 * one of the tap listeners requires a protocol tree;
745 * a postdissector wants field values or protocols on
749 (dfcode != NULL || have_filtering_tap_listeners() ||
750 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
754 /* Don't freeze/thaw the list when doing live capture */
755 /*packet_list_freeze();*/
757 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
759 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
762 gint64 data_offset = 0;
765 /* If any tap listeners require the columns, construct them. */
766 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
768 while (to_read != 0) {
769 wtap_cleareof(cf->provider.wth);
770 if (!wtap_read(cf->provider.wth, err, &err_info, &data_offset)) {
773 if (cf->state == FILE_READ_ABORTED) {
774 /* Well, the user decided to exit Wireshark. Break out of the
775 loop, and let the code below (which is called even if there
776 aren't any packets left to read) exit. */
779 if (read_record(cf, dfcode, &edt, (column_info *) cinfo, data_offset)) {
780 newly_displayed_packets++;
785 CATCH(OutOfMemoryError) {
786 simple_message_box(ESD_TYPE_ERROR, NULL,
787 "More information and workarounds can be found at\n"
788 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
789 "Sorry, but Wireshark has run out of memory and has to terminate now.");
791 /* Could we close the current capture and free up memory from that? */
792 return CF_READ_ABORTED;
794 /* we have to terminate, as we cannot recover from the memory error */
800 /* Update the file encapsulation; it might have changed based on the
801 packets we've read. */
802 cf->lnk_t = wtap_file_encap(cf->provider.wth);
804 /* Cleanup and release all dfilter resources */
805 dfilter_free(dfcode);
807 epan_dissect_cleanup(&edt);
809 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
810 cf->count, cf->state, *err);*/
812 /* Don't freeze/thaw the list when doing live capture */
813 /*packet_list_thaw();*/
814 /* With the new packet list the first packet
815 * isn't automatically selected.
817 if (!cf->current_frame)
818 packet_list_select_first_row();
820 /* moving to the end of the packet list - if the user requested so and
821 we have some new packets. */
822 if (newly_displayed_packets && cf->count != 0)
823 packet_list_moveto_end();
825 if (cf->state == FILE_READ_ABORTED) {
826 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
827 so that our caller can kill off the capture child process;
828 this will cause an EOF on the pipe from the child, so
829 "cf_finish_tail()" will be called, and it will clean up
831 return CF_READ_ABORTED;
832 } else if (*err != 0) {
833 /* We got an error reading the capture file.
834 XXX - pop up a dialog box instead? */
835 if (err_info != NULL) {
836 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
837 wtap_strerror(*err), cf->filename, err_info);
840 g_warning("Error \"%s\" while reading \"%s\"",
841 wtap_strerror(*err), cf->filename);
843 return CF_READ_ERROR;
849 cf_fake_continue_tail(capture_file *cf) {
850 cf->state = FILE_READ_DONE;
854 cf_finish_tail(capture_file *cf, int *err)
861 gboolean create_proto_tree;
865 /* Compile the current display filter.
866 * We assume this will not fail since cf->dfilter is only set in
867 * cf_filter IFF the filter was valid.
869 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
870 g_assert(!cf->dfilter || (compiled && dfcode));
872 /* Get the union of the flags for all tap listeners. */
873 tap_flags = union_of_tap_listener_flags();
875 /* If any tap listeners require the columns, construct them. */
876 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
879 * Determine whether we need to create a protocol tree.
882 * we're going to apply a display filter;
884 * one of the tap listeners is going to apply a filter;
886 * one of the tap listeners requires a protocol tree;
888 * a postdissector wants field values or protocols on
892 (dfcode != NULL || have_filtering_tap_listeners() ||
893 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
895 if (cf->provider.wth == NULL) {
897 return CF_READ_ERROR;
900 /* Don't freeze/thaw the list when doing live capture */
901 /*packet_list_freeze();*/
903 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
905 while ((wtap_read(cf->provider.wth, err, &err_info, &data_offset))) {
906 if (cf->state == FILE_READ_ABORTED) {
907 /* Well, the user decided to abort the read. Break out of the
908 loop, and let the code below (which is called even if there
909 aren't any packets left to read) exit. */
912 read_record(cf, dfcode, &edt, cinfo, data_offset);
915 /* Cleanup and release all dfilter resources */
916 dfilter_free(dfcode);
918 epan_dissect_cleanup(&edt);
920 /* Don't freeze/thaw the list when doing live capture */
921 /*packet_list_thaw();*/
923 if (cf->state == FILE_READ_ABORTED) {
924 /* Well, the user decided to abort the read. We're only called
925 when the child capture process closes the pipe to us (meaning
926 it's probably exited), so we can just close the capture
927 file; we return CF_READ_ABORTED so our caller can do whatever
928 is appropriate when that happens. */
930 return CF_READ_ABORTED;
933 /* We're done reading sequentially through the file. */
934 cf->state = FILE_READ_DONE;
936 /* We're done reading sequentially through the file; close the
937 sequential I/O side, to free up memory it requires. */
938 wtap_sequential_close(cf->provider.wth);
940 /* Allow the protocol dissectors to free up memory that they
941 * don't need after the sequential run-through of the packets. */
942 postseq_cleanup_all_protocols();
944 /* Update the file encapsulation; it might have changed based on the
945 packets we've read. */
946 cf->lnk_t = wtap_file_encap(cf->provider.wth);
948 /* Update the details in the file-set dialog, as the capture file
949 * has likely grown since we first stat-ed it */
950 fileset_update_file(cf->filename);
953 /* We got an error reading the capture file.
954 XXX - pop up a dialog box? */
955 if (err_info != NULL) {
956 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
957 wtap_strerror(*err), cf->filename, err_info);
960 g_warning("Error \"%s\" while reading \"%s\"",
961 wtap_strerror(*err), cf->filename);
963 return CF_READ_ERROR;
968 #endif /* HAVE_LIBPCAP */
971 cf_get_display_name(capture_file *cf)
975 /* Return a name to use in displays */
976 if (!cf->is_tempfile) {
977 /* Get the last component of the file name, and use that. */
979 displayname = g_filename_display_basename(cf->filename);
981 displayname=g_strdup("(No file)");
984 /* The file we read is a temporary file from a live capture or
985 a merge operation; we don't mention its name, but, if it's
986 from a capture, give the source of the capture. */
988 displayname = g_strdup(cf->source);
990 displayname = g_strdup("(Untitled)");
996 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1002 cf->source = g_strdup(source);
1004 cf->source = g_strdup("");
1008 const gchar *cf_get_tempfile_source(capture_file *cf) {
1016 /* XXX - use a macro instead? */
1018 cf_get_packet_count(capture_file *cf)
1023 /* XXX - use a macro instead? */
1025 cf_is_tempfile(capture_file *cf)
1027 return cf->is_tempfile;
1030 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1032 cf->is_tempfile = is_tempfile;
1036 /* XXX - use a macro instead? */
1037 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1039 cf->drops_known = drops_known;
1042 /* XXX - use a macro instead? */
1043 void cf_set_drops(capture_file *cf, guint32 drops)
1048 /* XXX - use a macro instead? */
1049 gboolean cf_get_drops_known(capture_file *cf)
1051 return cf->drops_known;
1054 /* XXX - use a macro instead? */
1055 guint32 cf_get_drops(capture_file *cf)
1060 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1062 cf->rfcode = rfcode;
1066 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1067 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1068 wtap_rec *rec, const guint8 *buf, gboolean add_to_packet_list)
1070 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1071 &cf->provider.ref, cf->provider.prev_dis);
1072 cf->provider.prev_cap = fdata;
1074 if (dfcode != NULL) {
1075 epan_dissect_prime_with_dfilter(edt, dfcode);
1078 /* Prepare coloring rules, this ensures that display filter rules containing
1079 * frame.color_rule references are still processed.
1080 * TODO: actually detect that situation or maybe apply other optimizations? */
1081 if (edt->tree && color_filters_used()) {
1082 color_filters_prime_edt(edt);
1083 fdata->flags.need_colorize = 1;
1087 if (!fdata->flags.visited) {
1088 /* This is the first pass, so prime the epan_dissect_t with the
1089 hfids postdissectors want on the first pass. */
1090 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1093 /* Dissect the frame. */
1094 epan_dissect_run_with_taps(edt, cf->cd_t, rec,
1095 frame_tvbuff_new(&cf->provider, fdata, buf),
1098 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1099 if (dfcode != NULL) {
1100 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1102 if (fdata->flags.passed_dfilter) {
1103 /* This frame passed the display filter but it may depend on other
1104 * (potentially not displayed) frames. Find those frames and mark them
1107 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
1110 fdata->flags.passed_dfilter = 1;
1112 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1113 cf->displayed_count++;
1115 if (add_to_packet_list) {
1116 /* We fill the needed columns from new_packet_list */
1117 packet_list_append(cinfo, fdata);
1120 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1122 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1123 cf->provider.prev_dis = fdata;
1125 /* If we haven't yet seen the first frame, this is it. */
1126 if (cf->first_displayed == 0)
1127 cf->first_displayed = fdata->num;
1129 /* This is the last frame we've seen so far. */
1130 cf->last_displayed = fdata->num;
1133 epan_dissect_reset(edt);
1137 * Read in a new record.
1138 * Returns TRUE if the packet was added to the packet (record) list,
1142 read_record(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1143 column_info *cinfo, gint64 offset)
1145 wtap_rec *rec = wtap_get_rec(cf->provider.wth);
1146 const guint8 *buf = wtap_get_buf_ptr(cf->provider.wth);
1149 gboolean passed = TRUE;
1150 gboolean added = FALSE;
1152 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1153 it's not already there.
1154 XXX - yes, this is O(N), so if every packet had a different
1155 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1156 there are probably going to be a small number of encapsulation types
1158 if (rec->rec_type == REC_TYPE_PACKET) {
1159 cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap);
1162 /* The frame number of this packet, if we add it to the set of frames,
1163 would be one more than the count of frames in the file so far. */
1164 frame_data_init(&fdlocal, cf->count + 1, rec, offset, cf->cum_bytes);
1167 epan_dissect_t rf_edt;
1169 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1170 epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
1171 epan_dissect_run(&rf_edt, cf->cd_t, rec,
1172 frame_tvbuff_new(&cf->provider, &fdlocal, buf),
1174 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1175 epan_dissect_cleanup(&rf_edt);
1181 /* This does a shallow copy of fdlocal, which is good enough. */
1182 fdata = frame_data_sequence_add(cf->provider.frames, &fdlocal);
1185 if (rec->opt_comment != NULL)
1186 cf->packet_comment_count++;
1187 cf->f_datalen = offset + fdlocal.cap_len;
1189 if (!cf->redissecting) {
1190 add_packet_to_packet_list(fdata, cf, edt, dfcode,
1191 cinfo, rec, buf, TRUE);
1199 typedef struct _callback_data_t {
1202 GTimeVal start_time;
1210 merge_callback(merge_event event, int num _U_,
1211 const merge_in_file_t in_files[], const guint in_file_count,
1215 callback_data_t *cb_data = (callback_data_t*) data;
1217 g_assert(cb_data != NULL);
1221 case MERGE_EVENT_INPUT_FILES_OPENED:
1225 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1229 case MERGE_EVENT_READY_TO_MERGE:
1230 /* Get the sum of the sizes of all the files. */
1231 for (i = 0; i < in_file_count; i++)
1232 cb_data->f_len += in_files[i].size;
1234 cb_data->prog_timer = g_timer_new();
1235 g_timer_start(cb_data->prog_timer);
1237 g_get_current_time(&cb_data->start_time);
1240 case MERGE_EVENT_RECORD_WAS_READ:
1242 /* Create the progress bar if necessary.
1243 We check on every iteration of the loop, so that it takes no
1244 longer than the standard time to create it (otherwise, for a
1245 large file, we might take considerably longer than that standard
1246 time in order to get to the next progress bar step). */
1247 if (cb_data->progbar == NULL) {
1248 cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1249 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1253 * Update the progress bar, but do it only after
1254 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1255 * and packets_bar_update will likely trigger UI paint events, which
1256 * might take a while depending on the platform and display. Reset
1257 * our timer *after* painting.
1259 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1261 gint64 file_pos = 0;
1262 /* Get the sum of the seek positions in all of the files. */
1263 for (i = 0; i < in_file_count; i++)
1264 file_pos += wtap_read_so_far(in_files[i].wth);
1266 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1267 if (progbar_val > 1.0f) {
1268 /* Some file probably grew while we were reading it.
1269 That "shouldn't happen", so we'll just clip the progress
1274 if (cb_data->progbar != NULL) {
1275 gchar status_str[100];
1276 g_snprintf(status_str, sizeof(status_str),
1277 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1278 file_pos / 1024, cb_data->f_len / 1024);
1279 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1281 g_timer_start(cb_data->prog_timer);
1286 case MERGE_EVENT_DONE:
1287 /* We're done merging the files; destroy the progress bar if it was created. */
1288 if (cb_data->progbar != NULL)
1289 destroy_progress_dlg(cb_data->progbar);
1290 g_timer_destroy(cb_data->prog_timer);
1294 return cb_data->stop_flag;
1300 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1301 int in_file_count, char *const *in_filenames,
1302 int file_type, gboolean do_append)
1305 gchar *err_info = NULL;
1307 guint32 err_framenum;
1308 merge_result status;
1309 merge_progress_callback_t cb;
1310 callback_data_t *cb_data = g_new0(callback_data_t, 1);
1312 /* prepare our callback routine */
1313 cb_data->pd_window = pd_window;
1314 cb.callback_func = merge_callback;
1317 cf_callback_invoke(cf_cb_file_merge_started, NULL);
1319 /* merge the files */
1320 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1321 (const char *const *) in_filenames,
1322 in_file_count, do_append,
1323 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1324 "Wireshark", &cb, &err, &err_info,
1325 &err_fileno, &err_framenum);
1333 case MERGE_USER_ABORTED:
1334 /* this isn't really an error, though we will return CF_ERROR later */
1337 case MERGE_ERR_CANT_OPEN_INFILE:
1338 cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
1341 case MERGE_ERR_CANT_OPEN_OUTFILE:
1342 cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
1345 case MERGE_ERR_CANT_READ_INFILE:
1346 cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
1349 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1350 simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
1351 err_framenum, in_filenames[err_fileno]);
1354 case MERGE_ERR_CANT_WRITE_OUTFILE:
1355 cfile_write_failure_alert_box(in_filenames[err_fileno],
1356 *out_filenamep, err, err_info,
1357 err_framenum, file_type);
1360 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1361 cfile_close_failure_alert_box(*out_filenamep, err);
1365 simple_error_message_box("Unknown merge_files error %d", status);
1369 cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1371 if (status != MERGE_OK) {
1372 /* Callers aren't expected to treat an error or an explicit abort
1373 differently - we put up error dialogs ourselves, so they don't
1381 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1383 const char *filter_new = dftext ? dftext : "";
1384 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1387 GTimeVal start_time;
1389 /* if new filter equals old one, do nothing unless told to do so */
1390 if (!force && strcmp(filter_new, filter_old) == 0) {
1396 if (dftext == NULL) {
1397 /* The new filter is an empty filter (i.e., display all packets).
1398 * so leave dfcode==NULL
1402 * We have a filter; make a copy of it (as we'll be saving it),
1403 * and try to compile it.
1405 dftext = g_strdup(dftext);
1406 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1407 /* The attempt failed; report an error. */
1408 simple_message_box(ESD_TYPE_ERROR, NULL,
1409 "See the help for a description of the display filter syntax.",
1410 "\"%s\" isn't a valid display filter: %s",
1418 if (dfcode == NULL) {
1419 /* Yes - free the filter text, and set it to null. */
1425 /* We have a valid filter. Replace the current filter. */
1426 g_free(cf->dfilter);
1427 cf->dfilter = dftext;
1428 g_get_current_time(&start_time);
1431 /* Now rescan the packet list, applying the new filter, but not
1432 throwing away information constructed on a previous pass. */
1433 if (cf->state != FILE_CLOSED) {
1434 if (dftext == NULL) {
1435 rescan_packets(cf, "Resetting", "Filter", FALSE);
1437 rescan_packets(cf, "Filtering", dftext, FALSE);
1441 /* Cleanup and release all dfilter resources */
1442 dfilter_free(dfcode);
1448 cf_reftime_packets(capture_file *cf)
1450 ref_time_packets(cf);
1454 cf_redissect_packets(capture_file *cf)
1456 if (cf->state != FILE_CLOSED) {
1457 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1462 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1463 wtap_rec *rec, Buffer *buf)
1468 if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) {
1469 cfile_read_failure_alert_box(cf->filename, err, err_info);
1476 cf_read_record(capture_file *cf, frame_data *fdata)
1478 return cf_read_record_r(cf, fdata, &cf->rec, &cf->buf);
1481 /* Rescan the list of packets, reconstructing the CList.
1483 "action" describes why we're doing this; it's used in the progress
1486 "action_item" describes what we're doing; it's used in the progress
1489 "redissect" is TRUE if we need to make the dissectors reconstruct
1490 any state information they have (because a preference that affects
1491 some dissector has changed, meaning some dissector might construct
1492 its state differently from the way it was constructed the last time). */
1494 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1496 /* Rescan packets new packet list */
1499 progdlg_t *progbar = NULL;
1500 GTimer *prog_timer = g_timer_new();
1502 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1503 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1504 gboolean selected_frame_seen;
1506 GTimeVal start_time;
1507 gchar status_str[100];
1511 gboolean create_proto_tree;
1513 gboolean add_to_packet_list = FALSE;
1515 guint32 frames_count;
1517 /* Compile the current display filter.
1518 * We assume this will not fail since cf->dfilter is only set in
1519 * cf_filter IFF the filter was valid.
1521 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1522 g_assert(!cf->dfilter || (compiled && dfcode));
1524 /* Get the union of the flags for all tap listeners. */
1525 tap_flags = union_of_tap_listener_flags();
1527 /* If any tap listeners require the columns, construct them. */
1528 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1531 * Determine whether we need to create a protocol tree.
1534 * we're going to apply a display filter;
1536 * one of the tap listeners is going to apply a filter;
1538 * one of the tap listeners requires a protocol tree;
1540 * we're redissecting and a postdissector wants field
1541 * values or protocols on the first pass.
1544 (dfcode != NULL || have_filtering_tap_listeners() ||
1545 (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1546 (redissect && postdissectors_want_hfids()));
1548 reset_tap_listeners();
1549 /* Which frame, if any, is the currently selected frame?
1550 XXX - should the selected frame or the focus frame be the "current"
1551 frame, that frame being the one from which "Find Frame" searches
1553 selected_frame = cf->current_frame;
1555 /* Mark frame num as not found */
1556 selected_frame_num = -1;
1558 /* Freeze the packet list while we redo it, so we don't get any
1559 screen updates while it happens. */
1560 packet_list_freeze();
1563 /* We need to re-initialize all the state information that protocols
1564 keep, because some preference that controls a dissector has changed,
1565 which might cause the state information to be constructed differently
1566 by that dissector. */
1568 /* We might receive new packets while redissecting, and we don't
1569 want to dissect those before their time. */
1570 cf->redissecting = TRUE;
1572 /* 'reset' dissection session */
1573 epan_free(cf->epan);
1574 if (cf->edt && cf->edt->pi.fd) {
1575 /* All pointers in "per frame proto data" for the currently selected
1576 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1577 Free them here to avoid unintended usage in packet_list_clear(). */
1578 frame_data_destroy(cf->edt->pi.fd);
1580 cf->epan = ws_epan_new(cf);
1581 cf->cinfo.epan = cf->epan;
1583 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1584 called via epan_new() / init_dissection() when reloading Lua plugins. */
1585 if (!create_proto_tree && have_filtering_tap_listeners()) {
1586 create_proto_tree = TRUE;
1589 /* We need to redissect the packets so we have to discard our old
1590 * packet list store. */
1591 packet_list_clear();
1592 add_to_packet_list = TRUE;
1595 /* We don't yet know which will be the first and last frames displayed. */
1596 cf->first_displayed = 0;
1597 cf->last_displayed = 0;
1599 /* We currently don't display any packets */
1600 cf->displayed_count = 0;
1602 /* Iterate through the list of frames. Call a routine for each frame
1603 to check whether it should be displayed and, if so, add it to
1604 the display list. */
1605 cf->provider.ref = NULL;
1606 cf->provider.prev_dis = NULL;
1607 cf->provider.prev_cap = NULL;
1610 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1612 g_timer_start(prog_timer);
1613 /* Count of packets at which we've looked. */
1615 /* Progress so far. */
1618 cf->stop_flag = FALSE;
1619 g_get_current_time(&start_time);
1621 /* no previous row yet */
1622 prev_frame_num = -1;
1625 preceding_frame_num = -1;
1626 preceding_frame = NULL;
1627 following_frame_num = -1;
1628 following_frame = NULL;
1630 selected_frame_seen = FALSE;
1632 frames_count = cf->count;
1634 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1636 for (framenum = 1; framenum <= frames_count; framenum++) {
1637 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1639 /* Create the progress bar if necessary.
1640 We check on every iteration of the loop, so that it takes no
1641 longer than the standard time to create it (otherwise, for a
1642 large file, we might take considerably longer than that standard
1643 time in order to get to the next progress bar step). */
1644 if (progbar == NULL)
1645 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1651 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1652 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1653 * likely trigger UI paint events, which might take a while depending on
1654 * the platform and display. Reset our timer *after* painting.
1656 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1657 /* let's not divide by zero. I should never be started
1658 * with count == 0, so let's assert that
1660 g_assert(cf->count > 0);
1661 progbar_val = (gfloat) count / frames_count;
1663 if (progbar != NULL) {
1664 g_snprintf(status_str, sizeof(status_str),
1665 "%4u of %u frames", count, frames_count);
1666 update_progress_dlg(progbar, progbar_val, status_str);
1669 g_timer_start(prog_timer);
1672 if (cf->stop_flag) {
1673 /* Well, the user decided to abort the filtering. Just stop.
1675 XXX - go back to the previous filter? Users probably just
1676 want not to wait for a filtering operation to finish;
1677 unless we cancel by having no filter, reverting to the
1678 previous filter will probably be even more expensive than
1679 continuing the filtering, as it involves going back to the
1680 beginning and filtering, and even with no filter we currently
1681 have to re-generate the entire clist, which is also expensive.
1683 I'm not sure what Network Monitor does, but it doesn't appear
1684 to give you an unfiltered display if you cancel. */
1691 /* Since all state for the frame was destroyed, mark the frame
1692 * as not visited, free the GSList referring to the state
1693 * data (the per-frame data itself was freed by
1694 * "init_dissection()"), and null out the GSList pointer. */
1695 frame_data_reset(fdata);
1696 frames_count = cf->count;
1699 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1700 fdata->flags.dependent_of_displayed = 0;
1702 if (!cf_read_record(cf, fdata))
1703 break; /* error reading the frame */
1705 /* If the previous frame is displayed, and we haven't yet seen the
1706 selected frame, remember that frame - it's the closest one we've
1707 yet seen before the selected frame. */
1708 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1709 preceding_frame_num = prev_frame_num;
1710 preceding_frame = prev_frame;
1713 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1715 ws_buffer_start_ptr(&cf->buf),
1716 add_to_packet_list);
1718 /* If this frame is displayed, and this is the first frame we've
1719 seen displayed after the selected frame, remember this frame -
1720 it's the closest one we've yet seen at or after the selected
1722 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1723 following_frame_num = fdata->num;
1724 following_frame = fdata;
1726 if (fdata == selected_frame) {
1727 selected_frame_seen = TRUE;
1728 if (fdata->flags.passed_dfilter)
1729 selected_frame_num = fdata->num;
1732 /* Remember this frame - it'll be the previous frame
1733 on the next pass through the loop. */
1734 prev_frame_num = fdata->num;
1738 epan_dissect_cleanup(&edt);
1740 /* We are done redissecting the packet list. */
1741 cf->redissecting = FALSE;
1744 frames_count = cf->count;
1745 /* Clear out what remains of the visited flags and per-frame data
1748 XXX - that may cause various forms of bogosity when dissecting
1749 these frames, as they won't have been seen by this sequential
1750 pass, but the only alternative I see is to keep scanning them
1751 even though the user requested that the scan stop, and that
1752 would leave the user stuck with an Wireshark grinding on
1753 until it finishes. Should we just stick them with that? */
1754 for (; framenum <= frames_count; framenum++) {
1755 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1756 frame_data_reset(fdata);
1760 /* We're done filtering the packets; destroy the progress bar if it
1762 if (progbar != NULL)
1763 destroy_progress_dlg(progbar);
1764 g_timer_destroy(prog_timer);
1766 /* Unfreeze the packet list. */
1767 if (!add_to_packet_list)
1768 packet_list_recreate_visible_rows();
1770 /* Compute the time it took to filter the file */
1771 compute_elapsed(cf, &start_time);
1775 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1777 if (selected_frame_num == -1) {
1778 /* The selected frame didn't pass the filter. */
1779 if (selected_frame == NULL) {
1780 /* That's because there *was* no selected frame. Make the first
1781 displayed frame the current frame. */
1782 selected_frame_num = 0;
1784 /* Find the nearest displayed frame to the selected frame (whether
1785 it's before or after that frame) and make that the current frame.
1786 If the next and previous displayed frames are equidistant from the
1787 selected frame, choose the next one. */
1788 g_assert(following_frame == NULL ||
1789 following_frame->num >= selected_frame->num);
1790 g_assert(preceding_frame == NULL ||
1791 preceding_frame->num <= selected_frame->num);
1792 if (following_frame == NULL) {
1793 /* No frame after the selected frame passed the filter, so we
1794 have to select the last displayed frame before the selected
1796 selected_frame_num = preceding_frame_num;
1797 selected_frame = preceding_frame;
1798 } else if (preceding_frame == NULL) {
1799 /* No frame before the selected frame passed the filter, so we
1800 have to select the first displayed frame after the selected
1802 selected_frame_num = following_frame_num;
1803 selected_frame = following_frame;
1805 /* Frames before and after the selected frame passed the filter, so
1806 we'll select the previous frame */
1807 selected_frame_num = preceding_frame_num;
1808 selected_frame = preceding_frame;
1813 if (selected_frame_num == -1) {
1814 /* There are no frames displayed at all. */
1815 cf_unselect_packet(cf);
1817 /* Either the frame that was selected passed the filter, or we've
1818 found the nearest displayed frame to that frame. Select it, make
1819 it the focus row, and make it visible. */
1820 /* Set to invalid to force update of packet list and packet details */
1821 cf->current_row = -1;
1822 if (selected_frame_num == 0) {
1823 packet_list_select_first_row();
1825 if (!packet_list_select_row_from_data(selected_frame)) {
1826 /* We didn't find a row corresponding to this frame.
1827 This means that the frame isn't being displayed currently,
1828 so we can't select it. */
1829 simple_message_box(ESD_TYPE_INFO, NULL,
1830 "The capture file is probably not fully dissected.",
1831 "End of capture exceeded.");
1836 /* Cleanup and release all dfilter resources */
1837 dfilter_free(dfcode);
1842 * Scan through all frame data and recalculate the ref time
1843 * without rereading the file.
1844 * XXX - do we need a progres bar or is this fast enough?
1847 ref_time_packets(capture_file *cf)
1853 cf->provider.ref = NULL;
1854 cf->provider.prev_dis = NULL;
1857 for (framenum = 1; framenum <= cf->count; framenum++) {
1858 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1860 /* just add some value here until we know if it is being displayed or not */
1861 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1867 /* If we don't have the time stamp of the first packet in the
1868 capture, it's because this is the first packet. Save the time
1869 stamp of this packet as the time stamp of the first packet. */
1870 if (cf->provider.ref == NULL)
1871 cf->provider.ref = fdata;
1872 /* if this frames is marked as a reference time frame, reset
1873 firstsec and firstusec to this frame */
1874 if (fdata->flags.ref_time)
1875 cf->provider.ref = fdata;
1877 /* If we don't have the time stamp of the previous displayed packet,
1878 it's because this is the first displayed packet. Save the time
1879 stamp of this packet as the time stamp of the previous displayed
1881 if (cf->provider.prev_dis == NULL) {
1882 cf->provider.prev_dis = fdata;
1885 /* Get the time elapsed between the first packet and this packet. */
1886 fdata->frame_ref_num = (fdata != cf->provider.ref) ? cf->provider.ref->num : 0;
1887 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->provider.ref->abs_ts);
1889 /* If it's greater than the current elapsed time, set the elapsed time
1890 to it (we check for "greater than" so as not to be confused by
1891 time moving backwards). */
1892 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1893 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1894 cf->elapsed_time = rel_ts;
1897 /* If this frame is displayed, get the time elapsed between the
1898 previous displayed packet and this packet. */
1899 if ( fdata->flags.passed_dfilter ) {
1900 fdata->prev_dis_num = cf->provider.prev_dis->num;
1901 cf->provider.prev_dis = fdata;
1907 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1908 /* This frame either passed the display filter list or is marked as
1909 a time reference frame. All time reference frames are displayed
1910 even if they don't pass the display filter */
1911 if (fdata->flags.ref_time) {
1912 /* if this was a TIME REF frame we should reset the cum_bytes field */
1913 cf->cum_bytes = fdata->pkt_len;
1914 fdata->cum_bytes = cf->cum_bytes;
1916 /* increase cum_bytes with this packets length */
1917 cf->cum_bytes += fdata->pkt_len;
1930 process_specified_records(capture_file *cf, packet_range_t *range,
1931 const char *string1, const char *string2, gboolean terminate_is_stop,
1932 gboolean (*callback)(capture_file *, frame_data *,
1933 wtap_rec *, const guint8 *, void *),
1934 void *callback_args,
1935 gboolean show_progress_bar)
1940 psp_return_t ret = PSP_FINISHED;
1942 progdlg_t *progbar = NULL;
1943 GTimer *prog_timer = g_timer_new();
1946 GTimeVal progbar_start_time;
1947 gchar progbar_status_str[100];
1948 range_process_e process_this;
1951 wtap_rec_init(&rec);
1952 ws_buffer_init(&buf, 1500);
1954 g_timer_start(prog_timer);
1955 /* Count of packets at which we've looked. */
1957 /* Progress so far. */
1960 cf->stop_flag = FALSE;
1961 g_get_current_time(&progbar_start_time);
1964 packet_range_process_init(range);
1966 /* Iterate through all the packets, printing the packets that
1967 were selected by the current display filter. */
1968 for (framenum = 1; framenum <= cf->count; framenum++) {
1969 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1971 /* Create the progress bar if necessary.
1972 We check on every iteration of the loop, so that it takes no
1973 longer than the standard time to create it (otherwise, for a
1974 large file, we might take considerably longer than that standard
1975 time in order to get to the next progress bar step). */
1976 if (show_progress_bar && progbar == NULL)
1977 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
1980 &progbar_start_time,
1984 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1985 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1986 * likely trigger UI paint events, which might take a while depending on
1987 * the platform and display. Reset our timer *after* painting.
1989 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1990 /* let's not divide by zero. I should never be started
1991 * with count == 0, so let's assert that
1993 g_assert(cf->count > 0);
1994 progbar_val = (gfloat) progbar_count / cf->count;
1996 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1997 "%4u of %u packets", progbar_count, cf->count);
1998 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2000 g_timer_start(prog_timer);
2003 if (cf->stop_flag) {
2004 /* Well, the user decided to abort the operation. Just stop,
2005 and arrange to return PSP_STOPPED to our caller, so they know
2006 it was stopped explicitly. */
2013 if (range != NULL) {
2014 /* do we have to process this packet? */
2015 process_this = packet_range_process_packet(range, fdata);
2016 if (process_this == range_process_next) {
2017 /* this packet uninteresting, continue with next one */
2019 } else if (process_this == range_processing_finished) {
2020 /* all interesting packets processed, stop the loop */
2025 /* Get the packet */
2026 if (!cf_read_record_r(cf, fdata, &rec, &buf)) {
2027 /* Attempt to get the packet failed. */
2031 /* Process the packet */
2032 if (!callback(cf, fdata, &rec, ws_buffer_start_ptr(&buf), callback_args)) {
2033 /* Callback failed. We assume it reported the error appropriately. */
2039 /* We're done printing the packets; destroy the progress bar if
2041 if (progbar != NULL)
2042 destroy_progress_dlg(progbar);
2043 g_timer_destroy(prog_timer);
2045 wtap_rec_cleanup(&rec);
2046 ws_buffer_free(&buf);
2054 } retap_callback_args_t;
2057 retap_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2058 const guint8 *pd, void *argsp)
2060 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2062 epan_dissect_run_with_taps(&args->edt, cf->cd_t, rec,
2063 frame_tvbuff_new(&cf->provider, fdata, pd),
2064 fdata, args->cinfo);
2065 epan_dissect_reset(&args->edt);
2071 cf_retap_packets(capture_file *cf)
2073 packet_range_t range;
2074 retap_callback_args_t callback_args;
2075 gboolean create_proto_tree;
2079 /* Presumably the user closed the capture file. */
2081 return CF_READ_ABORTED;
2084 cf_callback_invoke(cf_cb_file_retap_started, cf);
2086 /* Get the union of the flags for all tap listeners. */
2087 tap_flags = union_of_tap_listener_flags();
2089 /* If any tap listeners require the columns, construct them. */
2090 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2093 * Determine whether we need to create a protocol tree.
2096 * one of the tap listeners is going to apply a filter;
2098 * one of the tap listeners requires a protocol tree.
2101 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2103 /* Reset the tap listeners. */
2104 reset_tap_listeners();
2106 epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2108 /* Iterate through the list of packets, dissecting all packets and
2109 re-running the taps. */
2110 packet_range_init(&range, cf);
2111 packet_range_process_init(&range);
2113 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2114 "all packets", TRUE, retap_packet,
2115 &callback_args, TRUE);
2117 packet_range_cleanup(&range);
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;
3405 guint32 prev_framenum;
3407 frame_data *new_fd = NULL;
3408 progdlg_t *progbar = NULL;
3409 GTimer *prog_timer = g_timer_new();
3413 GTimeVal start_time;
3414 gchar status_str[100];
3416 match_result result;
3418 start_fd = cf->current_frame;
3419 if (start_fd != NULL) {
3420 prev_framenum = start_fd->num;
3422 prev_framenum = 0; /* No start packet selected. */
3425 /* Iterate through the list of packets, starting at the packet we've
3426 picked, calling a routine to run the filter on the packet, see if
3427 it matches, and stop if so. */
3429 framenum = prev_framenum;
3431 g_timer_start(prog_timer);
3432 /* Progress so far. */
3435 cf->stop_flag = FALSE;
3436 g_get_current_time(&start_time);
3438 title = cf->sfilter?cf->sfilter:"";
3440 /* Create the progress bar if necessary.
3441 We check on every iteration of the loop, so that it takes no
3442 longer than the standard time to create it (otherwise, for a
3443 large file, we might take considerably longer than that standard
3444 time in order to get to the next progress bar step). */
3445 if (progbar == NULL)
3446 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3447 FALSE, &cf->stop_flag, &start_time, progbar_val);
3450 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3451 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3452 * likely trigger UI paint events, which might take a while depending on
3453 * the platform and display. Reset our timer *after* painting.
3455 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3456 /* let's not divide by zero. I should never be started
3457 * with count == 0, so let's assert that
3459 g_assert(cf->count > 0);
3461 progbar_val = (gfloat) count / cf->count;
3463 g_snprintf(status_str, sizeof(status_str),
3464 "%4u of %u packets", count, cf->count);
3465 update_progress_dlg(progbar, progbar_val, status_str);
3467 g_timer_start(prog_timer);
3470 if (cf->stop_flag) {
3471 /* Well, the user decided to abort the search. Go back to the
3472 frame where we started. */
3477 /* Go past the current frame. */
3478 if (dir == SD_BACKWARD) {
3479 /* Go on to the previous frame. */
3480 if (framenum <= 1) {
3482 * XXX - other apps have a bit more of a detailed message
3483 * for this, and instead of offering "OK" and "Cancel",
3484 * they offer things such as "Continue" and "Cancel";
3485 * we need an API for popping up alert boxes with
3486 * {Verb} and "Cancel".
3489 if (prefs.gui_find_wrap) {
3490 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3491 framenum = cf->count; /* wrap around */
3493 statusbar_push_temporary_msg("Search reached the beginning.");
3494 framenum = prev_framenum; /* stay on previous packet */
3499 /* Go on to the next frame. */
3500 if (framenum == cf->count) {
3501 if (prefs.gui_find_wrap) {
3502 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3503 framenum = 1; /* wrap around */
3505 statusbar_push_temporary_msg("Search reached the end.");
3506 framenum = prev_framenum; /* stay on previous packet */
3512 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
3515 /* Is this packet in the display? */
3516 if (fdata && 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);
3544 if (new_fd != NULL) {
3545 /* Find and select */
3546 cf->search_in_progress = TRUE;
3547 found = packet_list_select_row_from_data(new_fd);
3548 cf->search_in_progress = FALSE;
3549 cf->search_pos = 0; /* Reset the position */
3550 cf->search_len = 0; /* Reset length */
3552 /* We didn't find a row corresponding to this frame.
3553 This means that the frame isn't being displayed currently,
3554 so we can't select it. */
3555 simple_message_box(ESD_TYPE_INFO, NULL,
3556 "The capture file is probably not fully dissected.",
3557 "End of capture exceeded.");
3560 return TRUE; /* success */
3562 return FALSE; /* failure */
3566 cf_goto_frame(capture_file *cf, guint fnumber)
3570 if (cf == NULL || cf->provider.frames == NULL) {
3571 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3572 statusbar_push_temporary_msg("There is no file loaded");
3573 return FALSE; /* we failed to go to that packet */
3576 fdata = frame_data_sequence_find(cf->provider.frames, fnumber);
3578 if (fdata == NULL) {
3579 /* we didn't find a packet with that packet number */
3580 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3581 return FALSE; /* we failed to go to that packet */
3583 if (!fdata->flags.passed_dfilter) {
3584 /* that packet currently isn't displayed */
3585 /* XXX - add it to the set of displayed packets? */
3586 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3587 return FALSE; /* we failed to go to that packet */
3590 if (!packet_list_select_row_from_data(fdata)) {
3591 /* We didn't find a row corresponding to this frame.
3592 This means that the frame isn't being displayed currently,
3593 so we can't select it. */
3594 simple_message_box(ESD_TYPE_INFO, NULL,
3595 "The capture file is probably not fully dissected.",
3596 "End of capture exceeded.");
3599 return TRUE; /* we got to that packet */
3603 * Go to frame specified by currently selected protocol tree item.
3606 cf_goto_framenum(capture_file *cf)
3608 header_field_info *hfinfo;
3611 if (cf->finfo_selected) {
3612 hfinfo = cf->finfo_selected->hfinfo;
3614 if (hfinfo->type == FT_FRAMENUM) {
3615 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3617 return cf_goto_frame(cf, framenum);
3624 /* Select the packet on a given row. */
3626 cf_select_packet(capture_file *cf, int row)
3628 epan_dissect_t *old_edt;
3631 /* Get the frame data struct pointer for this frame */
3632 fdata = packet_list_get_row_data(row);
3634 if (fdata == NULL) {
3638 /* Get the data in that frame. */
3639 if (!cf_read_record (cf, fdata)) {
3643 /* Record that this frame is the current frame. */
3644 cf->current_frame = fdata;
3645 cf->current_row = row;
3648 /* Create the logical protocol tree. */
3649 /* We don't need the columns here. */
3650 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3652 tap_build_interesting(cf->edt);
3653 epan_dissect_run(cf->edt, cf->cd_t, &cf->rec,
3654 frame_tvbuff_new_buffer(&cf->provider, cf->current_frame, &cf->buf),
3655 cf->current_frame, NULL);
3657 dfilter_macro_build_ftv_cache(cf->edt->tree);
3659 if (old_edt != NULL)
3660 epan_dissect_free(old_edt);
3664 /* Unselect the selected packet, if any. */
3666 cf_unselect_packet(capture_file *cf)
3668 epan_dissect_t *old_edt = cf->edt;
3672 /* No packet is selected. */
3673 cf->current_frame = NULL;
3674 cf->current_row = 0;
3676 /* Destroy the epan_dissect_t for the unselected packet. */
3677 if (old_edt != NULL)
3678 epan_dissect_free(old_edt);
3682 * Mark a particular frame.
3685 cf_mark_frame(capture_file *cf, frame_data *frame)
3687 if (! frame->flags.marked) {
3688 frame->flags.marked = TRUE;
3689 if (cf->count > cf->marked_count)
3695 * Unmark a particular frame.
3698 cf_unmark_frame(capture_file *cf, frame_data *frame)
3700 if (frame->flags.marked) {
3701 frame->flags.marked = FALSE;
3702 if (cf->marked_count > 0)
3708 * Ignore a particular frame.
3711 cf_ignore_frame(capture_file *cf, frame_data *frame)
3713 if (! frame->flags.ignored) {
3714 frame->flags.ignored = TRUE;
3715 if (cf->count > cf->ignored_count)
3716 cf->ignored_count++;
3721 * Un-ignore a particular frame.
3724 cf_unignore_frame(capture_file *cf, frame_data *frame)
3726 if (frame->flags.ignored) {
3727 frame->flags.ignored = FALSE;
3728 if (cf->ignored_count > 0)
3729 cf->ignored_count--;
3734 * Read the section comment.
3737 cf_read_section_comment(capture_file *cf)
3739 wtap_block_t shb_inf;
3743 /* XXX - support multiple SHBs */
3744 shb_inf = wtap_file_get_shb(cf->provider.wth);
3746 /* Get the first comment from the SHB. */
3747 /* XXX - support multiple comments */
3748 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3754 * Modify the section comment.
3757 cf_update_section_comment(capture_file *cf, gchar *comment)
3759 wtap_block_t shb_inf;
3763 /* XXX - support multiple SHBs */
3764 shb_inf = wtap_file_get_shb(cf->provider.wth);
3766 /* Get the first comment from the SHB. */
3767 /* XXX - support multiple comments */
3768 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3769 /* There's no comment - add one. */
3770 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3772 /* See if the comment has changed or not */
3773 if (strcmp(shb_comment, comment) == 0) {
3778 /* The comment has changed, let's update it */
3779 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3781 /* Mark the file as having unsaved changes */
3782 cf->unsaved_changes = TRUE;
3786 * Get the comment on a packet (record).
3787 * If the comment has been edited, it returns the result of the edit,
3788 * otherwise it returns the comment from the file.
3791 cf_get_packet_comment(capture_file *cf, const frame_data *fd)
3795 /* fetch user comment */
3796 if (fd->flags.has_user_comment)
3797 return g_strdup(cap_file_provider_get_user_comment(&cf->provider, fd));
3799 /* fetch phdr comment */
3800 if (fd->flags.has_phdr_comment) {
3801 wtap_rec rec; /* Record metadata */
3802 Buffer buf; /* Record data */
3804 wtap_rec_init(&rec);
3805 ws_buffer_init(&buf, 1500);
3807 if (!cf_read_record_r(cf, fd, &rec, &buf))
3808 { /* XXX, what we can do here? */ }
3810 comment = rec.opt_comment;
3811 wtap_rec_cleanup(&rec);
3812 ws_buffer_free(&buf);
3819 * Update(replace) the comment on a capture from a frame
3822 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3824 char *pkt_comment = cf_get_packet_comment(cf, fd);
3826 /* Check if the comment has changed */
3827 if (!g_strcmp0(pkt_comment, new_comment)) {
3828 g_free(pkt_comment);
3831 g_free(pkt_comment);
3834 cf->packet_comment_count--;
3837 cf->packet_comment_count++;
3839 cap_file_provider_set_user_comment(&cf->provider, fd, new_comment);
3841 expert_update_comment_count(cf->packet_comment_count);
3843 /* OK, we have unsaved changes. */
3844 cf->unsaved_changes = TRUE;
3849 * What types of comments does this capture file have?
3852 cf_comment_types(capture_file *cf)
3854 guint32 comment_types = 0;
3856 if (cf_read_section_comment(cf) != NULL)
3857 comment_types |= WTAP_COMMENT_PER_SECTION;
3858 if (cf->packet_comment_count != 0)
3859 comment_types |= WTAP_COMMENT_PER_PACKET;
3860 return comment_types;
3864 * Add a resolved address to this file's list of resolved addresses.
3867 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
3870 * XXX - support multiple resolved address lists, and add to the one
3871 * attached to this file?
3873 if (!add_ip_name_from_string(addr, name))
3876 /* OK, we have unsaved changes. */
3877 cf->unsaved_changes = TRUE;
3885 } save_callback_args_t;
3888 * Save a capture to a file, in a particular format, saving either
3889 * all packets, all currently-displayed packets, or all marked packets.
3891 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3892 * up a message box for the failure.
3895 save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec,
3896 const guint8 *pd, void *argsp)
3898 save_callback_args_t *args = (save_callback_args_t *)argsp;
3902 const char *pkt_comment;
3904 /* Copy the record information from what was read in from the file. */
3907 /* Make changes based on anything that the user has done but that
3908 hasn't been saved yet. */
3909 if (fdata->flags.has_user_comment)
3910 pkt_comment = cap_file_provider_get_user_comment(&cf->provider, fdata);
3912 pkt_comment = rec->opt_comment;
3913 new_rec.opt_comment = g_strdup(pkt_comment);
3914 new_rec.has_comment_changed = fdata->flags.has_user_comment ? TRUE : FALSE;
3915 /* XXX - what if times have been shifted? */
3917 /* and save the packet */
3918 if (!wtap_dump(args->pdh, &new_rec, pd, &err, &err_info)) {
3919 cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
3924 g_free(new_rec.opt_comment);
3929 * Can this capture file be written out in any format using Wiretap
3930 * rather than by copying the raw data?
3933 cf_can_write_with_wiretap(capture_file *cf)
3935 /* We don't care whether we support the comments in this file or not;
3936 if we can't, we'll offer the user the option of discarding the
3938 return wtap_dump_can_write(cf->linktypes, 0);
3942 * Should we let the user do a save?
3946 * the file has unsaved changes, and we can save it in some
3947 * format through Wiretap
3951 * the file is a temporary file and has no unsaved changes (so
3952 * that "saving" it just means copying it).
3954 * XXX - we shouldn't allow files to be edited if they can't be saved,
3955 * so cf->unsaved_changes should be true only if the file can be saved.
3957 * We don't care whether we support the comments in this file or not;
3958 * if we can't, we'll offer the user the option of discarding the
3962 cf_can_save(capture_file *cf)
3964 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
3965 /* Saved changes, and we can write it out with Wiretap. */
3969 if (cf->is_tempfile && !cf->unsaved_changes) {
3971 * Temporary file with no unsaved changes, so we can just do a
3977 /* Nothing to save. */
3982 * Should we let the user do a "save as"?
3986 * we can save it in some format through Wiretap
3990 * the file is a temporary file and has no unsaved changes (so
3991 * that "saving" it just means copying it).
3993 * XXX - we shouldn't allow files to be edited if they can't be saved,
3994 * so cf->unsaved_changes should be true only if the file can be saved.
3996 * We don't care whether we support the comments in this file or not;
3997 * if we can't, we'll offer the user the option of discarding the
4001 cf_can_save_as(capture_file *cf)
4003 if (wtap_dump_can_write(cf->linktypes, 0)) {
4004 /* We can write it out with Wiretap. */
4008 if (cf->is_tempfile && !cf->unsaved_changes) {
4010 * Temporary file with no unsaved changes, so we can just do a
4016 /* Nothing to save. */
4021 * Does this file have unsaved data?
4024 cf_has_unsaved_data(capture_file *cf)
4027 * If this is a temporary file, or a file with unsaved changes, it
4030 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4034 * Quick scan to find packet offsets.
4036 static cf_read_status_t
4037 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4039 const wtap_rec *rec;
4044 progdlg_t *progbar = NULL;
4045 GTimer *prog_timer = g_timer_new();
4048 GTimeVal start_time;
4049 gchar status_str[100];
4054 /* Close the old handle. */
4055 wtap_close(cf->provider.wth);
4057 /* Open the new file. */
4058 /* XXX: this will go through all open_routines for a matching one. But right
4059 now rescan_file() is only used when a file is being saved to a different
4060 format than the original, and the user is not given a choice of which
4061 reader to use (only which format to save it in), so doing this makes
4063 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4064 if (cf->provider.wth == NULL) {
4065 cfile_open_failure_alert_box(fname, err, err_info);
4066 return CF_READ_ERROR;
4069 /* We're scanning a file whose contents should be the same as what
4070 we had before, so we don't discard dissection state etc.. */
4073 /* Set the file name because we need it to set the follow stream filter.
4074 XXX - is that still true? We need it for other reasons, though,
4076 cf->filename = g_strdup(fname);
4078 /* Indicate whether it's a permanent or temporary file. */
4079 cf->is_tempfile = is_tempfile;
4081 /* No user changes yet. */
4082 cf->unsaved_changes = FALSE;
4084 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
4085 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4087 cf->snap = wtap_snapshot_length(cf->provider.wth);
4089 name_ptr = g_filename_display_basename(cf->filename);
4091 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4093 /* Record whether the file is compressed.
4094 XXX - do we know this at open time? */
4095 cf->iscompressed = wtap_iscompressed(cf->provider.wth);
4097 /* Find the size of the file. */
4098 size = wtap_file_size(cf->provider.wth, NULL);
4100 g_timer_start(prog_timer);
4102 cf->stop_flag = FALSE;
4103 g_get_current_time(&start_time);
4106 rec = wtap_get_rec(cf->provider.wth);
4107 while ((wtap_read(cf->provider.wth, &err, &err_info, &data_offset))) {
4109 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4110 fdata->file_off = data_offset;
4113 cf->f_datalen = wtap_read_so_far(cf->provider.wth);
4115 /* Create the progress bar if necessary. */
4116 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4117 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4118 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4119 TRUE, &cf->stop_flag, &start_time, progbar_val);
4123 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4124 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4125 * likely trigger UI paint events, which might take a while depending on
4126 * the platform and display. Reset our timer *after* painting.
4128 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4129 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4130 /* update the packet bar content on the first run or frequently on very large files */
4131 update_progress_dlg(progbar, progbar_val, status_str);
4132 compute_elapsed(cf, &start_time);
4133 packets_bar_update();
4134 g_timer_start(prog_timer);
4138 if (cf->stop_flag) {
4139 /* Well, the user decided to abort the rescan. Sadly, as this
4140 isn't a reread, recovering is difficult, so we'll just
4141 close the current capture. */
4145 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4146 it's not already there.
4147 XXX - yes, this is O(N), so if every packet had a different
4148 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4149 there are probably going to be a small number of encapsulation types
4151 if (rec->rec_type == REC_TYPE_PACKET) {
4152 cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap);
4156 /* Free the display name */
4159 /* We're done reading the file; destroy the progress bar if it was created. */
4160 if (progbar != NULL)
4161 destroy_progress_dlg(progbar);
4162 g_timer_destroy(prog_timer);
4164 /* We're done reading sequentially through the file. */
4165 cf->state = FILE_READ_DONE;
4167 /* Close the sequential I/O side, to free up memory it requires. */
4168 wtap_sequential_close(cf->provider.wth);
4170 /* compute the time it took to load the file */
4171 compute_elapsed(cf, &start_time);
4173 /* Set the file encapsulation type now; we don't know what it is until
4174 we've looked at all the packets, as we don't know until then whether
4175 there's more than one type (and thus whether it's
4176 WTAP_ENCAP_PER_PACKET). */
4177 cf->lnk_t = wtap_file_encap(cf->provider.wth);
4179 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4181 if (cf->stop_flag) {
4182 /* Our caller will give up at this point. */
4183 return CF_READ_ABORTED;
4187 /* Put up a message box noting that the read failed somewhere along
4188 the line. Don't throw out the stuff we managed to read, though,
4190 cfile_read_failure_alert_box(NULL, err, err_info);
4191 return CF_READ_ERROR;
4197 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4198 gboolean compressed, gboolean discard_comments,
4199 gboolean dont_reopen)
4202 gchar *fname_new = NULL;
4205 addrinfo_lists_t *addr_lists;
4209 gchar *display_basename;
4216 save_callback_args_t callback_args;
4217 gboolean needs_reload = FALSE;
4219 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4221 addr_lists = get_addrinfo_list();
4223 if (save_format == cf->cd_t && compressed == cf->iscompressed
4224 && !discard_comments && !cf->unsaved_changes
4225 && (wtap_addrinfo_list_empty(addr_lists) || !wtap_dump_has_name_resolution(save_format))) {
4226 /* We're saving in the format it's already in, and we're not discarding
4227 comments, and there are no changes we have in memory that aren't saved
4228 to the file, and we have no name resolution information to write or
4229 the file format we're saving in doesn't support writing name
4230 resolution information, so we can just move or copy the raw data. */
4232 if (cf->is_tempfile) {
4233 /* The file being saved is a temporary file from a live
4234 capture, so it doesn't need to stay around under that name;
4235 first, try renaming the capture buffer file to the new name.
4236 This acts as a "safe save", in that, if the file already
4237 exists, the existing file will be removed only if the rename
4240 Sadly, on Windows, as we have the current capture file
4241 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4242 (to cause the rename to remove an existing target), as
4243 done by ws_stdio_rename() (ws_rename() is #defined to
4244 be ws_stdio_rename() on Windows) will fail.
4246 According to the MSDN documentation for CreateFile(), if,
4247 when we open a capture file, we were to directly do a CreateFile(),
4248 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4249 convert it to a file descriptor with _open_osfhandle(),
4250 that would allow the file to be renamed out from under us.
4252 However, that doesn't work in practice. Perhaps the problem
4253 is that the process doing the rename is the process that
4254 has the file open. */
4256 if (ws_rename(cf->filename, fname) == 0) {
4257 /* That succeeded - there's no need to copy the source file. */
4258 how_to_save = SAVE_WITH_MOVE;
4260 if (errno == EXDEV) {
4261 /* They're on different file systems, so we have to copy the
4263 how_to_save = SAVE_WITH_COPY;
4265 /* The rename failed, but not because they're on different
4266 file systems - put up an error message. (Or should we
4267 just punt and try to copy? The only reason why I'd
4268 expect the rename to fail and the copy to succeed would
4269 be if we didn't have permission to remove the file from
4270 the temporary directory, and that might be fixable - but
4271 is it worth requiring the user to go off and fix it?) */
4272 cf_rename_failure_alert_box(fname, errno);
4277 /* Windows - copy the file to its new location. */
4278 how_to_save = SAVE_WITH_COPY;
4281 /* It's a permanent file, so we should copy it, and not remove the
4283 how_to_save = SAVE_WITH_COPY;
4286 if (how_to_save == SAVE_WITH_COPY) {
4287 /* Copy the file, if we haven't moved it. If we're overwriting
4288 an existing file, we do it with a "safe save", by writing
4289 to a new file and, if the write succeeds, renaming the
4290 new file on top of the old file. */
4291 if (file_exists(fname)) {
4292 fname_new = g_strdup_printf("%s~", fname);
4293 if (!copy_file_binary_mode(cf->filename, fname_new))
4296 if (!copy_file_binary_mode(cf->filename, fname))
4301 /* Either we're saving in a different format or we're saving changes,
4302 such as added, modified, or removed comments, that haven't yet
4303 been written to the underlying file; we can't do that by copying
4304 or moving the capture file, we have to do it by writing the packets
4307 GArray *shb_hdrs = NULL;
4308 wtapng_iface_descriptions_t *idb_inf = NULL;
4309 GArray *nrb_hdrs = NULL;
4312 /* XXX: what free's this shb_hdr? */
4313 shb_hdrs = wtap_file_get_shb_for_new_file(cf->provider.wth);
4314 idb_inf = wtap_file_get_idb_info(cf->provider.wth);
4315 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->provider.wth);
4317 /* Determine what file encapsulation type we should use. */
4318 encap = wtap_dump_file_encap_type(cf->linktypes);
4320 if (file_exists(fname)) {
4321 /* We're overwriting an existing file; write out to a new file,
4322 and, if that succeeds, rename the new file on top of the
4323 old file. That makes this a "safe save", so that we don't
4324 lose the old file if we have a problem writing out the new
4325 file. (If the existing file is the current capture file,
4326 we *HAVE* to do that, otherwise we're overwriting the file
4327 from which we're reading the packets that we're writing!) */
4328 fname_new = g_strdup_printf("%s~", fname);
4329 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4330 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4332 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4333 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4339 cfile_dump_open_failure_alert_box(fname, err, save_format);
4343 /* Add address resolution */
4344 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4346 /* Iterate through the list of packets, processing all the packets. */
4347 callback_args.pdh = pdh;
4348 callback_args.fname = fname;
4349 callback_args.file_type = save_format;
4350 switch (process_specified_records(cf, NULL, "Saving", "packets",
4351 TRUE, save_record, &callback_args, TRUE)) {
4354 /* Completed successfully. */
4358 /* The user decided to abort the saving.
4359 If we're writing to a temporary file, remove it.
4360 XXX - should we do so even if we're not writing to a
4362 wtap_dump_close(pdh, &err);
4363 if (fname_new != NULL)
4364 ws_unlink(fname_new);
4365 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4366 return CF_WRITE_ABORTED;
4369 /* Error while saving.
4370 If we're writing to a temporary file, remove it. */
4371 if (fname_new != NULL)
4372 ws_unlink(fname_new);
4373 wtap_dump_close(pdh, &err);
4377 needs_reload = wtap_dump_get_needs_reload(pdh);
4379 if (!wtap_dump_close(pdh, &err)) {
4380 cfile_close_failure_alert_box(fname, err);
4384 how_to_save = SAVE_WITH_WTAP;
4387 if (fname_new != NULL) {
4388 /* We wrote out to fname_new, and should rename it on top of
4389 fname. fname_new is now closed, so that should be possible even
4390 on Windows. However, on Windows, we first need to close whatever
4391 file descriptors we have open for fname. */
4393 wtap_fdclose(cf->provider.wth);
4395 /* Now do the rename. */
4396 if (ws_rename(fname_new, fname) == -1) {
4397 /* Well, the rename failed. */
4398 cf_rename_failure_alert_box(fname, errno);
4400 /* Attempt to reopen the random file descriptor using the
4401 current file's filename. (At this point, the sequential
4402 file descriptor is closed.) */
4403 if (!wtap_fdreopen(cf->provider.wth, cf->filename, &err)) {
4404 /* Oh, well, we're screwed. */
4405 display_basename = g_filename_display_basename(cf->filename);
4406 simple_error_message_box(
4407 file_open_error_message(err, FALSE), display_basename);
4408 g_free(display_basename);
4415 /* If this was a temporary file, and we didn't do the save by doing
4416 a move, so the tempoary file is still around under its old name,
4418 if (cf->is_tempfile && how_to_save != SAVE_WITH_MOVE) {
4419 /* If this fails, there's not much we can do, so just ignore errors. */
4420 ws_unlink(cf->filename);
4423 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4424 cf->unsaved_changes = FALSE;
4427 switch (how_to_save) {
4429 case SAVE_WITH_MOVE:
4430 /* We just moved the file, so the wtap structure refers to the
4431 new file, and all the information other than the filename
4432 and the "is temporary" status applies to the new file; just
4434 g_free(cf->filename);
4435 cf->filename = g_strdup(fname);
4436 cf->is_tempfile = FALSE;
4437 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4440 case SAVE_WITH_COPY:
4441 /* We just copied the file, so all the information other than
4442 the wtap structure, the filename, and the "is temporary"
4443 status applies to the new file; just update that. */
4444 wtap_close(cf->provider.wth);
4445 /* Although we're just "copying" and then opening the copy, it will
4446 try all open_routine readers to open the copy, so we need to
4447 reset the cfile's open_type. */
4448 cf->open_type = WTAP_TYPE_AUTO;
4449 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4450 if (cf->provider.wth == NULL) {
4451 cfile_open_failure_alert_box(fname, err, err_info);
4454 g_free(cf->filename);
4455 cf->filename = g_strdup(fname);
4456 cf->is_tempfile = FALSE;
4458 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4461 case SAVE_WITH_WTAP:
4462 /* Open and read the file we saved to.
4464 XXX - this is somewhat of a waste; we already have the
4465 packets, all this gets us is updated file type information
4466 (which we could just stuff into "cf"), and having the new
4467 file be the one we have opened and from which we're reading
4468 the data, and it means we have to spend time opening and
4469 reading the file, which could be a significant amount of
4470 time if the file is large.
4472 If the capture-file-writing code were to return the
4473 seek offset of each packet it writes, we could save that
4474 in the frame_data structure for the frame, and just open
4475 the file without reading it again...
4477 ...as long as, for gzipped files, the process of writing
4478 out the file *also* generates the information needed to
4479 support fast random access to the compressed file. */
4480 /* rescan_file will cause us to try all open_routines, so
4481 reset cfile's open_type */
4482 cf->open_type = WTAP_TYPE_AUTO;
4483 /* There are cases when SAVE_WITH_WTAP can result in new packets
4484 being written to the file, e.g ERF records
4485 In that case, we need to reload the whole file */
4487 if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) {
4488 if (cf_read(cf, TRUE) != CF_READ_OK) {
4489 /* The rescan failed; just close the file. Either
4490 a dialog was popped up for the failure, so the
4491 user knows what happened, or they stopped the
4492 rescan, in which case they know what happened. */
4493 /* XXX: This is inconsistent with normal open/reload behaviour. */
4499 if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4500 /* The rescan failed; just close the file. Either
4501 a dialog was popped up for the failure, so the
4502 user knows what happened, or they stopped the
4503 rescan, in which case they know what happened. */
4510 /* If we were told to discard the comments, do so. */
4511 if (discard_comments) {
4512 /* Remove SHB comment, if any. */
4513 wtap_write_shb_comment(cf->provider.wth, NULL);
4515 /* remove all user comments */
4516 for (framenum = 1; framenum <= cf->count; framenum++) {
4517 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4519 fdata->flags.has_phdr_comment = FALSE;
4520 fdata->flags.has_user_comment = FALSE;
4523 if (cf->provider.frames_user_comments) {
4524 g_tree_destroy(cf->provider.frames_user_comments);
4525 cf->provider.frames_user_comments = NULL;
4528 cf->packet_comment_count = 0;
4534 if (fname_new != NULL) {
4535 /* We were trying to write to a temporary file; get rid of it if it
4536 exists. (We don't care whether this fails, as, if it fails,
4537 there's not much we can do about it. I guess if it failed for
4538 a reason other than "it doesn't exist", we could report an
4539 error, so the user knows there's a junk file that they might
4540 want to clean up.) */
4541 ws_unlink(fname_new);
4544 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4545 return CF_WRITE_ERROR;
4549 cf_export_specified_packets(capture_file *cf, const char *fname,
4550 packet_range_t *range, guint save_format,
4551 gboolean compressed)
4553 gchar *fname_new = NULL;
4556 save_callback_args_t callback_args;
4557 GArray *shb_hdrs = NULL;
4558 wtapng_iface_descriptions_t *idb_inf = NULL;
4559 GArray *nrb_hdrs = NULL;
4562 packet_range_process_init(range);
4564 /* We're writing out specified packets from the specified capture
4565 file to another file. Even if all captured packets are to be
4566 written, don't special-case the operation - read each packet
4567 and then write it out if it's one of the specified ones. */
4569 /* XXX: what free's this shb_hdr? */
4570 shb_hdrs = wtap_file_get_shb_for_new_file(cf->provider.wth);
4571 idb_inf = wtap_file_get_idb_info(cf->provider.wth);
4572 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->provider.wth);
4574 /* Determine what file encapsulation type we should use. */
4575 encap = wtap_dump_file_encap_type(cf->linktypes);
4577 if (file_exists(fname)) {
4578 /* We're overwriting an existing file; write out to a new file,
4579 and, if that succeeds, rename the new file on top of the
4580 old file. That makes this a "safe save", so that we don't
4581 lose the old file if we have a problem writing out the new
4582 file. (If the existing file is the current capture file,
4583 we *HAVE* to do that, otherwise we're overwriting the file
4584 from which we're reading the packets that we're writing!) */
4585 fname_new = g_strdup_printf("%s~", fname);
4586 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4587 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4589 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4590 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4596 cfile_dump_open_failure_alert_box(fname, err, save_format);
4600 /* Add address resolution */
4601 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4603 /* Iterate through the list of packets, processing the packets we were
4606 XXX - we've already called "packet_range_process_init(range)", but
4607 "process_specified_records()" will do it again. Fortunately,
4608 that's harmless in this case, as we haven't done anything to
4609 "range" since we initialized it. */
4610 callback_args.pdh = pdh;
4611 callback_args.fname = fname;
4612 callback_args.file_type = save_format;
4613 switch (process_specified_records(cf, range, "Writing", "specified records",
4614 TRUE, save_record, &callback_args, TRUE)) {
4617 /* Completed successfully. */
4621 /* The user decided to abort the saving.
4622 If we're writing to a temporary file, remove it.
4623 XXX - should we do so even if we're not writing to a
4625 wtap_dump_close(pdh, &err);
4626 if (fname_new != NULL)
4627 ws_unlink(fname_new);
4628 return CF_WRITE_ABORTED;
4632 /* Error while saving.
4633 If we're writing to a temporary file, remove it. */
4634 if (fname_new != NULL)
4635 ws_unlink(fname_new);
4636 wtap_dump_close(pdh, &err);
4640 if (!wtap_dump_close(pdh, &err)) {
4641 cfile_close_failure_alert_box(fname, err);
4645 if (fname_new != NULL) {
4646 /* We wrote out to fname_new, and should rename it on top of
4647 fname; fname is now closed, so that should be possible even
4648 on Windows. Do the rename. */
4649 if (ws_rename(fname_new, fname) == -1) {
4650 /* Well, the rename failed. */
4651 cf_rename_failure_alert_box(fname, errno);
4659 if (fname_new != NULL) {
4660 /* We were trying to write to a temporary file; get rid of it if it
4661 exists. (We don't care whether this fails, as, if it fails,
4662 there's not much we can do about it. I guess if it failed for
4663 a reason other than "it doesn't exist", we could report an
4664 error, so the user knows there's a junk file that they might
4665 want to clean up.) */
4666 ws_unlink(fname_new);
4669 return CF_WRITE_ERROR;
4673 * XXX - whether we mention the source pathname, the target pathname,
4674 * or both depends on the error and on what we find if we look for
4675 * one or both of them.
4678 cf_rename_failure_alert_box(const char *filename, int err)
4680 gchar *display_basename;
4682 display_basename = g_filename_display_basename(filename);
4686 /* XXX - should check whether the source exists and, if not,
4687 report it as the problem and, if so, report the destination
4689 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4694 /* XXX - if we're doing a rename after a safe save, we should
4695 probably say something else. */
4696 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4701 /* XXX - this should probably mention both the source and destination
4703 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4704 display_basename, wtap_strerror(err));
4707 g_free(display_basename);
4710 /* Reload the current capture file. */
4712 cf_reload(capture_file *cf) {
4714 gboolean is_tempfile;
4717 /* If the file could be opened, "cf_open()" calls "cf_close()"
4718 to get rid of state for the old capture file before filling in state
4719 for the new capture file. "cf_close()" will remove the file if
4720 it's a temporary file; we don't want that to happen (for one thing,
4721 it'd prevent subsequent reopens from working). Remember whether it's
4722 a temporary file, mark it as not being a temporary file, and then
4723 reopen it as the type of file it was.
4725 Also, "cf_close()" will free "cf->filename", so we must make
4726 a copy of it first. */
4727 filename = g_strdup(cf->filename);
4728 is_tempfile = cf->is_tempfile;
4729 cf->is_tempfile = FALSE;
4730 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4731 switch (cf_read(cf, TRUE)) {
4735 /* Just because we got an error, that doesn't mean we were unable
4736 to read any of the file; we handle what we could get from the
4740 case CF_READ_ABORTED:
4741 /* The user bailed out of re-reading the capture file; the
4742 capture file has been closed - just free the capture file name
4743 string and return (without changing the last containing
4749 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4750 Instead, the file was left open, so we should restore "cf->is_tempfile"
4753 XXX - change the menu? Presumably "cf_open()" will do that;
4754 make sure it does! */
4755 cf->is_tempfile = is_tempfile;
4757 /* "cf_open()" made a copy of the file name we handed it, so
4758 we should free up our copy. */
4768 * indent-tabs-mode: nil
4771 * ex: set shiftwidth=2 tabstop=8 expandtab:
4772 * :indentSize=2:tabSize=8:noTabs=true: