4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
21 #include <wsutil/tempfile.h>
22 #include <wsutil/file_util.h>
23 #include <wsutil/filesystem.h>
24 #include <version_info.h>
26 #include <wiretap/merge.h>
28 #include <epan/exceptions.h>
29 #include <epan/epan.h>
30 #include <epan/column.h>
31 #include <epan/packet.h>
32 #include <epan/column-utils.h>
33 #include <epan/expert.h>
34 #include <epan/prefs.h>
35 #include <epan/dfilter/dfilter.h>
36 #include <epan/epan_dissect.h>
38 #include <epan/dissectors/packet-ber.h>
39 #include <epan/timestamp.h>
40 #include <epan/dfilter/dfilter-macro.h>
41 #include <epan/strutil.h>
42 #include <epan/addr_resolv.h>
43 #include <epan/color_filters.h>
48 #include "frame_tvbuff.h"
50 #include "ui/alert_box.h"
51 #include "ui/simple_dialog.h"
52 #include "ui/main_statusbar.h"
53 #include "ui/progress_dlg.h"
54 #include "ui/ws_ui_util.h"
56 /* Needed for addrinfo */
57 #ifdef HAVE_SYS_TYPES_H
58 # include <sys/types.h>
61 #ifdef HAVE_SYS_SOCKET_H
62 #include <sys/socket.h>
65 #ifdef HAVE_NETINET_IN_H
66 # include <netinet/in.h>
70 # include <winsock2.h>
71 # include <ws2tcpip.h>
75 gboolean auto_scroll_live; /* GTK+ only? */
78 static gboolean read_record(capture_file *cf, dfilter_t *dfcode,
79 epan_dissect_t *edt, column_info *cinfo, gint64 offset);
81 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
88 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
90 static void match_subtree_text(proto_node *node, gpointer data);
91 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
93 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
95 static match_result match_narrow(capture_file *cf, frame_data *fdata,
97 static match_result match_wide(capture_file *cf, frame_data *fdata,
99 static match_result match_binary(capture_file *cf, frame_data *fdata,
101 static match_result match_regex(capture_file *cf, frame_data *fdata,
103 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
105 static match_result match_marked(capture_file *cf, frame_data *fdata,
107 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
109 static gboolean find_packet(capture_file *cf,
110 match_result (*match_function)(capture_file *, frame_data *, void *),
111 void *criterion, search_direction dir);
113 static void cf_rename_failure_alert_box(const char *filename, int err);
114 static void ref_time_packets(capture_file *cf);
116 /* Seconds spent processing packets between pushing UI updates. */
117 #define PROGBAR_UPDATE_INTERVAL 0.150
119 /* Show the progress bar after this many seconds. */
120 #define PROGBAR_SHOW_DELAY 0.5
123 * We could probably use g_signal_...() instead of the callbacks below but that
124 * would require linking our CLI programs to libgobject and creating an object
125 * instance for the signals.
128 cf_callback_t cb_fct;
130 } cf_callback_data_t;
132 static GList *cf_callbacks = NULL;
135 cf_callback_invoke(int event, gpointer data)
137 cf_callback_data_t *cb;
138 GList *cb_item = cf_callbacks;
140 /* there should be at least one interested */
141 g_assert(cb_item != NULL);
143 while (cb_item != NULL) {
144 cb = (cf_callback_data_t *)cb_item->data;
145 cb->cb_fct(event, data, cb->user_data);
146 cb_item = g_list_next(cb_item);
152 cf_callback_add(cf_callback_t func, gpointer user_data)
154 cf_callback_data_t *cb;
156 cb = g_new(cf_callback_data_t,1);
158 cb->user_data = user_data;
160 cf_callbacks = g_list_prepend(cf_callbacks, cb);
164 cf_callback_remove(cf_callback_t func, gpointer user_data)
166 cf_callback_data_t *cb;
167 GList *cb_item = cf_callbacks;
169 while (cb_item != NULL) {
170 cb = (cf_callback_data_t *)cb_item->data;
171 if (cb->cb_fct == func && cb->user_data == user_data) {
172 cf_callbacks = g_list_remove(cf_callbacks, cb);
176 cb_item = g_list_next(cb_item);
179 g_assert_not_reached();
183 cf_timestamp_auto_precision(capture_file *cf)
187 /* don't try to get the file's precision if none is opened */
188 if (cf->state == FILE_CLOSED) {
192 /* Set the column widths of those columns that show the time in
193 "command-line-specified" format. */
194 for (i = 0; i < cf->cinfo.num_cols; i++) {
195 if (col_has_time_fmt(&cf->cinfo, i)) {
196 packet_list_resize_column(i);
202 cf_get_computed_elapsed(capture_file *cf)
204 return cf->computed_elapsed;
208 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
211 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
216 g_get_current_time(&time_now);
218 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
219 time_now.tv_usec - start_time->tv_usec;
221 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
224 static const nstime_t *
225 ws_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
227 if (prov->prev_dis && prov->prev_dis->num == frame_num)
228 return &prov->prev_dis->abs_ts;
230 if (prov->prev_cap && prov->prev_cap->num == frame_num)
231 return &prov->prev_cap->abs_ts;
234 frame_data *fd = frame_data_sequence_find(prov->frames, frame_num);
236 return (fd) ? &fd->abs_ts : NULL;
243 ws_epan_new(capture_file *cf)
245 static const struct packet_provider_funcs funcs = {
247 cap_file_provider_get_interface_name,
248 cap_file_provider_get_interface_description,
249 cap_file_provider_get_user_comment
252 return epan_new(&cf->provider, &funcs);
256 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
261 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
265 /* The open succeeded. Close whatever capture file we had open,
266 and fill in the information for this file. */
269 /* Initialize the record metadata. */
270 wtap_rec_init(&cf->rec);
272 /* XXX - we really want to initialize this after we've read all
273 the packets, so we know how much we'll ultimately need. */
274 ws_buffer_init(&cf->buf, 1500);
276 /* Create new epan session for dissection.
277 * (The old one was freed in cf_close().)
279 cf->epan = ws_epan_new(cf);
281 /* We're about to start reading the file. */
282 cf->state = FILE_READ_IN_PROGRESS;
284 cf->provider.wth = wth;
287 /* Set the file name because we need it to set the follow stream filter.
288 XXX - is that still true? We need it for other reasons, though,
290 cf->filename = g_strdup(fname);
292 /* Indicate whether it's a permanent or temporary file. */
293 cf->is_tempfile = is_tempfile;
295 /* No user changes yet. */
296 cf->unsaved_changes = FALSE;
298 cf->computed_elapsed = 0;
300 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
301 cf->open_type = type;
302 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
304 cf->packet_comment_count = 0;
305 cf->displayed_count = 0;
306 cf->marked_count = 0;
307 cf->ignored_count = 0;
308 cf->ref_time_count = 0;
309 cf->drops_known = FALSE;
311 cf->snap = wtap_snapshot_length(cf->provider.wth);
313 /* Allocate a frame_data_sequence for the frames in this file */
314 cf->provider.frames = new_frame_data_sequence();
316 nstime_set_zero(&cf->elapsed_time);
317 cf->provider.ref = NULL;
318 cf->provider.prev_dis = NULL;
319 cf->provider.prev_cap = NULL;
322 packet_list_queue_draw();
323 cf_callback_invoke(cf_cb_file_opened, cf);
325 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
326 /* tell the BER dissector the file name */
327 ber_set_filename(cf->filename);
330 wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name);
331 wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
336 cfile_open_failure_alert_box(fname, *err, err_info);
341 * Add an encapsulation type to cf->linktypes.
344 cf_add_encapsulation_type(capture_file *cf, int encap)
348 for (i = 0; i < cf->linktypes->len; i++) {
349 if (g_array_index(cf->linktypes, gint, i) == encap)
350 return; /* it's already there */
352 /* It's not already there - add it. */
353 g_array_append_val(cf->linktypes, encap);
356 /* Reset everything to a pristine state */
358 cf_close(capture_file *cf)
360 cf->stop_flag = FALSE;
361 if (cf->state == FILE_CLOSED)
362 return; /* Nothing to do */
364 /* Die if we're in the middle of reading a file. */
365 g_assert(cf->state != FILE_READ_IN_PROGRESS);
367 cf_callback_invoke(cf_cb_file_closing, cf);
369 /* close things, if not already closed before */
370 color_filters_cleanup();
372 if (cf->provider.wth) {
373 wtap_close(cf->provider.wth);
374 cf->provider.wth = NULL;
376 /* We have no file open... */
377 if (cf->filename != NULL) {
378 /* If it's a temporary file, remove it. */
380 ws_unlink(cf->filename);
381 g_free(cf->filename);
384 /* ...which means we have no changes to that file to save. */
385 cf->unsaved_changes = FALSE;
387 /* no open_routine type */
388 cf->open_type = WTAP_TYPE_AUTO;
390 /* Clean up the record metadata. */
391 wtap_rec_cleanup(&cf->rec);
393 /* Free up the packet buffer. */
394 ws_buffer_free(&cf->buf);
396 dfilter_free(cf->rfcode);
398 if (cf->provider.frames != NULL) {
399 free_frame_data_sequence(cf->provider.frames);
400 cf->provider.frames = NULL;
402 if (cf->provider.frames_user_comments) {
403 g_tree_destroy(cf->provider.frames_user_comments);
404 cf->provider.frames_user_comments = NULL;
406 cf_unselect_packet(cf); /* nothing to select */
407 cf->first_displayed = 0;
408 cf->last_displayed = 0;
410 /* No frames, no frame selected, no field in that frame selected. */
412 cf->current_frame = 0;
414 cf->finfo_selected = NULL;
416 /* No frame link-layer types, either. */
417 if (cf->linktypes != NULL) {
418 g_array_free(cf->linktypes, TRUE);
419 cf->linktypes = NULL;
422 /* Clear the packet list. */
423 packet_list_freeze();
428 nstime_set_zero(&cf->elapsed_time);
430 reset_tap_listeners();
435 /* We have no file open. */
436 cf->state = FILE_CLOSED;
438 cf_callback_invoke(cf_cb_file_closed, cf);
442 * TRUE if the progress dialog doesn't exist and it looks like we'll
443 * take > 2s to load, FALSE otherwise.
445 static inline gboolean
446 progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
450 if (progdlg) return FALSE;
451 elapsed = g_timer_elapsed(prog_timer, NULL);
452 if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
453 || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
460 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
464 progbar_val = (gfloat) file_pos / (gfloat) size;
465 if (progbar_val > 1.0) {
467 /* The file probably grew while we were reading it.
468 * Update file size, and try again.
470 size = wtap_file_size(cf->provider.wth, NULL);
473 progbar_val = (gfloat) file_pos / (gfloat) size;
475 /* If it's still > 1, either "wtap_file_size()" failed (in which
476 * case there's not much we can do about it), or the file
477 * *shrank* (in which case there's not much we can do about
478 * it); just clip the progress value at 1.0.
480 if (progbar_val > 1.0f)
484 g_snprintf(status_str, status_size,
485 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
486 file_pos / 1024, size / 1024);
492 cf_read(capture_file *cf, gboolean reloading)
495 gchar *err_info = NULL;
497 progdlg_t *volatile progbar = NULL;
498 GTimer *prog_timer = g_timer_new();
502 volatile gboolean create_proto_tree;
505 volatile gboolean is_read_aborted = FALSE;
507 /* Compile the current display filter.
508 * We assume this will not fail since cf->dfilter is only set in
509 * cf_filter IFF the filter was valid.
511 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
512 g_assert(!cf->dfilter || (compiled && dfcode));
514 /* Get the union of the flags for all tap listeners. */
515 tap_flags = union_of_tap_listener_flags();
518 * Determine whether we need to create a protocol tree.
521 * we're going to apply a display filter;
523 * one of the tap listeners is going to apply a filter;
525 * one of the tap listeners requires a protocol tree;
527 * a postdissector wants field values or protocols on
531 (dfcode != NULL || have_filtering_tap_listeners() ||
532 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
534 reset_tap_listeners();
536 name_ptr = g_filename_display_basename(cf->filename);
539 cf_callback_invoke(cf_cb_file_reload_started, cf);
541 cf_callback_invoke(cf_cb_file_read_started, cf);
543 /* Record whether the file is compressed.
544 XXX - do we know this at open time? */
545 cf->iscompressed = wtap_iscompressed(cf->provider.wth);
547 /* The packet list window will be empty until the file is completly loaded */
548 packet_list_freeze();
550 cf->stop_flag = FALSE;
551 g_get_current_time(&start_time);
553 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
563 gchar status_str[100];
567 /* If any tap listeners require the columns, construct them. */
568 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
570 /* Find the size of the file. */
571 size = wtap_file_size(cf->provider.wth, NULL);
573 g_timer_start(prog_timer);
575 while ((wtap_read(cf->provider.wth, &err, &err_info, &data_offset))) {
578 file_pos = wtap_read_so_far(cf->provider.wth);
580 /* Create the progress bar if necessary. */
581 if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
582 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
584 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
585 TRUE, &cf->stop_flag, &start_time, progbar_val);
587 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
588 TRUE, &cf->stop_flag, &start_time, progbar_val);
592 * Update the progress bar, but do it only after
593 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
594 * and packets_bar_update will likely trigger UI paint events, which
595 * might take a while depending on the platform and display. Reset
596 * our timer *after* painting.
598 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
599 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
600 /* update the packet bar content on the first run or frequently on very large files */
601 update_progress_dlg(progbar, progbar_val, status_str);
602 compute_elapsed(cf, &start_time);
603 packets_bar_update();
604 g_timer_start(prog_timer);
608 if (cf->state == FILE_READ_ABORTED) {
609 /* Well, the user decided to exit Wireshark. Break out of the
610 loop, and let the code below (which is called even if there
611 aren't any packets left to read) exit. */
612 is_read_aborted = TRUE;
616 /* Well, the user decided to abort the read. He/She will be warned and
617 it might be enough for him/her to work with the already loaded
619 This is especially true for very large capture files, where you don't
620 want to wait loading the whole file (which may last minutes or even
621 hours even on fast machines) just to see that it was the wrong file. */
624 read_record(cf, dfcode, &edt, cinfo, data_offset);
627 CATCH(OutOfMemoryError) {
628 simple_message_box(ESD_TYPE_ERROR, NULL,
629 "More information and workarounds can be found at\n"
630 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
631 "Sorry, but Wireshark has run out of memory and has to terminate now.");
633 /* Could we close the current capture and free up memory from that? */
635 /* we have to terminate, as we cannot recover from the memory error */
641 /* Free the display name */
644 /* Cleanup and release all dfilter resources */
645 dfilter_free(dfcode);
647 epan_dissect_cleanup(&edt);
649 /* We're done reading the file; destroy the progress bar if it was created. */
651 destroy_progress_dlg(progbar);
652 g_timer_destroy(prog_timer);
654 /* We're done reading sequentially through the file. */
655 cf->state = FILE_READ_DONE;
657 /* Close the sequential I/O side, to free up memory it requires. */
658 wtap_sequential_close(cf->provider.wth);
660 /* Allow the protocol dissectors to free up memory that they
661 * don't need after the sequential run-through of the packets. */
662 postseq_cleanup_all_protocols();
664 /* compute the time it took to load the file */
665 compute_elapsed(cf, &start_time);
667 /* Set the file encapsulation type now; we don't know what it is until
668 we've looked at all the packets, as we don't know until then whether
669 there's more than one type (and thus whether it's
670 WTAP_ENCAP_PER_PACKET). */
671 cf->lnk_t = wtap_file_encap(cf->provider.wth);
673 cf->current_frame = frame_data_sequence_find(cf->provider.frames, cf->first_displayed);
678 cf_callback_invoke(cf_cb_file_reload_finished, cf);
680 cf_callback_invoke(cf_cb_file_read_finished, cf);
682 /* If we have any displayed packets to select, select the first of those
683 packets by making the first row the selected row. */
684 if (cf->first_displayed != 0) {
685 packet_list_select_first_row();
688 if (is_read_aborted) {
690 * Well, the user decided to exit Wireshark while reading this *offline*
691 * capture file (Live captures are handled by something like
692 * cf_continue_tail). Clean up accordingly.
695 return CF_READ_ABORTED;
699 simple_message_box(ESD_TYPE_WARN, NULL,
700 "The remaining packets in the file were discarded.\n"
702 "As a lot of packets from the original file will be missing,\n"
703 "remember to be careful when saving the current content to a file.\n",
704 "File loading was cancelled.");
705 return CF_READ_ERROR;
709 /* Put up a message box noting that the read failed somewhere along
710 the line. Don't throw out the stuff we managed to read, though,
712 cfile_read_failure_alert_box(NULL, err, err_info);
713 return CF_READ_ERROR;
720 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
723 volatile int newly_displayed_packets = 0;
726 gboolean create_proto_tree;
730 /* Compile the current display filter.
731 * We assume this will not fail since cf->dfilter is only set in
732 * cf_filter IFF the filter was valid.
734 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
735 g_assert(!cf->dfilter || (compiled && dfcode));
737 /* Get the union of the flags for all tap listeners. */
738 tap_flags = union_of_tap_listener_flags();
741 * Determine whether we need to create a protocol tree.
744 * we're going to apply a display filter;
746 * one of the tap listeners is going to apply a filter;
748 * one of the tap listeners requires a protocol tree;
750 * a postdissector wants field values or protocols on
754 (dfcode != NULL || have_filtering_tap_listeners() ||
755 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
759 packet_list_check_end();
760 /* Don't freeze/thaw the list when doing live capture */
761 /*packet_list_freeze();*/
763 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
765 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
768 gint64 data_offset = 0;
771 /* If any tap listeners require the columns, construct them. */
772 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
774 while (to_read != 0) {
775 wtap_cleareof(cf->provider.wth);
776 if (!wtap_read(cf->provider.wth, err, &err_info, &data_offset)) {
779 if (cf->state == FILE_READ_ABORTED) {
780 /* Well, the user decided to exit Wireshark. Break out of the
781 loop, and let the code below (which is called even if there
782 aren't any packets left to read) exit. */
785 if (read_record(cf, dfcode, &edt, (column_info *) cinfo, data_offset)) {
786 newly_displayed_packets++;
791 CATCH(OutOfMemoryError) {
792 simple_message_box(ESD_TYPE_ERROR, NULL,
793 "More information and workarounds can be found at\n"
794 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
795 "Sorry, but Wireshark has run out of memory and has to terminate now.");
797 /* Could we close the current capture and free up memory from that? */
798 return CF_READ_ABORTED;
800 /* we have to terminate, as we cannot recover from the memory error */
806 /* Update the file encapsulation; it might have changed based on the
807 packets we've read. */
808 cf->lnk_t = wtap_file_encap(cf->provider.wth);
810 /* Cleanup and release all dfilter resources */
811 dfilter_free(dfcode);
813 epan_dissect_cleanup(&edt);
815 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
816 cf->count, cf->state, *err);*/
818 /* Don't freeze/thaw the list when doing live capture */
819 /*packet_list_thaw();*/
820 /* With the new packet list the first packet
821 * isn't automatically selected.
823 if (!cf->current_frame)
824 packet_list_select_first_row();
826 /* moving to the end of the packet list - if the user requested so and
827 we have some new packets. */
828 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
829 packet_list_moveto_end();
831 if (cf->state == FILE_READ_ABORTED) {
832 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
833 so that our caller can kill off the capture child process;
834 this will cause an EOF on the pipe from the child, so
835 "cf_finish_tail()" will be called, and it will clean up
837 return CF_READ_ABORTED;
838 } else if (*err != 0) {
839 /* We got an error reading the capture file.
840 XXX - pop up a dialog box instead? */
841 if (err_info != NULL) {
842 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
843 wtap_strerror(*err), cf->filename, err_info);
846 g_warning("Error \"%s\" while reading \"%s\"",
847 wtap_strerror(*err), cf->filename);
849 return CF_READ_ERROR;
855 cf_fake_continue_tail(capture_file *cf) {
856 cf->state = FILE_READ_DONE;
860 cf_finish_tail(capture_file *cf, int *err)
867 gboolean create_proto_tree;
871 /* Compile the current display filter.
872 * We assume this will not fail since cf->dfilter is only set in
873 * cf_filter IFF the filter was valid.
875 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
876 g_assert(!cf->dfilter || (compiled && dfcode));
878 /* Get the union of the flags for all tap listeners. */
879 tap_flags = union_of_tap_listener_flags();
881 /* If any tap listeners require the columns, construct them. */
882 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
885 * Determine whether we need to create a protocol tree.
888 * we're going to apply a display filter;
890 * one of the tap listeners is going to apply a filter;
892 * one of the tap listeners requires a protocol tree;
894 * a postdissector wants field values or protocols on
898 (dfcode != NULL || have_filtering_tap_listeners() ||
899 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
901 if (cf->provider.wth == NULL) {
903 return CF_READ_ERROR;
906 packet_list_check_end();
907 /* Don't freeze/thaw the list when doing live capture */
908 /*packet_list_freeze();*/
910 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
912 while ((wtap_read(cf->provider.wth, err, &err_info, &data_offset))) {
913 if (cf->state == FILE_READ_ABORTED) {
914 /* Well, the user decided to abort the read. Break out of the
915 loop, and let the code below (which is called even if there
916 aren't any packets left to read) exit. */
919 read_record(cf, dfcode, &edt, cinfo, data_offset);
922 /* Cleanup and release all dfilter resources */
923 dfilter_free(dfcode);
925 epan_dissect_cleanup(&edt);
927 /* Don't freeze/thaw the list when doing live capture */
928 /*packet_list_thaw();*/
930 if (cf->state == FILE_READ_ABORTED) {
931 /* Well, the user decided to abort the read. We're only called
932 when the child capture process closes the pipe to us (meaning
933 it's probably exited), so we can just close the capture
934 file; we return CF_READ_ABORTED so our caller can do whatever
935 is appropriate when that happens. */
937 return CF_READ_ABORTED;
940 if (auto_scroll_live && cf->count != 0)
941 packet_list_moveto_end();
943 /* We're done reading sequentially through the file. */
944 cf->state = FILE_READ_DONE;
946 /* We're done reading sequentially through the file; close the
947 sequential I/O side, to free up memory it requires. */
948 wtap_sequential_close(cf->provider.wth);
950 /* Allow the protocol dissectors to free up memory that they
951 * don't need after the sequential run-through of the packets. */
952 postseq_cleanup_all_protocols();
954 /* Update the file encapsulation; it might have changed based on the
955 packets we've read. */
956 cf->lnk_t = wtap_file_encap(cf->provider.wth);
958 /* Update the details in the file-set dialog, as the capture file
959 * has likely grown since we first stat-ed it */
960 fileset_update_file(cf->filename);
963 /* We got an error reading the capture file.
964 XXX - pop up a dialog box? */
965 if (err_info != NULL) {
966 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
967 wtap_strerror(*err), cf->filename, err_info);
970 g_warning("Error \"%s\" while reading \"%s\"",
971 wtap_strerror(*err), cf->filename);
973 return CF_READ_ERROR;
978 #endif /* HAVE_LIBPCAP */
981 cf_get_display_name(capture_file *cf)
985 /* Return a name to use in displays */
986 if (!cf->is_tempfile) {
987 /* Get the last component of the file name, and use that. */
989 displayname = g_filename_display_basename(cf->filename);
991 displayname=g_strdup("(No file)");
994 /* The file we read is a temporary file from a live capture or
995 a merge operation; we don't mention its name, but, if it's
996 from a capture, give the source of the capture. */
998 displayname = g_strdup(cf->source);
1000 displayname = g_strdup("(Untitled)");
1006 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1012 cf->source = g_strdup(source);
1014 cf->source = g_strdup("");
1018 const gchar *cf_get_tempfile_source(capture_file *cf) {
1026 /* XXX - use a macro instead? */
1028 cf_get_packet_count(capture_file *cf)
1033 /* XXX - use a macro instead? */
1035 cf_is_tempfile(capture_file *cf)
1037 return cf->is_tempfile;
1040 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1042 cf->is_tempfile = is_tempfile;
1046 /* XXX - use a macro instead? */
1047 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1049 cf->drops_known = drops_known;
1052 /* XXX - use a macro instead? */
1053 void cf_set_drops(capture_file *cf, guint32 drops)
1058 /* XXX - use a macro instead? */
1059 gboolean cf_get_drops_known(capture_file *cf)
1061 return cf->drops_known;
1064 /* XXX - use a macro instead? */
1065 guint32 cf_get_drops(capture_file *cf)
1070 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1072 cf->rfcode = rfcode;
1076 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1077 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1078 wtap_rec *rec, const guint8 *buf, gboolean add_to_packet_list)
1080 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1081 &cf->provider.ref, cf->provider.prev_dis);
1082 cf->provider.prev_cap = fdata;
1084 if (dfcode != NULL) {
1085 epan_dissect_prime_with_dfilter(edt, dfcode);
1088 /* Prepare coloring rules, this ensures that display filter rules containing
1089 * frame.color_rule references are still processed.
1090 * TODO: actually detect that situation or maybe apply other optimizations? */
1091 if (edt->tree && color_filters_used()) {
1092 color_filters_prime_edt(edt);
1093 fdata->flags.need_colorize = 1;
1097 if (!fdata->flags.visited) {
1098 /* This is the first pass, so prime the epan_dissect_t with the
1099 hfids postdissectors want on the first pass. */
1100 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1103 /* Dissect the frame. */
1104 epan_dissect_run_with_taps(edt, cf->cd_t, rec,
1105 frame_tvbuff_new(&cf->provider, fdata, buf),
1108 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1109 if (dfcode != NULL) {
1110 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1112 if (fdata->flags.passed_dfilter) {
1113 /* This frame passed the display filter but it may depend on other
1114 * (potentially not displayed) frames. Find those frames and mark them
1117 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
1120 fdata->flags.passed_dfilter = 1;
1122 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1123 cf->displayed_count++;
1125 if (add_to_packet_list) {
1126 /* We fill the needed columns from new_packet_list */
1127 packet_list_append(cinfo, fdata);
1130 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1132 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1133 cf->provider.prev_dis = fdata;
1135 /* If we haven't yet seen the first frame, this is it. */
1136 if (cf->first_displayed == 0)
1137 cf->first_displayed = fdata->num;
1139 /* This is the last frame we've seen so far. */
1140 cf->last_displayed = fdata->num;
1143 epan_dissect_reset(edt);
1147 * Read in a new record.
1148 * Returns TRUE if the packet was added to the packet (record) list,
1152 read_record(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1153 column_info *cinfo, gint64 offset)
1155 wtap_rec *rec = wtap_get_rec(cf->provider.wth);
1156 const guint8 *buf = wtap_get_buf_ptr(cf->provider.wth);
1159 gboolean passed = TRUE;
1160 gboolean added = FALSE;
1162 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1163 it's not already there.
1164 XXX - yes, this is O(N), so if every packet had a different
1165 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1166 there are probably going to be a small number of encapsulation types
1168 if (rec->rec_type == REC_TYPE_PACKET) {
1169 cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap);
1172 /* The frame number of this packet, if we add it to the set of frames,
1173 would be one more than the count of frames in the file so far. */
1174 frame_data_init(&fdlocal, cf->count + 1, rec, offset, cf->cum_bytes);
1177 epan_dissect_t rf_edt;
1179 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1180 epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
1181 epan_dissect_run(&rf_edt, cf->cd_t, rec,
1182 frame_tvbuff_new(&cf->provider, &fdlocal, buf),
1184 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1185 epan_dissect_cleanup(&rf_edt);
1191 /* This does a shallow copy of fdlocal, which is good enough. */
1192 fdata = frame_data_sequence_add(cf->provider.frames, &fdlocal);
1195 if (rec->opt_comment != NULL)
1196 cf->packet_comment_count++;
1197 cf->f_datalen = offset + fdlocal.cap_len;
1199 if (!cf->redissecting) {
1200 add_packet_to_packet_list(fdata, cf, edt, dfcode,
1201 cinfo, rec, buf, TRUE);
1209 typedef struct _callback_data_t {
1212 GTimeVal start_time;
1220 merge_callback(merge_event event, int num _U_,
1221 const merge_in_file_t in_files[], const guint in_file_count,
1225 callback_data_t *cb_data = (callback_data_t*) data;
1227 g_assert(cb_data != NULL);
1231 case MERGE_EVENT_INPUT_FILES_OPENED:
1235 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1239 case MERGE_EVENT_READY_TO_MERGE:
1240 /* Get the sum of the sizes of all the files. */
1241 for (i = 0; i < in_file_count; i++)
1242 cb_data->f_len += in_files[i].size;
1244 cb_data->prog_timer = g_timer_new();
1245 g_timer_start(cb_data->prog_timer);
1247 g_get_current_time(&cb_data->start_time);
1250 case MERGE_EVENT_RECORD_WAS_READ:
1252 /* Create the progress bar if necessary.
1253 We check on every iteration of the loop, so that it takes no
1254 longer than the standard time to create it (otherwise, for a
1255 large file, we might take considerably longer than that standard
1256 time in order to get to the next progress bar step). */
1257 if (cb_data->progbar == NULL) {
1258 cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1259 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1263 * Update the progress bar, but do it only after
1264 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1265 * and packets_bar_update will likely trigger UI paint events, which
1266 * might take a while depending on the platform and display. Reset
1267 * our timer *after* painting.
1269 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1271 gint64 file_pos = 0;
1272 /* Get the sum of the seek positions in all of the files. */
1273 for (i = 0; i < in_file_count; i++)
1274 file_pos += wtap_read_so_far(in_files[i].wth);
1276 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1277 if (progbar_val > 1.0f) {
1278 /* Some file probably grew while we were reading it.
1279 That "shouldn't happen", so we'll just clip the progress
1284 if (cb_data->progbar != NULL) {
1285 gchar status_str[100];
1286 g_snprintf(status_str, sizeof(status_str),
1287 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1288 file_pos / 1024, cb_data->f_len / 1024);
1289 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1291 g_timer_start(cb_data->prog_timer);
1296 case MERGE_EVENT_DONE:
1297 /* We're done merging the files; destroy the progress bar if it was created. */
1298 if (cb_data->progbar != NULL)
1299 destroy_progress_dlg(cb_data->progbar);
1300 g_timer_destroy(cb_data->prog_timer);
1304 return cb_data->stop_flag;
1310 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1311 int in_file_count, char *const *in_filenames,
1312 int file_type, gboolean do_append)
1315 gchar *err_info = NULL;
1317 guint32 err_framenum;
1318 merge_result status;
1319 merge_progress_callback_t cb;
1320 callback_data_t *cb_data = g_new0(callback_data_t, 1);
1322 /* prepare our callback routine */
1323 cb_data->pd_window = pd_window;
1324 cb.callback_func = merge_callback;
1327 cf_callback_invoke(cf_cb_file_merge_started, NULL);
1329 /* merge the files */
1330 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1331 (const char *const *) in_filenames,
1332 in_file_count, do_append,
1333 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1334 "Wireshark", &cb, &err, &err_info,
1335 &err_fileno, &err_framenum);
1343 case MERGE_USER_ABORTED:
1344 /* this isn't really an error, though we will return CF_ERROR later */
1347 case MERGE_ERR_CANT_OPEN_INFILE:
1348 cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
1351 case MERGE_ERR_CANT_OPEN_OUTFILE:
1352 cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
1355 case MERGE_ERR_CANT_READ_INFILE:
1356 cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
1359 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1360 simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
1361 err_framenum, in_filenames[err_fileno]);
1364 case MERGE_ERR_CANT_WRITE_OUTFILE:
1365 cfile_write_failure_alert_box(in_filenames[err_fileno],
1366 *out_filenamep, err, err_info,
1367 err_framenum, file_type);
1370 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1371 cfile_close_failure_alert_box(*out_filenamep, err);
1375 simple_error_message_box("Unknown merge_files error %d", status);
1379 cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1381 if (status != MERGE_OK) {
1382 /* Callers aren't expected to treat an error or an explicit abort
1383 differently - we put up error dialogs ourselves, so they don't
1391 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1393 const char *filter_new = dftext ? dftext : "";
1394 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1397 GTimeVal start_time;
1399 /* if new filter equals old one, do nothing unless told to do so */
1400 if (!force && strcmp(filter_new, filter_old) == 0) {
1406 if (dftext == NULL) {
1407 /* The new filter is an empty filter (i.e., display all packets).
1408 * so leave dfcode==NULL
1412 * We have a filter; make a copy of it (as we'll be saving it),
1413 * and try to compile it.
1415 dftext = g_strdup(dftext);
1416 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1417 /* The attempt failed; report an error. */
1418 simple_message_box(ESD_TYPE_ERROR, NULL,
1419 "See the help for a description of the display filter syntax.",
1420 "\"%s\" isn't a valid display filter: %s",
1428 if (dfcode == NULL) {
1429 /* Yes - free the filter text, and set it to null. */
1435 /* We have a valid filter. Replace the current filter. */
1436 g_free(cf->dfilter);
1437 cf->dfilter = dftext;
1438 g_get_current_time(&start_time);
1441 /* Now rescan the packet list, applying the new filter, but not
1442 throwing away information constructed on a previous pass. */
1443 if (cf->state != FILE_CLOSED) {
1444 if (dftext == NULL) {
1445 rescan_packets(cf, "Resetting", "Filter", FALSE);
1447 rescan_packets(cf, "Filtering", dftext, FALSE);
1451 /* Cleanup and release all dfilter resources */
1452 dfilter_free(dfcode);
1458 cf_reftime_packets(capture_file *cf)
1460 ref_time_packets(cf);
1464 cf_redissect_packets(capture_file *cf)
1466 if (cf->state != FILE_CLOSED) {
1467 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1472 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1473 wtap_rec *rec, Buffer *buf)
1478 if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) {
1479 cfile_read_failure_alert_box(cf->filename, err, err_info);
1486 cf_read_record(capture_file *cf, frame_data *fdata)
1488 return cf_read_record_r(cf, fdata, &cf->rec, &cf->buf);
1491 /* Rescan the list of packets, reconstructing the CList.
1493 "action" describes why we're doing this; it's used in the progress
1496 "action_item" describes what we're doing; it's used in the progress
1499 "redissect" is TRUE if we need to make the dissectors reconstruct
1500 any state information they have (because a preference that affects
1501 some dissector has changed, meaning some dissector might construct
1502 its state differently from the way it was constructed the last time). */
1504 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1506 /* Rescan packets new packet list */
1509 progdlg_t *progbar = NULL;
1510 GTimer *prog_timer = g_timer_new();
1512 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1513 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1514 gboolean selected_frame_seen;
1516 GTimeVal start_time;
1517 gchar status_str[100];
1521 gboolean create_proto_tree;
1523 gboolean add_to_packet_list = FALSE;
1525 guint32 frames_count;
1527 /* Compile the current display filter.
1528 * We assume this will not fail since cf->dfilter is only set in
1529 * cf_filter IFF the filter was valid.
1531 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1532 g_assert(!cf->dfilter || (compiled && dfcode));
1534 /* Get the union of the flags for all tap listeners. */
1535 tap_flags = union_of_tap_listener_flags();
1537 /* If any tap listeners require the columns, construct them. */
1538 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1541 * Determine whether we need to create a protocol tree.
1544 * we're going to apply a display filter;
1546 * one of the tap listeners is going to apply a filter;
1548 * one of the tap listeners requires a protocol tree;
1550 * we're redissecting and a postdissector wants field
1551 * values or protocols on the first pass.
1554 (dfcode != NULL || have_filtering_tap_listeners() ||
1555 (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1556 (redissect && postdissectors_want_hfids()));
1558 reset_tap_listeners();
1559 /* Which frame, if any, is the currently selected frame?
1560 XXX - should the selected frame or the focus frame be the "current"
1561 frame, that frame being the one from which "Find Frame" searches
1563 selected_frame = cf->current_frame;
1565 /* Mark frame num as not found */
1566 selected_frame_num = -1;
1568 /* Freeze the packet list while we redo it, so we don't get any
1569 screen updates while it happens. */
1570 packet_list_freeze();
1573 /* We need to re-initialize all the state information that protocols
1574 keep, because some preference that controls a dissector has changed,
1575 which might cause the state information to be constructed differently
1576 by that dissector. */
1578 /* We might receive new packets while redissecting, and we don't
1579 want to dissect those before their time. */
1580 cf->redissecting = TRUE;
1582 /* 'reset' dissection session */
1583 epan_free(cf->epan);
1584 if (cf->edt && cf->edt->pi.fd) {
1585 /* All pointers in "per frame proto data" for the currently selected
1586 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1587 Free them here to avoid unintended usage in packet_list_clear(). */
1588 frame_data_destroy(cf->edt->pi.fd);
1590 cf->epan = ws_epan_new(cf);
1591 cf->cinfo.epan = cf->epan;
1593 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1594 called via epan_new() / init_dissection() when reloading Lua plugins. */
1595 if (!create_proto_tree && have_filtering_tap_listeners()) {
1596 create_proto_tree = TRUE;
1599 /* We need to redissect the packets so we have to discard our old
1600 * packet list store. */
1601 packet_list_clear();
1602 add_to_packet_list = TRUE;
1605 /* We don't yet know which will be the first and last frames displayed. */
1606 cf->first_displayed = 0;
1607 cf->last_displayed = 0;
1609 /* We currently don't display any packets */
1610 cf->displayed_count = 0;
1612 /* Iterate through the list of frames. Call a routine for each frame
1613 to check whether it should be displayed and, if so, add it to
1614 the display list. */
1615 cf->provider.ref = NULL;
1616 cf->provider.prev_dis = NULL;
1617 cf->provider.prev_cap = NULL;
1620 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1622 g_timer_start(prog_timer);
1623 /* Count of packets at which we've looked. */
1625 /* Progress so far. */
1628 cf->stop_flag = FALSE;
1629 g_get_current_time(&start_time);
1631 /* no previous row yet */
1632 prev_frame_num = -1;
1635 preceding_frame_num = -1;
1636 preceding_frame = NULL;
1637 following_frame_num = -1;
1638 following_frame = NULL;
1640 selected_frame_seen = FALSE;
1642 frames_count = cf->count;
1644 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1646 for (framenum = 1; framenum <= frames_count; framenum++) {
1647 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1649 /* Create the progress bar if necessary.
1650 We check on every iteration of the loop, so that it takes no
1651 longer than the standard time to create it (otherwise, for a
1652 large file, we might take considerably longer than that standard
1653 time in order to get to the next progress bar step). */
1654 if (progbar == NULL)
1655 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1661 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1662 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1663 * likely trigger UI paint events, which might take a while depending on
1664 * the platform and display. Reset our timer *after* painting.
1666 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1667 /* let's not divide by zero. I should never be started
1668 * with count == 0, so let's assert that
1670 g_assert(cf->count > 0);
1671 progbar_val = (gfloat) count / frames_count;
1673 if (progbar != NULL) {
1674 g_snprintf(status_str, sizeof(status_str),
1675 "%4u of %u frames", count, frames_count);
1676 update_progress_dlg(progbar, progbar_val, status_str);
1679 g_timer_start(prog_timer);
1682 if (cf->stop_flag) {
1683 /* Well, the user decided to abort the filtering. Just stop.
1685 XXX - go back to the previous filter? Users probably just
1686 want not to wait for a filtering operation to finish;
1687 unless we cancel by having no filter, reverting to the
1688 previous filter will probably be even more expensive than
1689 continuing the filtering, as it involves going back to the
1690 beginning and filtering, and even with no filter we currently
1691 have to re-generate the entire clist, which is also expensive.
1693 I'm not sure what Network Monitor does, but it doesn't appear
1694 to give you an unfiltered display if you cancel. */
1701 /* Since all state for the frame was destroyed, mark the frame
1702 * as not visited, free the GSList referring to the state
1703 * data (the per-frame data itself was freed by
1704 * "init_dissection()"), and null out the GSList pointer. */
1705 frame_data_reset(fdata);
1706 frames_count = cf->count;
1709 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1710 fdata->flags.dependent_of_displayed = 0;
1712 if (!cf_read_record(cf, fdata))
1713 break; /* error reading the frame */
1715 /* If the previous frame is displayed, and we haven't yet seen the
1716 selected frame, remember that frame - it's the closest one we've
1717 yet seen before the selected frame. */
1718 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1719 preceding_frame_num = prev_frame_num;
1720 preceding_frame = prev_frame;
1723 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1725 ws_buffer_start_ptr(&cf->buf),
1726 add_to_packet_list);
1728 /* If this frame is displayed, and this is the first frame we've
1729 seen displayed after the selected frame, remember this frame -
1730 it's the closest one we've yet seen at or after the selected
1732 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1733 following_frame_num = fdata->num;
1734 following_frame = fdata;
1736 if (fdata == selected_frame) {
1737 selected_frame_seen = TRUE;
1738 if (fdata->flags.passed_dfilter)
1739 selected_frame_num = fdata->num;
1742 /* Remember this frame - it'll be the previous frame
1743 on the next pass through the loop. */
1744 prev_frame_num = fdata->num;
1748 epan_dissect_cleanup(&edt);
1750 /* We are done redissecting the packet list. */
1751 cf->redissecting = FALSE;
1754 frames_count = cf->count;
1755 /* Clear out what remains of the visited flags and per-frame data
1758 XXX - that may cause various forms of bogosity when dissecting
1759 these frames, as they won't have been seen by this sequential
1760 pass, but the only alternative I see is to keep scanning them
1761 even though the user requested that the scan stop, and that
1762 would leave the user stuck with an Wireshark grinding on
1763 until it finishes. Should we just stick them with that? */
1764 for (; framenum <= frames_count; framenum++) {
1765 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1766 frame_data_reset(fdata);
1770 /* We're done filtering the packets; destroy the progress bar if it
1772 if (progbar != NULL)
1773 destroy_progress_dlg(progbar);
1774 g_timer_destroy(prog_timer);
1776 /* Unfreeze the packet list. */
1777 if (!add_to_packet_list)
1778 packet_list_recreate_visible_rows();
1780 /* Compute the time it took to filter the file */
1781 compute_elapsed(cf, &start_time);
1785 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1787 if (selected_frame_num == -1) {
1788 /* The selected frame didn't pass the filter. */
1789 if (selected_frame == NULL) {
1790 /* That's because there *was* no selected frame. Make the first
1791 displayed frame the current frame. */
1792 selected_frame_num = 0;
1794 /* Find the nearest displayed frame to the selected frame (whether
1795 it's before or after that frame) and make that the current frame.
1796 If the next and previous displayed frames are equidistant from the
1797 selected frame, choose the next one. */
1798 g_assert(following_frame == NULL ||
1799 following_frame->num >= selected_frame->num);
1800 g_assert(preceding_frame == NULL ||
1801 preceding_frame->num <= selected_frame->num);
1802 if (following_frame == NULL) {
1803 /* No frame after the selected frame passed the filter, so we
1804 have to select the last displayed frame before the selected
1806 selected_frame_num = preceding_frame_num;
1807 selected_frame = preceding_frame;
1808 } else if (preceding_frame == NULL) {
1809 /* No frame before the selected frame passed the filter, so we
1810 have to select the first displayed frame after the selected
1812 selected_frame_num = following_frame_num;
1813 selected_frame = following_frame;
1815 /* Frames before and after the selected frame passed the filter, so
1816 we'll select the previous frame */
1817 selected_frame_num = preceding_frame_num;
1818 selected_frame = preceding_frame;
1823 if (selected_frame_num == -1) {
1824 /* There are no frames displayed at all. */
1825 cf_unselect_packet(cf);
1827 /* Either the frame that was selected passed the filter, or we've
1828 found the nearest displayed frame to that frame. Select it, make
1829 it the focus row, and make it visible. */
1830 /* Set to invalid to force update of packet list and packet details */
1831 cf->current_row = -1;
1832 if (selected_frame_num == 0) {
1833 packet_list_select_first_row();
1835 if (!packet_list_select_row_from_data(selected_frame)) {
1836 /* We didn't find a row corresponding to this frame.
1837 This means that the frame isn't being displayed currently,
1838 so we can't select it. */
1839 simple_message_box(ESD_TYPE_INFO, NULL,
1840 "The capture file is probably not fully dissected.",
1841 "End of capture exceeded.");
1846 /* Cleanup and release all dfilter resources */
1847 dfilter_free(dfcode);
1852 * Scan through all frame data and recalculate the ref time
1853 * without rereading the file.
1854 * XXX - do we need a progres bar or is this fast enough?
1857 ref_time_packets(capture_file *cf)
1863 cf->provider.ref = NULL;
1864 cf->provider.prev_dis = NULL;
1867 for (framenum = 1; framenum <= cf->count; framenum++) {
1868 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1870 /* just add some value here until we know if it is being displayed or not */
1871 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1877 /* If we don't have the time stamp of the first packet in the
1878 capture, it's because this is the first packet. Save the time
1879 stamp of this packet as the time stamp of the first packet. */
1880 if (cf->provider.ref == NULL)
1881 cf->provider.ref = fdata;
1882 /* if this frames is marked as a reference time frame, reset
1883 firstsec and firstusec to this frame */
1884 if (fdata->flags.ref_time)
1885 cf->provider.ref = fdata;
1887 /* If we don't have the time stamp of the previous displayed packet,
1888 it's because this is the first displayed packet. Save the time
1889 stamp of this packet as the time stamp of the previous displayed
1891 if (cf->provider.prev_dis == NULL) {
1892 cf->provider.prev_dis = fdata;
1895 /* Get the time elapsed between the first packet and this packet. */
1896 fdata->frame_ref_num = (fdata != cf->provider.ref) ? cf->provider.ref->num : 0;
1897 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->provider.ref->abs_ts);
1899 /* If it's greater than the current elapsed time, set the elapsed time
1900 to it (we check for "greater than" so as not to be confused by
1901 time moving backwards). */
1902 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1903 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1904 cf->elapsed_time = rel_ts;
1907 /* If this frame is displayed, get the time elapsed between the
1908 previous displayed packet and this packet. */
1909 if ( fdata->flags.passed_dfilter ) {
1910 fdata->prev_dis_num = cf->provider.prev_dis->num;
1911 cf->provider.prev_dis = fdata;
1917 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1918 /* This frame either passed the display filter list or is marked as
1919 a time reference frame. All time reference frames are displayed
1920 even if they don't pass the display filter */
1921 if (fdata->flags.ref_time) {
1922 /* if this was a TIME REF frame we should reset the cum_bytes field */
1923 cf->cum_bytes = fdata->pkt_len;
1924 fdata->cum_bytes = cf->cum_bytes;
1926 /* increase cum_bytes with this packets length */
1927 cf->cum_bytes += fdata->pkt_len;
1940 process_specified_records(capture_file *cf, packet_range_t *range,
1941 const char *string1, const char *string2, gboolean terminate_is_stop,
1942 gboolean (*callback)(capture_file *, frame_data *,
1943 wtap_rec *, const guint8 *, void *),
1944 void *callback_args,
1945 gboolean show_progress_bar)
1950 psp_return_t ret = PSP_FINISHED;
1952 progdlg_t *progbar = NULL;
1953 GTimer *prog_timer = g_timer_new();
1956 GTimeVal progbar_start_time;
1957 gchar progbar_status_str[100];
1958 range_process_e process_this;
1961 wtap_rec_init(&rec);
1962 ws_buffer_init(&buf, 1500);
1964 g_timer_start(prog_timer);
1965 /* Count of packets at which we've looked. */
1967 /* Progress so far. */
1970 cf->stop_flag = FALSE;
1971 g_get_current_time(&progbar_start_time);
1974 packet_range_process_init(range);
1976 /* Iterate through all the packets, printing the packets that
1977 were selected by the current display filter. */
1978 for (framenum = 1; framenum <= cf->count; framenum++) {
1979 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1981 /* Create the progress bar if necessary.
1982 We check on every iteration of the loop, so that it takes no
1983 longer than the standard time to create it (otherwise, for a
1984 large file, we might take considerably longer than that standard
1985 time in order to get to the next progress bar step). */
1986 if (show_progress_bar && progbar == NULL)
1987 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
1990 &progbar_start_time,
1994 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1995 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1996 * likely trigger UI paint events, which might take a while depending on
1997 * the platform and display. Reset our timer *after* painting.
1999 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2000 /* let's not divide by zero. I should never be started
2001 * with count == 0, so let's assert that
2003 g_assert(cf->count > 0);
2004 progbar_val = (gfloat) progbar_count / cf->count;
2006 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2007 "%4u of %u packets", progbar_count, cf->count);
2008 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2010 g_timer_start(prog_timer);
2013 if (cf->stop_flag) {
2014 /* Well, the user decided to abort the operation. Just stop,
2015 and arrange to return PSP_STOPPED to our caller, so they know
2016 it was stopped explicitly. */
2023 if (range != NULL) {
2024 /* do we have to process this packet? */
2025 process_this = packet_range_process_packet(range, fdata);
2026 if (process_this == range_process_next) {
2027 /* this packet uninteresting, continue with next one */
2029 } else if (process_this == range_processing_finished) {
2030 /* all interesting packets processed, stop the loop */
2035 /* Get the packet */
2036 if (!cf_read_record_r(cf, fdata, &rec, &buf)) {
2037 /* Attempt to get the packet failed. */
2041 /* Process the packet */
2042 if (!callback(cf, fdata, &rec, ws_buffer_start_ptr(&buf), callback_args)) {
2043 /* Callback failed. We assume it reported the error appropriately. */
2049 /* We're done printing the packets; destroy the progress bar if
2051 if (progbar != NULL)
2052 destroy_progress_dlg(progbar);
2053 g_timer_destroy(prog_timer);
2055 wtap_rec_cleanup(&rec);
2056 ws_buffer_free(&buf);
2064 } retap_callback_args_t;
2067 retap_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2068 const guint8 *pd, void *argsp)
2070 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2072 epan_dissect_run_with_taps(&args->edt, cf->cd_t, rec,
2073 frame_tvbuff_new(&cf->provider, fdata, pd),
2074 fdata, args->cinfo);
2075 epan_dissect_reset(&args->edt);
2081 cf_retap_packets(capture_file *cf)
2083 packet_range_t range;
2084 retap_callback_args_t callback_args;
2085 gboolean create_proto_tree;
2089 /* Presumably the user closed the capture file. */
2091 return CF_READ_ABORTED;
2094 cf_callback_invoke(cf_cb_file_retap_started, cf);
2096 /* Get the union of the flags for all tap listeners. */
2097 tap_flags = union_of_tap_listener_flags();
2099 /* If any tap listeners require the columns, construct them. */
2100 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2103 * Determine whether we need to create a protocol tree.
2106 * one of the tap listeners is going to apply a filter;
2108 * one of the tap listeners requires a protocol tree.
2111 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2113 /* Reset the tap listeners. */
2114 reset_tap_listeners();
2116 epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2118 /* Iterate through the list of packets, dissecting all packets and
2119 re-running the taps. */
2120 packet_range_init(&range, cf);
2121 packet_range_process_init(&range);
2123 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2124 "all packets", TRUE, retap_packet,
2125 &callback_args, TRUE);
2127 epan_dissect_cleanup(&callback_args.edt);
2129 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2133 /* Completed successfully. */
2137 /* Well, the user decided to abort the refiltering.
2138 Return CF_READ_ABORTED so our caller knows they did that. */
2139 return CF_READ_ABORTED;
2142 /* Error while retapping. */
2143 return CF_READ_ERROR;
2146 g_assert_not_reached();
2151 print_args_t *print_args;
2152 gboolean print_header_line;
2153 char *header_line_buf;
2154 int header_line_buf_len;
2155 gboolean print_formfeed;
2156 gboolean print_separator;
2160 int num_visible_cols;
2163 } print_callback_args_t;
2166 print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2167 const guint8 *pd, void *argsp)
2169 print_callback_args_t *args = (print_callback_args_t *)argsp;
2175 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2176 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2177 col_item_t* col_item;
2179 /* Fill in the column information if we're printing the summary
2181 if (args->print_args->print_summary) {
2182 col_custom_prime_edt(&args->edt, &cf->cinfo);
2183 epan_dissect_run(&args->edt, cf->cd_t, rec,
2184 frame_tvbuff_new(&cf->provider, fdata, pd),
2186 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2188 epan_dissect_run(&args->edt, cf->cd_t, rec,
2189 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2191 if (args->print_formfeed) {
2192 if (!new_page(args->print_args->stream))
2195 if (args->print_separator) {
2196 if (!print_line(args->print_args->stream, 0, ""))
2202 * We generate bookmarks, if the output format supports them.
2203 * The name is "__frameN__".
2205 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2207 if (args->print_args->print_summary) {
2208 if (!args->print_args->print_col_headings)
2209 args->print_header_line = FALSE;
2210 if (args->print_header_line) {
2211 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2213 args->print_header_line = FALSE; /* we might not need to print any more */
2215 cp = &args->line_buf[0];
2217 for (i = 0; i < args->num_visible_cols; i++) {
2218 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2219 /* Find the length of the string for this column. */
2220 column_len = (int) strlen(col_item->col_data);
2221 if (args->col_widths[i] > column_len)
2222 column_len = args->col_widths[i];
2224 /* Make sure there's room in the line buffer for the column; if not,
2225 double its length. */
2226 line_len += column_len + 1; /* "+1" for space */
2227 if (line_len > args->line_buf_len) {
2228 cp_off = (int) (cp - args->line_buf);
2229 args->line_buf_len = 2 * line_len;
2230 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2231 cp = args->line_buf + cp_off;
2234 /* Right-justify the packet number column. */
2235 if (col_item->col_fmt == COL_NUMBER)
2236 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2238 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2240 if (i != args->num_visible_cols - 1)
2246 * Generate a bookmark, using the summary line as the title.
2248 if (!print_bookmark(args->print_args->stream, bookmark_name,
2252 if (!print_line(args->print_args->stream, 0, args->line_buf))
2256 * Generate a bookmark, using "Frame N" as the title, as we're not
2257 * printing the summary line.
2259 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2260 if (!print_bookmark(args->print_args->stream, bookmark_name,
2263 } /* if (print_summary) */
2265 if (args->print_args->print_dissections != print_dissections_none) {
2266 if (args->print_args->print_summary) {
2267 /* Separate the summary line from the tree with a blank line. */
2268 if (!print_line(args->print_args->stream, 0, ""))
2272 /* Print the information in that tree. */
2273 if (!proto_tree_print(args->print_args->print_dissections,
2274 args->print_args->print_hex, &args->edt, NULL,
2275 args->print_args->stream))
2278 /* Print a blank line if we print anything after this (aka more than one packet). */
2279 args->print_separator = TRUE;
2281 /* Print a header line if we print any more packet summaries */
2282 if (args->print_args->print_col_headings)
2283 args->print_header_line = TRUE;
2286 if (args->print_args->print_hex) {
2287 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2288 if (!print_line(args->print_args->stream, 0, ""))
2291 /* Print the full packet data as hex. */
2292 if (!print_hex_data(args->print_args->stream, &args->edt))
2295 /* Print a blank line if we print anything after this (aka more than one packet). */
2296 args->print_separator = TRUE;
2298 /* Print a header line if we print any more packet summaries */
2299 if (args->print_args->print_col_headings)
2300 args->print_header_line = TRUE;
2301 } /* if (args->print_args->print_dissections != print_dissections_none) */
2303 epan_dissect_reset(&args->edt);
2305 /* do we want to have a formfeed between each packet from now on? */
2306 if (args->print_args->print_formfeed) {
2307 args->print_formfeed = TRUE;
2313 epan_dissect_reset(&args->edt);
2318 cf_print_packets(capture_file *cf, print_args_t *print_args,
2319 gboolean show_progress_bar)
2321 print_callback_args_t callback_args;
2324 int i, cp_off, column_len, line_len;
2325 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2329 gboolean proto_tree_needed;
2331 callback_args.print_args = print_args;
2332 callback_args.print_header_line = print_args->print_col_headings;
2333 callback_args.header_line_buf = NULL;
2334 callback_args.header_line_buf_len = 256;
2335 callback_args.print_formfeed = FALSE;
2336 callback_args.print_separator = FALSE;
2337 callback_args.line_buf = NULL;
2338 callback_args.line_buf_len = 256;
2339 callback_args.col_widths = NULL;
2340 callback_args.num_visible_cols = 0;
2341 callback_args.visible_cols = NULL;
2343 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2344 destroy_print_stream(print_args->stream);
2345 return CF_PRINT_WRITE_ERROR;
2348 if (print_args->print_summary) {
2349 /* We're printing packet summaries. Allocate the header line buffer
2350 and get the column widths. */
2351 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2353 /* Find the number of visible columns and the last visible column */
2354 for (i = 0; i < prefs.num_cols; i++) {
2356 clp = g_list_nth(prefs.col_list, i);
2357 if (clp == NULL) /* Sanity check, Invalid column requested */
2360 cfmt = (fmt_data *) clp->data;
2361 if (cfmt->visible) {
2363 last_visible_col = i;
2367 /* if num_visible_col is 0, we are done */
2368 if (num_visible_col == 0) {
2369 g_free(callback_args.header_line_buf);
2373 /* Find the widths for each of the columns - maximum of the
2374 width of the title and the width of the data - and construct
2375 a buffer with a line containing the column titles. */
2376 callback_args.num_visible_cols = num_visible_col;
2377 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2378 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2379 cp = &callback_args.header_line_buf[0];
2381 visible_col_count = 0;
2382 for (i = 0; i < cf->cinfo.num_cols; i++) {
2384 clp = g_list_nth(prefs.col_list, i);
2385 if (clp == NULL) /* Sanity check, Invalid column requested */
2388 cfmt = (fmt_data *) clp->data;
2389 if (cfmt->visible == FALSE)
2392 /* Save the order of visible columns */
2393 callback_args.visible_cols[visible_col_count] = i;
2395 /* Don't pad the last column. */
2396 if (i == last_visible_col)
2397 callback_args.col_widths[visible_col_count] = 0;
2399 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2400 data_width = get_column_char_width(get_column_format(i));
2401 if (data_width > callback_args.col_widths[visible_col_count])
2402 callback_args.col_widths[visible_col_count] = data_width;
2405 /* Find the length of the string for this column. */
2406 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2407 if (callback_args.col_widths[visible_col_count] > column_len)
2408 column_len = callback_args.col_widths[visible_col_count];
2410 /* Make sure there's room in the line buffer for the column; if not,
2411 double its length. */
2412 line_len += column_len + 1; /* "+1" for space */
2413 if (line_len > callback_args.header_line_buf_len) {
2414 cp_off = (int) (cp - callback_args.header_line_buf);
2415 callback_args.header_line_buf_len = 2 * line_len;
2416 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2417 callback_args.header_line_buf_len + 1);
2418 cp = callback_args.header_line_buf + cp_off;
2421 /* Right-justify the packet number column. */
2422 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2423 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2425 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2427 if (i != cf->cinfo.num_cols - 1)
2430 visible_col_count++;
2434 /* Now start out the main line buffer with the same length as the
2435 header line buffer. */
2436 callback_args.line_buf_len = callback_args.header_line_buf_len;
2437 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2438 } /* if (print_summary) */
2440 /* Create the protocol tree, and make it visible, if we're printing
2441 the dissection or the hex data.
2442 XXX - do we need it if we're just printing the hex data? */
2444 callback_args.print_args->print_dissections != print_dissections_none ||
2445 callback_args.print_args->print_hex ||
2446 have_custom_cols(&cf->cinfo) || have_field_extractors();
2447 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2449 /* Iterate through the list of packets, printing the packets we were
2451 ret = process_specified_records(cf, &print_args->range, "Printing",
2452 "selected packets", TRUE, print_packet,
2453 &callback_args, show_progress_bar);
2454 epan_dissect_cleanup(&callback_args.edt);
2455 g_free(callback_args.header_line_buf);
2456 g_free(callback_args.line_buf);
2457 g_free(callback_args.col_widths);
2458 g_free(callback_args.visible_cols);
2463 /* Completed successfully. */
2467 /* Well, the user decided to abort the printing.
2469 XXX - note that what got generated before they did that
2470 will get printed if we're piping to a print program; we'd
2471 have to write to a file and then hand that to the print
2472 program to make it actually not print anything. */
2476 /* Error while printing.
2478 XXX - note that what got generated before they did that
2479 will get printed if we're piping to a print program; we'd
2480 have to write to a file and then hand that to the print
2481 program to make it actually not print anything. */
2482 destroy_print_stream(print_args->stream);
2483 return CF_PRINT_WRITE_ERROR;
2486 if (!print_finale(print_args->stream)) {
2487 destroy_print_stream(print_args->stream);
2488 return CF_PRINT_WRITE_ERROR;
2491 if (!destroy_print_stream(print_args->stream))
2492 return CF_PRINT_WRITE_ERROR;
2500 print_args_t *print_args;
2501 } write_packet_callback_args_t;
2504 write_pdml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2505 const guint8 *pd, void *argsp)
2507 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2509 /* Create the protocol tree, but don't fill in the column information. */
2510 epan_dissect_run(&args->edt, cf->cd_t, rec,
2511 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2513 /* Write out the information in that tree. */
2514 write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, &cf->cinfo, args->fh, FALSE);
2516 epan_dissect_reset(&args->edt);
2518 return !ferror(args->fh);
2522 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2524 write_packet_callback_args_t callback_args;
2528 fh = ws_fopen(print_args->file, "w");
2530 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2532 write_pdml_preamble(fh, cf->filename);
2535 return CF_PRINT_WRITE_ERROR;
2538 callback_args.fh = fh;
2539 callback_args.print_args = print_args;
2540 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2542 /* Iterate through the list of packets, printing the packets we were
2544 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2545 "selected packets", TRUE,
2546 write_pdml_packet, &callback_args, TRUE);
2548 epan_dissect_cleanup(&callback_args.edt);
2553 /* Completed successfully. */
2557 /* Well, the user decided to abort the printing. */
2561 /* Error while printing. */
2563 return CF_PRINT_WRITE_ERROR;
2566 write_pdml_finale(fh);
2569 return CF_PRINT_WRITE_ERROR;
2572 /* XXX - check for an error */
2579 write_psml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2580 const guint8 *pd, void *argsp)
2582 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2584 /* Fill in the column information */
2585 col_custom_prime_edt(&args->edt, &cf->cinfo);
2586 epan_dissect_run(&args->edt, cf->cd_t, rec,
2587 frame_tvbuff_new(&cf->provider, fdata, pd),
2589 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2591 /* Write out the column information. */
2592 write_psml_columns(&args->edt, args->fh, FALSE);
2594 epan_dissect_reset(&args->edt);
2596 return !ferror(args->fh);
2600 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2602 write_packet_callback_args_t callback_args;
2606 gboolean proto_tree_needed;
2608 fh = ws_fopen(print_args->file, "w");
2610 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2612 write_psml_preamble(&cf->cinfo, fh);
2615 return CF_PRINT_WRITE_ERROR;
2618 callback_args.fh = fh;
2619 callback_args.print_args = print_args;
2621 /* Fill in the column information, only create the protocol tree
2622 if having custom columns or field extractors. */
2623 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2624 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2626 /* Iterate through the list of packets, printing the packets we were
2628 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2629 "selected packets", TRUE,
2630 write_psml_packet, &callback_args, TRUE);
2632 epan_dissect_cleanup(&callback_args.edt);
2637 /* Completed successfully. */
2641 /* Well, the user decided to abort the printing. */
2645 /* Error while printing. */
2647 return CF_PRINT_WRITE_ERROR;
2650 write_psml_finale(fh);
2653 return CF_PRINT_WRITE_ERROR;
2656 /* XXX - check for an error */
2663 write_csv_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2664 const guint8 *pd, void *argsp)
2666 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2668 /* Fill in the column information */
2669 col_custom_prime_edt(&args->edt, &cf->cinfo);
2670 epan_dissect_run(&args->edt, cf->cd_t, rec,
2671 frame_tvbuff_new(&cf->provider, fdata, pd),
2673 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2675 /* Write out the column information. */
2676 write_csv_columns(&args->edt, args->fh);
2678 epan_dissect_reset(&args->edt);
2680 return !ferror(args->fh);
2684 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2686 write_packet_callback_args_t callback_args;
2687 gboolean proto_tree_needed;
2691 fh = ws_fopen(print_args->file, "w");
2693 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2695 write_csv_column_titles(&cf->cinfo, fh);
2698 return CF_PRINT_WRITE_ERROR;
2701 callback_args.fh = fh;
2702 callback_args.print_args = print_args;
2704 /* only create the protocol tree if having custom columns or field extractors. */
2705 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2706 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2708 /* Iterate through the list of packets, printing the packets we were
2710 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2711 "selected packets", TRUE,
2712 write_csv_packet, &callback_args, TRUE);
2714 epan_dissect_cleanup(&callback_args.edt);
2719 /* Completed successfully. */
2723 /* Well, the user decided to abort the printing. */
2727 /* Error while printing. */
2729 return CF_PRINT_WRITE_ERROR;
2732 /* XXX - check for an error */
2739 carrays_write_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2740 const guint8 *pd, void *argsp)
2742 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2744 epan_dissect_run(&args->edt, cf->cd_t, rec,
2745 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2746 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2747 epan_dissect_reset(&args->edt);
2749 return !ferror(args->fh);
2753 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2755 write_packet_callback_args_t callback_args;
2759 fh = ws_fopen(print_args->file, "w");
2762 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2766 return CF_PRINT_WRITE_ERROR;
2769 callback_args.fh = fh;
2770 callback_args.print_args = print_args;
2771 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2773 /* Iterate through the list of packets, printing the packets we were
2775 ret = process_specified_records(cf, &print_args->range,
2777 "selected packets", TRUE,
2778 carrays_write_packet, &callback_args, TRUE);
2780 epan_dissect_cleanup(&callback_args.edt);
2784 /* Completed successfully. */
2787 /* Well, the user decided to abort the printing. */
2790 /* Error while printing. */
2792 return CF_PRINT_WRITE_ERROR;
2800 write_json_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2801 const guint8 *pd, void *argsp)
2803 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2805 /* Create the protocol tree, but don't fill in the column information. */
2806 epan_dissect_run(&args->edt, cf->cd_t, rec,
2807 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2809 /* Write out the information in that tree. */
2810 write_json_proto_tree(NULL, args->print_args->print_dissections,
2811 args->print_args->print_hex, NULL, PF_NONE,
2812 &args->edt, &cf->cinfo, proto_node_group_children_by_unique, args->fh);
2814 epan_dissect_reset(&args->edt);
2816 return !ferror(args->fh);
2820 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2822 write_packet_callback_args_t callback_args;
2826 fh = ws_fopen(print_args->file, "w");
2828 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2830 write_json_preamble(fh);
2833 return CF_PRINT_WRITE_ERROR;
2836 callback_args.fh = fh;
2837 callback_args.print_args = print_args;
2838 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2840 /* Iterate through the list of packets, printing the packets we were
2842 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2843 "selected packets", TRUE,
2844 write_json_packet, &callback_args, TRUE);
2846 epan_dissect_cleanup(&callback_args.edt);
2851 /* Completed successfully. */
2855 /* Well, the user decided to abort the printing. */
2859 /* Error while printing. */
2861 return CF_PRINT_WRITE_ERROR;
2864 write_json_finale(fh);
2867 return CF_PRINT_WRITE_ERROR;
2870 /* XXX - check for an error */
2877 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2878 search_direction dir)
2882 mdata.string = string;
2883 mdata.string_len = strlen(string);
2884 return find_packet(cf, match_protocol_tree, &mdata, dir);
2888 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2890 mdata->frame_matched = FALSE;
2891 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2892 mdata->string_len = strlen(mdata->string);
2894 /* Iterate through all the nodes looking for matching text */
2895 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2896 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2900 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2902 match_data *mdata = (match_data *)criterion;
2905 /* Load the frame's data. */
2906 if (!cf_read_record(cf, fdata)) {
2907 /* Attempt to get the packet failed. */
2911 /* Construct the protocol tree, including the displayed text */
2912 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2913 /* We don't need the column information */
2914 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
2915 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
2918 /* Iterate through all the nodes, seeing if they have text that matches. */
2920 mdata->frame_matched = FALSE;
2921 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2922 epan_dissect_cleanup(&edt);
2923 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2927 match_subtree_text(proto_node *node, gpointer data)
2929 match_data *mdata = (match_data *) data;
2930 const gchar *string = mdata->string;
2931 size_t string_len = mdata->string_len;
2932 capture_file *cf = mdata->cf;
2933 field_info *fi = PNODE_FINFO(node);
2934 gchar label_str[ITEM_LABEL_LENGTH];
2941 /* dissection with an invisible proto tree? */
2944 if (mdata->frame_matched) {
2945 /* We already had a match; don't bother doing any more work. */
2949 /* Don't match invisible entries. */
2950 if (PROTO_ITEM_IS_HIDDEN(node))
2953 /* was a free format label produced? */
2955 label_ptr = fi->rep->representation;
2957 /* no, make a generic label */
2958 label_ptr = label_str;
2959 proto_item_fill_label(fi, label_str);
2963 if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
2964 mdata->frame_matched = TRUE;
2969 /* Does that label match? */
2970 label_len = strlen(label_ptr);
2971 for (i = 0; i < label_len; i++) {
2972 c_char = label_ptr[i];
2974 c_char = g_ascii_toupper(c_char);
2975 if (c_char == string[c_match]) {
2977 if (c_match == string_len) {
2978 /* No need to look further; we have a match */
2979 mdata->frame_matched = TRUE;
2988 /* Recurse into the subtree, if it exists */
2989 if (node->first_child != NULL)
2990 proto_tree_children_foreach(node, match_subtree_text, mdata);
2994 cf_find_packet_summary_line(capture_file *cf, const char *string,
2995 search_direction dir)
2999 mdata.string = string;
3000 mdata.string_len = strlen(string);
3001 return find_packet(cf, match_summary_line, &mdata, dir);
3005 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3007 match_data *mdata = (match_data *)criterion;
3008 const gchar *string = mdata->string;
3009 size_t string_len = mdata->string_len;
3011 const char *info_column;
3012 size_t info_column_len;
3013 match_result result = MR_NOTMATCHED;
3019 /* Load the frame's data. */
3020 if (!cf_read_record(cf, fdata)) {
3021 /* Attempt to get the packet failed. */
3025 /* Don't bother constructing the protocol tree */
3026 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3027 /* Get the column information */
3028 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3029 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3032 /* Find the Info column */
3033 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3034 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3035 /* Found it. See if we match. */
3036 info_column = edt.pi.cinfo->columns[colx].col_data;
3037 info_column_len = strlen(info_column);
3039 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3040 result = MR_MATCHED;
3044 for (i = 0; i < info_column_len; i++) {
3045 c_char = info_column[i];
3047 c_char = g_ascii_toupper(c_char);
3048 if (c_char == string[c_match]) {
3050 if (c_match == string_len) {
3051 result = MR_MATCHED;
3061 epan_dissect_cleanup(&edt);
3068 } cbs_t; /* "Counted byte string" */
3072 * The current match_* routines only support ASCII case insensitivity and don't
3073 * convert UTF-8 inputs to UTF-16 for matching.
3075 * We could modify them to use the GLib Unicode routines or the International
3076 * Components for Unicode library but it's not apparent that we could do so
3077 * without consuming a lot more CPU and memory or that searching would be
3078 * significantly better.
3082 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3083 search_direction dir)
3088 info.data_len = string_size;
3090 /* Regex, String or hex search? */
3092 /* Regular Expression search */
3093 return find_packet(cf, match_regex, NULL, dir);
3094 } else if (cf->string) {
3095 /* String search - what type of string? */
3096 switch (cf->scs_type) {
3098 case SCS_NARROW_AND_WIDE:
3099 return find_packet(cf, match_narrow_and_wide, &info, dir);
3102 return find_packet(cf, match_narrow, &info, dir);
3105 return find_packet(cf, match_wide, &info, dir);
3108 g_assert_not_reached();
3112 return find_packet(cf, match_binary, &info, dir);
3116 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3118 cbs_t *info = (cbs_t *)criterion;
3119 const guint8 *ascii_text = info->data;
3120 size_t textlen = info->data_len;
3121 match_result result;
3128 /* Load the frame's data. */
3129 if (!cf_read_record(cf, fdata)) {
3130 /* Attempt to get the packet failed. */
3134 result = MR_NOTMATCHED;
3135 buf_len = fdata->cap_len;
3136 pd = ws_buffer_start_ptr(&cf->buf);
3138 while (i < buf_len) {
3141 c_char = g_ascii_toupper(c_char);
3142 if (c_char != '\0') {
3143 if (c_char == ascii_text[c_match]) {
3145 if (c_match == textlen) {
3146 result = MR_MATCHED;
3147 cf->search_pos = i; /* Save the position of the last character
3148 for highlighting the field. */
3149 cf->search_len = (guint32)textlen;
3154 g_assert(i>=c_match);
3155 i -= (guint32)c_match;
3165 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3168 cbs_t *info = (cbs_t *)criterion;
3169 const guint8 *ascii_text = info->data;
3170 size_t textlen = info->data_len;
3171 match_result result;
3177 /* Load the frame's data. */
3178 if (!cf_read_record(cf, fdata)) {
3179 /* Attempt to get the packet failed. */
3183 result = MR_NOTMATCHED;
3184 buf_len = fdata->cap_len;
3185 pd = ws_buffer_start_ptr(&cf->buf);
3187 while (i < buf_len) {
3190 c_char = g_ascii_toupper(c_char);
3191 if (c_char == ascii_text[c_match]) {
3193 if (c_match == textlen) {
3194 result = MR_MATCHED;
3195 cf->search_pos = i; /* Save the position of the last character
3196 for highlighting the field. */
3197 cf->search_len = (guint32)textlen;
3202 g_assert(i>=c_match);
3203 i -= (guint32)c_match;
3213 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3215 cbs_t *info = (cbs_t *)criterion;
3216 const guint8 *ascii_text = info->data;
3217 size_t textlen = info->data_len;
3218 match_result result;
3225 /* Load the frame's data. */
3226 if (!cf_read_record(cf, fdata)) {
3227 /* Attempt to get the packet failed. */
3231 result = MR_NOTMATCHED;
3232 buf_len = fdata->cap_len;
3233 pd = ws_buffer_start_ptr(&cf->buf);
3235 while (i < buf_len) {
3238 c_char = g_ascii_toupper(c_char);
3239 if (c_char == ascii_text[c_match]) {
3241 if (c_match == textlen) {
3242 result = MR_MATCHED;
3243 cf->search_pos = i; /* Save the position of the last character
3244 for highlighting the field. */
3245 cf->search_len = (guint32)textlen;
3251 g_assert(i>=(c_match*2));
3252 i -= (guint32)c_match*2;
3261 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3263 cbs_t *info = (cbs_t *)criterion;
3264 const guint8 *binary_data = info->data;
3265 size_t datalen = info->data_len;
3266 match_result result;
3272 /* Load the frame's data. */
3273 if (!cf_read_record(cf, fdata)) {
3274 /* Attempt to get the packet failed. */
3278 result = MR_NOTMATCHED;
3279 buf_len = fdata->cap_len;
3280 pd = ws_buffer_start_ptr(&cf->buf);
3282 while (i < buf_len) {
3283 if (pd[i] == binary_data[c_match]) {
3285 if (c_match == datalen) {
3286 result = MR_MATCHED;
3287 cf->search_pos = i; /* Save the position of the last character
3288 for highlighting the field. */
3289 cf->search_len = (guint32)datalen;
3294 g_assert(i>=c_match);
3295 i -= (guint32)c_match;
3304 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3306 match_result result = MR_NOTMATCHED;
3307 GMatchInfo *match_info = NULL;
3309 /* Load the frame's data. */
3310 if (!cf_read_record(cf, fdata)) {
3311 /* Attempt to get the packet failed. */
3315 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3316 0, (GRegexMatchFlags) 0, &match_info, NULL))
3318 gint start_pos = 0, end_pos = 0;
3319 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3320 cf->search_pos = end_pos - 1;
3321 cf->search_len = end_pos - start_pos;
3322 result = MR_MATCHED;
3328 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3329 search_direction dir)
3331 return find_packet(cf, match_dfilter, sfcode, dir);
3335 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3336 search_direction dir)
3341 if (!dfilter_compile(filter, &sfcode, NULL)) {
3343 * XXX - this shouldn't happen, as the filter string is machine
3348 if (sfcode == NULL) {
3350 * XXX - this shouldn't happen, as the filter string is machine
3355 result = find_packet(cf, match_dfilter, sfcode, dir);
3356 dfilter_free(sfcode);
3361 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3363 dfilter_t *sfcode = (dfilter_t *)criterion;
3365 match_result result;
3367 /* Load the frame's data. */
3368 if (!cf_read_record(cf, fdata)) {
3369 /* Attempt to get the packet failed. */
3373 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3374 epan_dissect_prime_with_dfilter(&edt, sfcode);
3375 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3376 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3378 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3379 epan_dissect_cleanup(&edt);
3384 cf_find_packet_marked(capture_file *cf, search_direction dir)
3386 return find_packet(cf, match_marked, NULL, dir);
3390 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3392 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3396 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3398 return find_packet(cf, match_time_reference, NULL, dir);
3402 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3404 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3408 find_packet(capture_file *cf,
3409 match_result (*match_function)(capture_file *, frame_data *, void *),
3410 void *criterion, search_direction dir)
3412 frame_data *start_fd;
3415 frame_data *new_fd = NULL;
3416 progdlg_t *progbar = NULL;
3417 GTimer *prog_timer = g_timer_new();
3421 GTimeVal start_time;
3422 gchar status_str[100];
3424 match_result result;
3426 start_fd = cf->current_frame;
3427 if (start_fd != NULL) {
3428 /* Iterate through the list of packets, starting at the packet we've
3429 picked, calling a routine to run the filter on the packet, see if
3430 it matches, and stop if so. */
3432 framenum = start_fd->num;
3434 g_timer_start(prog_timer);
3435 /* Progress so far. */
3438 cf->stop_flag = FALSE;
3439 g_get_current_time(&start_time);
3441 title = cf->sfilter?cf->sfilter:"";
3443 /* Create the progress bar if necessary.
3444 We check on every iteration of the loop, so that it takes no
3445 longer than the standard time to create it (otherwise, for a
3446 large file, we might take considerably longer than that standard
3447 time in order to get to the next progress bar step). */
3448 if (progbar == NULL)
3449 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3450 FALSE, &cf->stop_flag, &start_time, progbar_val);
3453 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3454 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3455 * likely trigger UI paint events, which might take a while depending on
3456 * the platform and display. Reset our timer *after* painting.
3458 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3459 /* let's not divide by zero. I should never be started
3460 * with count == 0, so let's assert that
3462 g_assert(cf->count > 0);
3464 progbar_val = (gfloat) count / cf->count;
3466 g_snprintf(status_str, sizeof(status_str),
3467 "%4u of %u packets", count, cf->count);
3468 update_progress_dlg(progbar, progbar_val, status_str);
3470 g_timer_start(prog_timer);
3473 if (cf->stop_flag) {
3474 /* Well, the user decided to abort the search. Go back to the
3475 frame where we started. */
3480 /* Go past the current frame. */
3481 if (dir == SD_BACKWARD) {
3482 /* Go on to the previous frame. */
3483 if (framenum == 1) {
3485 * XXX - other apps have a bit more of a detailed message
3486 * for this, and instead of offering "OK" and "Cancel",
3487 * they offer things such as "Continue" and "Cancel";
3488 * we need an API for popping up alert boxes with
3489 * {Verb} and "Cancel".
3492 if (prefs.gui_find_wrap)
3494 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3495 framenum = cf->count; /* wrap around */
3499 statusbar_push_temporary_msg("Search reached the beginning.");
3500 framenum = start_fd->num; /* stay on previous packet */
3505 /* Go on to the next frame. */
3506 if (framenum == cf->count) {
3507 if (prefs.gui_find_wrap)
3509 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3510 framenum = 1; /* wrap around */
3514 statusbar_push_temporary_msg("Search reached the end.");
3515 framenum = start_fd->num; /* stay on previous packet */
3520 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
3524 /* Is this packet in the display? */
3525 if (fdata->flags.passed_dfilter) {
3526 /* Yes. Does it match the search criterion? */
3527 result = (*match_function)(cf, fdata, criterion);
3528 if (result == MR_ERROR) {
3529 /* Error; our caller has reported the error. Go back to the frame
3530 where we started. */
3533 } else if (result == MR_MATCHED) {
3534 /* Yes. Go to the new frame. */
3540 if (fdata == start_fd) {
3541 /* We're back to the frame we were on originally, and that frame
3542 doesn't match the search filter. The search failed. */
3547 /* We're done scanning the packets; destroy the progress bar if it
3549 if (progbar != NULL)
3550 destroy_progress_dlg(progbar);
3551 g_timer_destroy(prog_timer);
3554 if (new_fd != NULL) {
3555 /* Find and select */
3556 cf->search_in_progress = TRUE;
3557 found = packet_list_select_row_from_data(new_fd);
3558 cf->search_in_progress = FALSE;
3559 cf->search_pos = 0; /* Reset the position */
3560 cf->search_len = 0; /* Reset length */
3562 /* We didn't find a row corresponding to this frame.
3563 This means that the frame isn't being displayed currently,
3564 so we can't select it. */
3565 simple_message_box(ESD_TYPE_INFO, NULL,
3566 "The capture file is probably not fully dissected.",
3567 "End of capture exceeded.");
3570 return TRUE; /* success */
3572 return FALSE; /* failure */
3576 cf_goto_frame(capture_file *cf, guint fnumber)
3580 if (cf == NULL || cf->provider.frames == NULL) {
3581 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3582 statusbar_push_temporary_msg("There is no file loaded");
3583 return FALSE; /* we failed to go to that packet */
3586 fdata = frame_data_sequence_find(cf->provider.frames, fnumber);
3588 if (fdata == NULL) {
3589 /* we didn't find a packet with that packet number */
3590 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3591 return FALSE; /* we failed to go to that packet */
3593 if (!fdata->flags.passed_dfilter) {
3594 /* that packet currently isn't displayed */
3595 /* XXX - add it to the set of displayed packets? */
3596 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3597 return FALSE; /* we failed to go to that packet */
3600 if (!packet_list_select_row_from_data(fdata)) {
3601 /* We didn't find a row corresponding to this frame.
3602 This means that the frame isn't being displayed currently,
3603 so we can't select it. */
3604 simple_message_box(ESD_TYPE_INFO, NULL,
3605 "The capture file is probably not fully dissected.",
3606 "End of capture exceeded.");
3609 return TRUE; /* we got to that packet */
3613 * Go to frame specified by currently selected protocol tree item.
3616 cf_goto_framenum(capture_file *cf)
3618 header_field_info *hfinfo;
3621 if (cf->finfo_selected) {
3622 hfinfo = cf->finfo_selected->hfinfo;
3624 if (hfinfo->type == FT_FRAMENUM) {
3625 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3627 return cf_goto_frame(cf, framenum);
3634 /* Select the packet on a given row. */
3636 cf_select_packet(capture_file *cf, int row)
3638 epan_dissect_t *old_edt;
3641 /* Get the frame data struct pointer for this frame */
3642 fdata = packet_list_get_row_data(row);
3644 if (fdata == NULL) {
3648 /* Get the data in that frame. */
3649 if (!cf_read_record (cf, fdata)) {
3653 /* Record that this frame is the current frame. */
3654 cf->current_frame = fdata;
3655 cf->current_row = row;
3658 /* Create the logical protocol tree. */
3659 /* We don't need the columns here. */
3660 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3662 tap_build_interesting(cf->edt);
3663 epan_dissect_run(cf->edt, cf->cd_t, &cf->rec,
3664 frame_tvbuff_new_buffer(&cf->provider, cf->current_frame, &cf->buf),
3665 cf->current_frame, NULL);
3667 dfilter_macro_build_ftv_cache(cf->edt->tree);
3669 cf_callback_invoke(cf_cb_packet_selected, cf);
3671 if (old_edt != NULL)
3672 epan_dissect_free(old_edt);
3676 /* Unselect the selected packet, if any. */
3678 cf_unselect_packet(capture_file *cf)
3680 epan_dissect_t *old_edt = cf->edt;
3684 /* No packet is selected. */
3685 cf->current_frame = NULL;
3686 cf->current_row = 0;
3688 cf_callback_invoke(cf_cb_packet_unselected, cf);
3690 /* No protocol tree means no selected field. */
3691 cf_unselect_field(cf);
3693 /* Destroy the epan_dissect_t for the unselected packet. */
3694 if (old_edt != NULL)
3695 epan_dissect_free(old_edt);
3698 /* Unset the selected protocol tree field, if any. */
3700 cf_unselect_field(capture_file *cf)
3702 cf->finfo_selected = NULL;
3704 cf_callback_invoke(cf_cb_field_unselected, cf);
3708 * Mark a particular frame.
3711 cf_mark_frame(capture_file *cf, frame_data *frame)
3713 if (! frame->flags.marked) {
3714 frame->flags.marked = TRUE;
3715 if (cf->count > cf->marked_count)
3721 * Unmark a particular frame.
3724 cf_unmark_frame(capture_file *cf, frame_data *frame)
3726 if (frame->flags.marked) {
3727 frame->flags.marked = FALSE;
3728 if (cf->marked_count > 0)
3734 * Ignore a particular frame.
3737 cf_ignore_frame(capture_file *cf, frame_data *frame)
3739 if (! frame->flags.ignored) {
3740 frame->flags.ignored = TRUE;
3741 if (cf->count > cf->ignored_count)
3742 cf->ignored_count++;
3747 * Un-ignore a particular frame.
3750 cf_unignore_frame(capture_file *cf, frame_data *frame)
3752 if (frame->flags.ignored) {
3753 frame->flags.ignored = FALSE;
3754 if (cf->ignored_count > 0)
3755 cf->ignored_count--;
3760 * Read the section comment.
3763 cf_read_section_comment(capture_file *cf)
3765 wtap_block_t shb_inf;
3769 /* XXX - support multiple SHBs */
3770 shb_inf = wtap_file_get_shb(cf->provider.wth);
3772 /* Get the first comment from the SHB. */
3773 /* XXX - support multiple comments */
3774 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3780 * Modify the section comment.
3783 cf_update_section_comment(capture_file *cf, gchar *comment)
3785 wtap_block_t shb_inf;
3789 /* XXX - support multiple SHBs */
3790 shb_inf = wtap_file_get_shb(cf->provider.wth);
3792 /* Get the first comment from the SHB. */
3793 /* XXX - support multiple comments */
3794 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3795 /* There's no comment - add one. */
3796 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3798 /* See if the comment has changed or not */
3799 if (strcmp(shb_comment, comment) == 0) {
3804 /* The comment has changed, let's update it */
3805 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3807 /* Mark the file as having unsaved changes */
3808 cf->unsaved_changes = TRUE;
3812 * Get the comment on a packet (record).
3813 * If the comment has been edited, it returns the result of the edit,
3814 * otherwise it returns the comment from the file.
3817 cf_get_packet_comment(capture_file *cf, const frame_data *fd)
3821 /* fetch user comment */
3822 if (fd->flags.has_user_comment)
3823 return g_strdup(cap_file_provider_get_user_comment(&cf->provider, fd));
3825 /* fetch phdr comment */
3826 if (fd->flags.has_phdr_comment) {
3827 wtap_rec rec; /* Record metadata */
3828 Buffer buf; /* Record data */
3830 wtap_rec_init(&rec);
3831 ws_buffer_init(&buf, 1500);
3833 if (!cf_read_record_r(cf, fd, &rec, &buf))
3834 { /* XXX, what we can do here? */ }
3836 comment = rec.opt_comment;
3837 wtap_rec_cleanup(&rec);
3838 ws_buffer_free(&buf);
3845 * Update(replace) the comment on a capture from a frame
3848 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3850 char *pkt_comment = cf_get_packet_comment(cf, fd);
3852 /* Check if the comment has changed */
3853 if (!g_strcmp0(pkt_comment, new_comment)) {
3854 g_free(pkt_comment);
3857 g_free(pkt_comment);
3860 cf->packet_comment_count--;
3863 cf->packet_comment_count++;
3865 cap_file_provider_set_user_comment(&cf->provider, fd, new_comment);
3867 expert_update_comment_count(cf->packet_comment_count);
3869 /* OK, we have unsaved changes. */
3870 cf->unsaved_changes = TRUE;
3875 * What types of comments does this capture file have?
3878 cf_comment_types(capture_file *cf)
3880 guint32 comment_types = 0;
3882 if (cf_read_section_comment(cf) != NULL)
3883 comment_types |= WTAP_COMMENT_PER_SECTION;
3884 if (cf->packet_comment_count != 0)
3885 comment_types |= WTAP_COMMENT_PER_PACKET;
3886 return comment_types;
3890 * Add a resolved address to this file's list of resolved addresses.
3893 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
3896 * XXX - support multiple resolved address lists, and add to the one
3897 * attached to this file?
3899 if (!add_ip_name_from_string(addr, name))
3902 /* OK, we have unsaved changes. */
3903 cf->unsaved_changes = TRUE;
3911 } save_callback_args_t;
3914 * Save a capture to a file, in a particular format, saving either
3915 * all packets, all currently-displayed packets, or all marked packets.
3917 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3918 * up a message box for the failure.
3921 save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec,
3922 const guint8 *pd, void *argsp)
3924 save_callback_args_t *args = (save_callback_args_t *)argsp;
3928 const char *pkt_comment;
3930 /* Copy the record information from what was read in from the file. */
3933 /* Make changes based on anything that the user has done but that
3934 hasn't been saved yet. */
3935 if (fdata->flags.has_user_comment)
3936 pkt_comment = cap_file_provider_get_user_comment(&cf->provider, fdata);
3938 pkt_comment = rec->opt_comment;
3939 new_rec.opt_comment = g_strdup(pkt_comment);
3940 new_rec.has_comment_changed = fdata->flags.has_user_comment ? TRUE : FALSE;
3941 /* XXX - what if times have been shifted? */
3943 /* and save the packet */
3944 if (!wtap_dump(args->pdh, &new_rec, pd, &err, &err_info)) {
3945 cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
3950 g_free(new_rec.opt_comment);
3955 * Can this capture file be written out in any format using Wiretap
3956 * rather than by copying the raw data?
3959 cf_can_write_with_wiretap(capture_file *cf)
3961 /* We don't care whether we support the comments in this file or not;
3962 if we can't, we'll offer the user the option of discarding the
3964 return wtap_dump_can_write(cf->linktypes, 0);
3968 * Should we let the user do a save?
3972 * the file has unsaved changes, and we can save it in some
3973 * format through Wiretap
3977 * the file is a temporary file and has no unsaved changes (so
3978 * that "saving" it just means copying it).
3980 * XXX - we shouldn't allow files to be edited if they can't be saved,
3981 * so cf->unsaved_changes should be true only if the file can be saved.
3983 * We don't care whether we support the comments in this file or not;
3984 * if we can't, we'll offer the user the option of discarding the
3988 cf_can_save(capture_file *cf)
3990 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
3991 /* Saved changes, and we can write it out with Wiretap. */
3995 if (cf->is_tempfile && !cf->unsaved_changes) {
3997 * Temporary file with no unsaved changes, so we can just do a
4003 /* Nothing to save. */
4008 * Should we let the user do a "save as"?
4012 * we can save it in some format through Wiretap
4016 * the file is a temporary file and has no unsaved changes (so
4017 * that "saving" it just means copying it).
4019 * XXX - we shouldn't allow files to be edited if they can't be saved,
4020 * so cf->unsaved_changes should be true only if the file can be saved.
4022 * We don't care whether we support the comments in this file or not;
4023 * if we can't, we'll offer the user the option of discarding the
4027 cf_can_save_as(capture_file *cf)
4029 if (wtap_dump_can_write(cf->linktypes, 0)) {
4030 /* We can write it out with Wiretap. */
4034 if (cf->is_tempfile && !cf->unsaved_changes) {
4036 * Temporary file with no unsaved changes, so we can just do a
4042 /* Nothing to save. */
4047 * Does this file have unsaved data?
4050 cf_has_unsaved_data(capture_file *cf)
4053 * If this is a temporary file, or a file with unsaved changes, it
4056 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4060 * Quick scan to find packet offsets.
4062 static cf_read_status_t
4063 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4065 const wtap_rec *rec;
4070 progdlg_t *progbar = NULL;
4071 GTimer *prog_timer = g_timer_new();
4074 GTimeVal start_time;
4075 gchar status_str[100];
4080 /* Close the old handle. */
4081 wtap_close(cf->provider.wth);
4083 /* Open the new file. */
4084 /* XXX: this will go through all open_routines for a matching one. But right
4085 now rescan_file() is only used when a file is being saved to a different
4086 format than the original, and the user is not given a choice of which
4087 reader to use (only which format to save it in), so doing this makes
4089 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4090 if (cf->provider.wth == NULL) {
4091 cfile_open_failure_alert_box(fname, err, err_info);
4092 return CF_READ_ERROR;
4095 /* We're scanning a file whose contents should be the same as what
4096 we had before, so we don't discard dissection state etc.. */
4099 /* Set the file name because we need it to set the follow stream filter.
4100 XXX - is that still true? We need it for other reasons, though,
4102 cf->filename = g_strdup(fname);
4104 /* Indicate whether it's a permanent or temporary file. */
4105 cf->is_tempfile = is_tempfile;
4107 /* No user changes yet. */
4108 cf->unsaved_changes = FALSE;
4110 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
4111 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4113 cf->snap = wtap_snapshot_length(cf->provider.wth);
4115 name_ptr = g_filename_display_basename(cf->filename);
4117 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4119 /* Record whether the file is compressed.
4120 XXX - do we know this at open time? */
4121 cf->iscompressed = wtap_iscompressed(cf->provider.wth);
4123 /* Find the size of the file. */
4124 size = wtap_file_size(cf->provider.wth, NULL);
4126 g_timer_start(prog_timer);
4128 cf->stop_flag = FALSE;
4129 g_get_current_time(&start_time);
4132 rec = wtap_get_rec(cf->provider.wth);
4133 while ((wtap_read(cf->provider.wth, &err, &err_info, &data_offset))) {
4135 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4136 fdata->file_off = data_offset;
4139 cf->f_datalen = wtap_read_so_far(cf->provider.wth);
4141 /* Create the progress bar if necessary. */
4142 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4143 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4144 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4145 TRUE, &cf->stop_flag, &start_time, progbar_val);
4149 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4150 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4151 * likely trigger UI paint events, which might take a while depending on
4152 * the platform and display. Reset our timer *after* painting.
4154 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4155 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4156 /* update the packet bar content on the first run or frequently on very large files */
4157 update_progress_dlg(progbar, progbar_val, status_str);
4158 compute_elapsed(cf, &start_time);
4159 packets_bar_update();
4160 g_timer_start(prog_timer);
4164 if (cf->stop_flag) {
4165 /* Well, the user decided to abort the rescan. Sadly, as this
4166 isn't a reread, recovering is difficult, so we'll just
4167 close the current capture. */
4171 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4172 it's not already there.
4173 XXX - yes, this is O(N), so if every packet had a different
4174 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4175 there are probably going to be a small number of encapsulation types
4177 if (rec->rec_type == REC_TYPE_PACKET) {
4178 cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap);
4182 /* Free the display name */
4185 /* We're done reading the file; destroy the progress bar if it was created. */
4186 if (progbar != NULL)
4187 destroy_progress_dlg(progbar);
4188 g_timer_destroy(prog_timer);
4190 /* We're done reading sequentially through the file. */
4191 cf->state = FILE_READ_DONE;
4193 /* Close the sequential I/O side, to free up memory it requires. */
4194 wtap_sequential_close(cf->provider.wth);
4196 /* compute the time it took to load the file */
4197 compute_elapsed(cf, &start_time);
4199 /* Set the file encapsulation type now; we don't know what it is until
4200 we've looked at all the packets, as we don't know until then whether
4201 there's more than one type (and thus whether it's
4202 WTAP_ENCAP_PER_PACKET). */
4203 cf->lnk_t = wtap_file_encap(cf->provider.wth);
4205 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4207 if (cf->stop_flag) {
4208 /* Our caller will give up at this point. */
4209 return CF_READ_ABORTED;
4213 /* Put up a message box noting that the read failed somewhere along
4214 the line. Don't throw out the stuff we managed to read, though,
4216 cfile_read_failure_alert_box(NULL, err, err_info);
4217 return CF_READ_ERROR;
4223 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4224 gboolean compressed, gboolean discard_comments,
4225 gboolean dont_reopen)
4228 gchar *fname_new = NULL;
4231 addrinfo_lists_t *addr_lists;
4235 gchar *display_basename;
4242 save_callback_args_t callback_args;
4243 gboolean needs_reload = FALSE;
4245 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4247 addr_lists = get_addrinfo_list();
4249 if (save_format == cf->cd_t && compressed == cf->iscompressed
4250 && !discard_comments && !cf->unsaved_changes
4251 && (wtap_addrinfo_list_empty(addr_lists) || !wtap_dump_has_name_resolution(save_format))) {
4252 /* We're saving in the format it's already in, and we're not discarding
4253 comments, and there are no changes we have in memory that aren't saved
4254 to the file, and we have no name resolution information to write or
4255 the file format we're saving in doesn't support writing name
4256 resolution information, so we can just move or copy the raw data. */
4258 if (cf->is_tempfile) {
4259 /* The file being saved is a temporary file from a live
4260 capture, so it doesn't need to stay around under that name;
4261 first, try renaming the capture buffer file to the new name.
4262 This acts as a "safe save", in that, if the file already
4263 exists, the existing file will be removed only if the rename
4266 Sadly, on Windows, as we have the current capture file
4267 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4268 (to cause the rename to remove an existing target), as
4269 done by ws_stdio_rename() (ws_rename() is #defined to
4270 be ws_stdio_rename() on Windows) will fail.
4272 According to the MSDN documentation for CreateFile(), if,
4273 when we open a capture file, we were to directly do a CreateFile(),
4274 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4275 convert it to a file descriptor with _open_osfhandle(),
4276 that would allow the file to be renamed out from under us.
4278 However, that doesn't work in practice. Perhaps the problem
4279 is that the process doing the rename is the process that
4280 has the file open. */
4282 if (ws_rename(cf->filename, fname) == 0) {
4283 /* That succeeded - there's no need to copy the source file. */
4284 how_to_save = SAVE_WITH_MOVE;
4286 if (errno == EXDEV) {
4287 /* They're on different file systems, so we have to copy the
4289 how_to_save = SAVE_WITH_COPY;
4291 /* The rename failed, but not because they're on different
4292 file systems - put up an error message. (Or should we
4293 just punt and try to copy? The only reason why I'd
4294 expect the rename to fail and the copy to succeed would
4295 be if we didn't have permission to remove the file from
4296 the temporary directory, and that might be fixable - but
4297 is it worth requiring the user to go off and fix it?) */
4298 cf_rename_failure_alert_box(fname, errno);
4303 /* Windows - copy the file to its new location. */
4304 how_to_save = SAVE_WITH_COPY;
4307 /* It's a permanent file, so we should copy it, and not remove the
4309 how_to_save = SAVE_WITH_COPY;
4312 if (how_to_save == SAVE_WITH_COPY) {
4313 /* Copy the file, if we haven't moved it. If we're overwriting
4314 an existing file, we do it with a "safe save", by writing
4315 to a new file and, if the write succeeds, renaming the
4316 new file on top of the old file. */
4317 if (file_exists(fname)) {
4318 fname_new = g_strdup_printf("%s~", fname);
4319 if (!copy_file_binary_mode(cf->filename, fname_new))
4322 if (!copy_file_binary_mode(cf->filename, fname))
4327 /* Either we're saving in a different format or we're saving changes,
4328 such as added, modified, or removed comments, that haven't yet
4329 been written to the underlying file; we can't do that by copying
4330 or moving the capture file, we have to do it by writing the packets
4333 GArray *shb_hdrs = NULL;
4334 wtapng_iface_descriptions_t *idb_inf = NULL;
4335 GArray *nrb_hdrs = NULL;
4338 /* XXX: what free's this shb_hdr? */
4339 shb_hdrs = wtap_file_get_shb_for_new_file(cf->provider.wth);
4340 idb_inf = wtap_file_get_idb_info(cf->provider.wth);
4341 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->provider.wth);
4343 /* Determine what file encapsulation type we should use. */
4344 encap = wtap_dump_file_encap_type(cf->linktypes);
4346 if (file_exists(fname)) {
4347 /* We're overwriting an existing file; write out to a new file,
4348 and, if that succeeds, rename the new file on top of the
4349 old file. That makes this a "safe save", so that we don't
4350 lose the old file if we have a problem writing out the new
4351 file. (If the existing file is the current capture file,
4352 we *HAVE* to do that, otherwise we're overwriting the file
4353 from which we're reading the packets that we're writing!) */
4354 fname_new = g_strdup_printf("%s~", fname);
4355 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4356 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4358 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4359 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4365 cfile_dump_open_failure_alert_box(fname, err, save_format);
4369 /* Add address resolution */
4370 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4372 /* Iterate through the list of packets, processing all the packets. */
4373 callback_args.pdh = pdh;
4374 callback_args.fname = fname;
4375 callback_args.file_type = save_format;
4376 switch (process_specified_records(cf, NULL, "Saving", "packets",
4377 TRUE, save_record, &callback_args, TRUE)) {
4380 /* Completed successfully. */
4384 /* The user decided to abort the saving.
4385 If we're writing to a temporary file, remove it.
4386 XXX - should we do so even if we're not writing to a
4388 wtap_dump_close(pdh, &err);
4389 if (fname_new != NULL)
4390 ws_unlink(fname_new);
4391 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4392 return CF_WRITE_ABORTED;
4395 /* Error while saving.
4396 If we're writing to a temporary file, remove it. */
4397 if (fname_new != NULL)
4398 ws_unlink(fname_new);
4399 wtap_dump_close(pdh, &err);
4403 needs_reload = wtap_dump_get_needs_reload(pdh);
4405 if (!wtap_dump_close(pdh, &err)) {
4406 cfile_close_failure_alert_box(fname, err);
4410 how_to_save = SAVE_WITH_WTAP;
4413 if (fname_new != NULL) {
4414 /* We wrote out to fname_new, and should rename it on top of
4415 fname. fname_new is now closed, so that should be possible even
4416 on Windows. However, on Windows, we first need to close whatever
4417 file descriptors we have open for fname. */
4419 wtap_fdclose(cf->provider.wth);
4421 /* Now do the rename. */
4422 if (ws_rename(fname_new, fname) == -1) {
4423 /* Well, the rename failed. */
4424 cf_rename_failure_alert_box(fname, errno);
4426 /* Attempt to reopen the random file descriptor using the
4427 current file's filename. (At this point, the sequential
4428 file descriptor is closed.) */
4429 if (!wtap_fdreopen(cf->provider.wth, cf->filename, &err)) {
4430 /* Oh, well, we're screwed. */
4431 display_basename = g_filename_display_basename(cf->filename);
4432 simple_error_message_box(
4433 file_open_error_message(err, FALSE), display_basename);
4434 g_free(display_basename);
4441 /* If this was a temporary file, and we didn't do the save by doing
4442 a move, so the tempoary file is still around under its old name,
4444 if (cf->is_tempfile && how_to_save != SAVE_WITH_MOVE) {
4445 /* If this fails, there's not much we can do, so just ignore errors. */
4446 ws_unlink(cf->filename);
4449 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4450 cf->unsaved_changes = FALSE;
4453 switch (how_to_save) {
4455 case SAVE_WITH_MOVE:
4456 /* We just moved the file, so the wtap structure refers to the
4457 new file, and all the information other than the filename
4458 and the "is temporary" status applies to the new file; just
4460 g_free(cf->filename);
4461 cf->filename = g_strdup(fname);
4462 cf->is_tempfile = FALSE;
4463 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4466 case SAVE_WITH_COPY:
4467 /* We just copied the file, so all the information other than
4468 the wtap structure, the filename, and the "is temporary"
4469 status applies to the new file; just update that. */
4470 wtap_close(cf->provider.wth);
4471 /* Although we're just "copying" and then opening the copy, it will
4472 try all open_routine readers to open the copy, so we need to
4473 reset the cfile's open_type. */
4474 cf->open_type = WTAP_TYPE_AUTO;
4475 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4476 if (cf->provider.wth == NULL) {
4477 cfile_open_failure_alert_box(fname, err, err_info);
4480 g_free(cf->filename);
4481 cf->filename = g_strdup(fname);
4482 cf->is_tempfile = FALSE;
4484 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4487 case SAVE_WITH_WTAP:
4488 /* Open and read the file we saved to.
4490 XXX - this is somewhat of a waste; we already have the
4491 packets, all this gets us is updated file type information
4492 (which we could just stuff into "cf"), and having the new
4493 file be the one we have opened and from which we're reading
4494 the data, and it means we have to spend time opening and
4495 reading the file, which could be a significant amount of
4496 time if the file is large.
4498 If the capture-file-writing code were to return the
4499 seek offset of each packet it writes, we could save that
4500 in the frame_data structure for the frame, and just open
4501 the file without reading it again...
4503 ...as long as, for gzipped files, the process of writing
4504 out the file *also* generates the information needed to
4505 support fast random access to the compressed file. */
4506 /* rescan_file will cause us to try all open_routines, so
4507 reset cfile's open_type */
4508 cf->open_type = WTAP_TYPE_AUTO;
4509 /* There are cases when SAVE_WITH_WTAP can result in new packets
4510 being written to the file, e.g ERF records
4511 In that case, we need to reload the whole file */
4513 if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) {
4514 if (cf_read(cf, TRUE) != CF_READ_OK) {
4515 /* The rescan failed; just close the file. Either
4516 a dialog was popped up for the failure, so the
4517 user knows what happened, or they stopped the
4518 rescan, in which case they know what happened. */
4519 /* XXX: This is inconsistent with normal open/reload behaviour. */
4525 if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4526 /* The rescan failed; just close the file. Either
4527 a dialog was popped up for the failure, so the
4528 user knows what happened, or they stopped the
4529 rescan, in which case they know what happened. */
4536 /* If we were told to discard the comments, do so. */
4537 if (discard_comments) {
4538 /* Remove SHB comment, if any. */
4539 wtap_write_shb_comment(cf->provider.wth, NULL);
4541 /* remove all user comments */
4542 for (framenum = 1; framenum <= cf->count; framenum++) {
4543 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4545 fdata->flags.has_phdr_comment = FALSE;
4546 fdata->flags.has_user_comment = FALSE;
4549 if (cf->provider.frames_user_comments) {
4550 g_tree_destroy(cf->provider.frames_user_comments);
4551 cf->provider.frames_user_comments = NULL;
4554 cf->packet_comment_count = 0;
4560 if (fname_new != NULL) {
4561 /* We were trying to write to a temporary file; get rid of it if it
4562 exists. (We don't care whether this fails, as, if it fails,
4563 there's not much we can do about it. I guess if it failed for
4564 a reason other than "it doesn't exist", we could report an
4565 error, so the user knows there's a junk file that they might
4566 want to clean up.) */
4567 ws_unlink(fname_new);
4570 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4571 return CF_WRITE_ERROR;
4575 cf_export_specified_packets(capture_file *cf, const char *fname,
4576 packet_range_t *range, guint save_format,
4577 gboolean compressed)
4579 gchar *fname_new = NULL;
4582 save_callback_args_t callback_args;
4583 GArray *shb_hdrs = NULL;
4584 wtapng_iface_descriptions_t *idb_inf = NULL;
4585 GArray *nrb_hdrs = NULL;
4588 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4590 packet_range_process_init(range);
4592 /* We're writing out specified packets from the specified capture
4593 file to another file. Even if all captured packets are to be
4594 written, don't special-case the operation - read each packet
4595 and then write it out if it's one of the specified ones. */
4597 /* XXX: what free's this shb_hdr? */
4598 shb_hdrs = wtap_file_get_shb_for_new_file(cf->provider.wth);
4599 idb_inf = wtap_file_get_idb_info(cf->provider.wth);
4600 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->provider.wth);
4602 /* Determine what file encapsulation type we should use. */
4603 encap = wtap_dump_file_encap_type(cf->linktypes);
4605 if (file_exists(fname)) {
4606 /* We're overwriting an existing file; write out to a new file,
4607 and, if that succeeds, rename the new file on top of the
4608 old file. That makes this a "safe save", so that we don't
4609 lose the old file if we have a problem writing out the new
4610 file. (If the existing file is the current capture file,
4611 we *HAVE* to do that, otherwise we're overwriting the file
4612 from which we're reading the packets that we're writing!) */
4613 fname_new = g_strdup_printf("%s~", fname);
4614 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4615 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4617 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4618 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4624 cfile_dump_open_failure_alert_box(fname, err, save_format);
4628 /* Add address resolution */
4629 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4631 /* Iterate through the list of packets, processing the packets we were
4634 XXX - we've already called "packet_range_process_init(range)", but
4635 "process_specified_records()" will do it again. Fortunately,
4636 that's harmless in this case, as we haven't done anything to
4637 "range" since we initialized it. */
4638 callback_args.pdh = pdh;
4639 callback_args.fname = fname;
4640 callback_args.file_type = save_format;
4641 switch (process_specified_records(cf, range, "Writing", "specified records",
4642 TRUE, save_record, &callback_args, TRUE)) {
4645 /* Completed successfully. */
4649 /* The user decided to abort the saving.
4650 If we're writing to a temporary file, remove it.
4651 XXX - should we do so even if we're not writing to a
4653 wtap_dump_close(pdh, &err);
4654 if (fname_new != NULL)
4655 ws_unlink(fname_new);
4656 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4657 return CF_WRITE_ABORTED;
4661 /* Error while saving.
4662 If we're writing to a temporary file, remove it. */
4663 if (fname_new != NULL)
4664 ws_unlink(fname_new);
4665 wtap_dump_close(pdh, &err);
4669 if (!wtap_dump_close(pdh, &err)) {
4670 cfile_close_failure_alert_box(fname, err);
4674 if (fname_new != NULL) {
4675 /* We wrote out to fname_new, and should rename it on top of
4676 fname; fname is now closed, so that should be possible even
4677 on Windows. Do the rename. */
4678 if (ws_rename(fname_new, fname) == -1) {
4679 /* Well, the rename failed. */
4680 cf_rename_failure_alert_box(fname, errno);
4685 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4689 if (fname_new != NULL) {
4690 /* We were trying to write to a temporary file; get rid of it if it
4691 exists. (We don't care whether this fails, as, if it fails,
4692 there's not much we can do about it. I guess if it failed for
4693 a reason other than "it doesn't exist", we could report an
4694 error, so the user knows there's a junk file that they might
4695 want to clean up.) */
4696 ws_unlink(fname_new);
4699 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4700 return CF_WRITE_ERROR;
4704 * XXX - whether we mention the source pathname, the target pathname,
4705 * or both depends on the error and on what we find if we look for
4706 * one or both of them.
4709 cf_rename_failure_alert_box(const char *filename, int err)
4711 gchar *display_basename;
4713 display_basename = g_filename_display_basename(filename);
4717 /* XXX - should check whether the source exists and, if not,
4718 report it as the problem and, if so, report the destination
4720 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4725 /* XXX - if we're doing a rename after a safe save, we should
4726 probably say something else. */
4727 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4732 /* XXX - this should probably mention both the source and destination
4734 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4735 display_basename, wtap_strerror(err));
4738 g_free(display_basename);
4741 /* Reload the current capture file. */
4743 cf_reload(capture_file *cf) {
4745 gboolean is_tempfile;
4748 /* If the file could be opened, "cf_open()" calls "cf_close()"
4749 to get rid of state for the old capture file before filling in state
4750 for the new capture file. "cf_close()" will remove the file if
4751 it's a temporary file; we don't want that to happen (for one thing,
4752 it'd prevent subsequent reopens from working). Remember whether it's
4753 a temporary file, mark it as not being a temporary file, and then
4754 reopen it as the type of file it was.
4756 Also, "cf_close()" will free "cf->filename", so we must make
4757 a copy of it first. */
4758 filename = g_strdup(cf->filename);
4759 is_tempfile = cf->is_tempfile;
4760 cf->is_tempfile = FALSE;
4761 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4762 switch (cf_read(cf, TRUE)) {
4766 /* Just because we got an error, that doesn't mean we were unable
4767 to read any of the file; we handle what we could get from the
4771 case CF_READ_ABORTED:
4772 /* The user bailed out of re-reading the capture file; the
4773 capture file has been closed - just free the capture file name
4774 string and return (without changing the last containing
4780 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4781 Instead, the file was left open, so we should restore "cf->is_tempfile"
4784 XXX - change the menu? Presumably "cf_open()" will do that;
4785 make sure it does! */
4786 cf->is_tempfile = is_tempfile;
4788 /* "cf_open()" made a copy of the file name we handed it, so
4789 we should free up our copy. */
4799 * indent-tabs-mode: nil
4802 * ex: set shiftwidth=2 tabstop=8 expandtab:
4803 * :indentSize=2:tabSize=8:noTabs=true: