4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0+
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-int.h>
30 #include <epan/epan.h>
31 #include <epan/column.h>
32 #include <epan/packet.h>
33 #include <epan/column-utils.h>
34 #include <epan/expert.h>
35 #include <epan/prefs.h>
36 #include <epan/dfilter/dfilter.h>
37 #include <epan/epan_dissect.h>
39 #include <epan/dissectors/packet-ber.h>
40 #include <epan/timestamp.h>
41 #include <epan/dfilter/dfilter-macro.h>
42 #include <epan/strutil.h>
43 #include <epan/addr_resolv.h>
44 #include <epan/color_filters.h>
47 #include "cfile-int.h"
50 #include "frame_tvbuff.h"
52 #include "ui/alert_box.h"
53 #include "ui/simple_dialog.h"
54 #include "ui/main_statusbar.h"
55 #include "ui/progress_dlg.h"
56 #include "ui/ws_ui_util.h"
58 /* Needed for addrinfo */
59 #ifdef HAVE_SYS_TYPES_H
60 # include <sys/types.h>
63 #ifdef HAVE_SYS_SOCKET_H
64 #include <sys/socket.h>
67 #ifdef HAVE_NETINET_IN_H
68 # include <netinet/in.h>
72 # include <winsock2.h>
73 # include <ws2tcpip.h>
77 gboolean auto_scroll_live; /* GTK+ only? */
80 static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
81 column_info *cinfo, gint64 offset);
83 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
90 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
92 static void match_subtree_text(proto_node *node, gpointer data);
93 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
95 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
97 static match_result match_narrow(capture_file *cf, frame_data *fdata,
99 static match_result match_wide(capture_file *cf, frame_data *fdata,
101 static match_result match_binary(capture_file *cf, frame_data *fdata,
103 static match_result match_regex(capture_file *cf, frame_data *fdata,
105 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
107 static match_result match_marked(capture_file *cf, frame_data *fdata,
109 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
111 static gboolean find_packet(capture_file *cf,
112 match_result (*match_function)(capture_file *, frame_data *, void *),
113 void *criterion, search_direction dir);
115 static const char *cf_get_user_packet_comment(frame_set *fs, const frame_data *fd);
117 static void cf_rename_failure_alert_box(const char *filename, int err);
118 static void ref_time_packets(capture_file *cf);
120 /* Seconds spent processing packets between pushing UI updates. */
121 #define PROGBAR_UPDATE_INTERVAL 0.150
123 /* Show the progress bar after this many seconds. */
124 #define PROGBAR_SHOW_DELAY 0.5
127 * We could probably use g_signal_...() instead of the callbacks below but that
128 * would require linking our CLI programs to libgobject and creating an object
129 * instance for the signals.
132 cf_callback_t cb_fct;
134 } cf_callback_data_t;
136 static GList *cf_callbacks = NULL;
139 cf_callback_invoke(int event, gpointer data)
141 cf_callback_data_t *cb;
142 GList *cb_item = cf_callbacks;
144 /* there should be at least one interested */
145 g_assert(cb_item != NULL);
147 while (cb_item != NULL) {
148 cb = (cf_callback_data_t *)cb_item->data;
149 cb->cb_fct(event, data, cb->user_data);
150 cb_item = g_list_next(cb_item);
156 cf_callback_add(cf_callback_t func, gpointer user_data)
158 cf_callback_data_t *cb;
160 cb = g_new(cf_callback_data_t,1);
162 cb->user_data = user_data;
164 cf_callbacks = g_list_prepend(cf_callbacks, cb);
168 cf_callback_remove(cf_callback_t func, gpointer user_data)
170 cf_callback_data_t *cb;
171 GList *cb_item = cf_callbacks;
173 while (cb_item != NULL) {
174 cb = (cf_callback_data_t *)cb_item->data;
175 if (cb->cb_fct == func && cb->user_data == user_data) {
176 cf_callbacks = g_list_remove(cf_callbacks, cb);
180 cb_item = g_list_next(cb_item);
183 g_assert_not_reached();
187 cf_timestamp_auto_precision(capture_file *cf)
191 /* don't try to get the file's precision if none is opened */
192 if (cf->state == FILE_CLOSED) {
196 /* Set the column widths of those columns that show the time in
197 "command-line-specified" format. */
198 for (i = 0; i < cf->cinfo.num_cols; i++) {
199 if (col_has_time_fmt(&cf->cinfo, i)) {
200 packet_list_resize_column(i);
206 cf_get_computed_elapsed(capture_file *cf)
208 return cf->computed_elapsed;
212 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
215 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
220 g_get_current_time(&time_now);
222 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
223 time_now.tv_usec - start_time->tv_usec;
225 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
228 static const nstime_t *
229 ws_get_frame_ts(frame_set *fs, guint32 frame_num)
231 if (fs->prev_dis && fs->prev_dis->num == frame_num)
232 return &fs->prev_dis->abs_ts;
234 if (fs->prev_cap && fs->prev_cap->num == frame_num)
235 return &fs->prev_cap->abs_ts;
238 frame_data *fd = frame_data_sequence_find(fs->frames, frame_num);
240 return (fd) ? &fd->abs_ts : NULL;
247 ws_get_user_comment(frame_set *fs, const frame_data *fd)
249 return cf_get_user_packet_comment(fs, fd);
253 ws_epan_new(capture_file *cf)
255 epan_t *epan = epan_new();
257 epan->fs = &cf->frame_set_info;
258 epan->get_frame_ts = ws_get_frame_ts;
259 epan->get_interface_name = frame_set_get_interface_name;
260 epan->get_interface_description = frame_set_get_interface_description;
261 epan->get_user_comment = ws_get_user_comment;
267 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
272 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
276 /* The open succeeded. Close whatever capture file we had open,
277 and fill in the information for this file. */
280 /* Initialize the packet header. */
281 wtap_phdr_init(&cf->phdr);
283 /* XXX - we really want to initialize this after we've read all
284 the packets, so we know how much we'll ultimately need. */
285 ws_buffer_init(&cf->buf, 1500);
287 /* Create new epan session for dissection.
288 * (The old one was freed in cf_close().)
290 cf->epan = ws_epan_new(cf);
292 /* We're about to start reading the file. */
293 cf->state = FILE_READ_IN_PROGRESS;
295 cf->frame_set_info.wth = wth;
298 /* Set the file name because we need it to set the follow stream filter.
299 XXX - is that still true? We need it for other reasons, though,
301 cf->filename = g_strdup(fname);
303 /* Indicate whether it's a permanent or temporary file. */
304 cf->is_tempfile = is_tempfile;
306 /* No user changes yet. */
307 cf->unsaved_changes = FALSE;
309 cf->computed_elapsed = 0;
311 cf->cd_t = wtap_file_type_subtype(cf->frame_set_info.wth);
312 cf->open_type = type;
313 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
315 cf->packet_comment_count = 0;
316 cf->displayed_count = 0;
317 cf->marked_count = 0;
318 cf->ignored_count = 0;
319 cf->ref_time_count = 0;
320 cf->drops_known = FALSE;
322 cf->snap = wtap_snapshot_length(cf->frame_set_info.wth);
324 /* Allocate a frame_data_sequence for the frames in this file */
325 cf->frame_set_info.frames = new_frame_data_sequence();
327 nstime_set_zero(&cf->elapsed_time);
328 cf->frame_set_info.ref = NULL;
329 cf->frame_set_info.prev_dis = NULL;
330 cf->frame_set_info.prev_cap = NULL;
333 packet_list_queue_draw();
334 cf_callback_invoke(cf_cb_file_opened, cf);
336 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
337 /* tell the BER dissector the file name */
338 ber_set_filename(cf->filename);
341 wtap_set_cb_new_ipv4(cf->frame_set_info.wth, add_ipv4_name);
342 wtap_set_cb_new_ipv6(cf->frame_set_info.wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
347 cfile_open_failure_alert_box(fname, *err, err_info);
352 * Add an encapsulation type to cf->linktypes.
355 cf_add_encapsulation_type(capture_file *cf, int encap)
359 for (i = 0; i < cf->linktypes->len; i++) {
360 if (g_array_index(cf->linktypes, gint, i) == encap)
361 return; /* it's already there */
363 /* It's not already there - add it. */
364 g_array_append_val(cf->linktypes, encap);
367 /* Reset everything to a pristine state */
369 cf_close(capture_file *cf)
371 cf->stop_flag = FALSE;
372 if (cf->state == FILE_CLOSED)
373 return; /* Nothing to do */
375 /* Die if we're in the middle of reading a file. */
376 g_assert(cf->state != FILE_READ_IN_PROGRESS);
378 cf_callback_invoke(cf_cb_file_closing, cf);
380 /* close things, if not already closed before */
381 color_filters_cleanup();
383 if (cf->frame_set_info.wth) {
384 wtap_close(cf->frame_set_info.wth);
385 cf->frame_set_info.wth = NULL;
387 /* We have no file open... */
388 if (cf->filename != NULL) {
389 /* If it's a temporary file, remove it. */
391 ws_unlink(cf->filename);
392 g_free(cf->filename);
395 /* ...which means we have no changes to that file to save. */
396 cf->unsaved_changes = FALSE;
398 /* no open_routine type */
399 cf->open_type = WTAP_TYPE_AUTO;
401 /* Clean up the packet header. */
402 wtap_phdr_cleanup(&cf->phdr);
404 /* Free up the packet buffer. */
405 ws_buffer_free(&cf->buf);
407 dfilter_free(cf->rfcode);
409 if (cf->frame_set_info.frames != NULL) {
410 free_frame_data_sequence(cf->frame_set_info.frames);
411 cf->frame_set_info.frames = NULL;
413 if (cf->frame_set_info.frames_user_comments) {
414 g_tree_destroy(cf->frame_set_info.frames_user_comments);
415 cf->frame_set_info.frames_user_comments = NULL;
417 cf_unselect_packet(cf); /* nothing to select */
418 cf->first_displayed = 0;
419 cf->last_displayed = 0;
421 /* No frames, no frame selected, no field in that frame selected. */
423 cf->current_frame = 0;
425 cf->finfo_selected = NULL;
427 /* No frame link-layer types, either. */
428 if (cf->linktypes != NULL) {
429 g_array_free(cf->linktypes, TRUE);
430 cf->linktypes = NULL;
433 /* Clear the packet list. */
434 packet_list_freeze();
439 nstime_set_zero(&cf->elapsed_time);
441 reset_tap_listeners();
446 /* We have no file open. */
447 cf->state = FILE_CLOSED;
449 cf_callback_invoke(cf_cb_file_closed, cf);
453 * TRUE if the progress dialog doesn't exist and it looks like we'll
454 * take > 2s to load, FALSE otherwise.
456 static inline gboolean
457 progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
461 if (progdlg) return FALSE;
462 elapsed = g_timer_elapsed(prog_timer, NULL);
463 if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
464 || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
471 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
475 progbar_val = (gfloat) file_pos / (gfloat) size;
476 if (progbar_val > 1.0) {
478 /* The file probably grew while we were reading it.
479 * Update file size, and try again.
481 size = wtap_file_size(cf->frame_set_info.wth, NULL);
484 progbar_val = (gfloat) file_pos / (gfloat) size;
486 /* If it's still > 1, either "wtap_file_size()" failed (in which
487 * case there's not much we can do about it), or the file
488 * *shrank* (in which case there's not much we can do about
489 * it); just clip the progress value at 1.0.
491 if (progbar_val > 1.0f)
495 g_snprintf(status_str, status_size,
496 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
497 file_pos / 1024, size / 1024);
503 cf_read(capture_file *cf, gboolean reloading)
506 gchar *err_info = NULL;
508 progdlg_t *volatile progbar = NULL;
509 GTimer *prog_timer = g_timer_new();
513 volatile gboolean create_proto_tree;
516 volatile gboolean is_read_aborted = FALSE;
518 /* Compile the current display filter.
519 * We assume this will not fail since cf->dfilter is only set in
520 * cf_filter IFF the filter was valid.
522 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
523 g_assert(!cf->dfilter || (compiled && dfcode));
525 /* Get the union of the flags for all tap listeners. */
526 tap_flags = union_of_tap_listener_flags();
529 * Determine whether we need to create a protocol tree.
532 * we're going to apply a display filter;
534 * one of the tap listeners is going to apply a filter;
536 * one of the tap listeners requires a protocol tree;
538 * a postdissector wants field values or protocols on
542 (dfcode != NULL || have_filtering_tap_listeners() ||
543 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
545 reset_tap_listeners();
547 name_ptr = g_filename_display_basename(cf->filename);
550 cf_callback_invoke(cf_cb_file_reload_started, cf);
552 cf_callback_invoke(cf_cb_file_read_started, cf);
554 /* Record whether the file is compressed.
555 XXX - do we know this at open time? */
556 cf->iscompressed = wtap_iscompressed(cf->frame_set_info.wth);
558 /* The packet list window will be empty until the file is completly loaded */
559 packet_list_freeze();
561 cf->stop_flag = FALSE;
562 g_get_current_time(&start_time);
564 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
574 gchar status_str[100];
578 /* If any tap listeners require the columns, construct them. */
579 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
581 /* Find the size of the file. */
582 size = wtap_file_size(cf->frame_set_info.wth, NULL);
584 g_timer_start(prog_timer);
586 while ((wtap_read(cf->frame_set_info.wth, &err, &err_info, &data_offset))) {
589 file_pos = wtap_read_so_far(cf->frame_set_info.wth);
591 /* Create the progress bar if necessary. */
592 if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
593 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
595 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
596 TRUE, &cf->stop_flag, &start_time, progbar_val);
598 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
599 TRUE, &cf->stop_flag, &start_time, progbar_val);
603 * Update the progress bar, but do it only after
604 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
605 * and packets_bar_update will likely trigger UI paint events, which
606 * might take a while depending on the platform and display. Reset
607 * our timer *after* painting.
609 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
610 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
611 /* update the packet bar content on the first run or frequently on very large files */
612 update_progress_dlg(progbar, progbar_val, status_str);
613 compute_elapsed(cf, &start_time);
614 packets_bar_update();
615 g_timer_start(prog_timer);
619 if (cf->state == FILE_READ_ABORTED) {
620 /* Well, the user decided to exit Wireshark. Break out of the
621 loop, and let the code below (which is called even if there
622 aren't any packets left to read) exit. */
623 is_read_aborted = TRUE;
627 /* Well, the user decided to abort the read. He/She will be warned and
628 it might be enough for him/her to work with the already loaded
630 This is especially true for very large capture files, where you don't
631 want to wait loading the whole file (which may last minutes or even
632 hours even on fast machines) just to see that it was the wrong file. */
635 read_packet(cf, dfcode, &edt, cinfo, data_offset);
638 CATCH(OutOfMemoryError) {
639 simple_message_box(ESD_TYPE_ERROR, NULL,
640 "More information and workarounds can be found at\n"
641 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
642 "Sorry, but Wireshark has run out of memory and has to terminate now.");
644 /* Could we close the current capture and free up memory from that? */
646 /* we have to terminate, as we cannot recover from the memory error */
652 /* Free the display name */
655 /* Cleanup and release all dfilter resources */
656 dfilter_free(dfcode);
658 epan_dissect_cleanup(&edt);
660 /* We're done reading the file; destroy the progress bar if it was created. */
662 destroy_progress_dlg(progbar);
663 g_timer_destroy(prog_timer);
665 /* We're done reading sequentially through the file. */
666 cf->state = FILE_READ_DONE;
668 /* Close the sequential I/O side, to free up memory it requires. */
669 wtap_sequential_close(cf->frame_set_info.wth);
671 /* Allow the protocol dissectors to free up memory that they
672 * don't need after the sequential run-through of the packets. */
673 postseq_cleanup_all_protocols();
675 /* compute the time it took to load the file */
676 compute_elapsed(cf, &start_time);
678 /* Set the file encapsulation type now; we don't know what it is until
679 we've looked at all the packets, as we don't know until then whether
680 there's more than one type (and thus whether it's
681 WTAP_ENCAP_PER_PACKET). */
682 cf->lnk_t = wtap_file_encap(cf->frame_set_info.wth);
684 cf->current_frame = frame_data_sequence_find(cf->frame_set_info.frames, cf->first_displayed);
689 cf_callback_invoke(cf_cb_file_reload_finished, cf);
691 cf_callback_invoke(cf_cb_file_read_finished, cf);
693 /* If we have any displayed packets to select, select the first of those
694 packets by making the first row the selected row. */
695 if (cf->first_displayed != 0) {
696 packet_list_select_first_row();
699 if (is_read_aborted) {
701 * Well, the user decided to exit Wireshark while reading this *offline*
702 * capture file (Live captures are handled by something like
703 * cf_continue_tail). Clean up accordingly.
706 return CF_READ_ABORTED;
710 simple_message_box(ESD_TYPE_WARN, NULL,
711 "The remaining packets in the file were discarded.\n"
713 "As a lot of packets from the original file will be missing,\n"
714 "remember to be careful when saving the current content to a file.\n",
715 "File loading was cancelled.");
716 return CF_READ_ERROR;
720 /* Put up a message box noting that the read failed somewhere along
721 the line. Don't throw out the stuff we managed to read, though,
723 cfile_read_failure_alert_box(NULL, err, err_info);
724 return CF_READ_ERROR;
731 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
734 volatile int newly_displayed_packets = 0;
737 gboolean create_proto_tree;
741 /* Compile the current display filter.
742 * We assume this will not fail since cf->dfilter is only set in
743 * cf_filter IFF the filter was valid.
745 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
746 g_assert(!cf->dfilter || (compiled && dfcode));
748 /* Get the union of the flags for all tap listeners. */
749 tap_flags = union_of_tap_listener_flags();
752 * Determine whether we need to create a protocol tree.
755 * we're going to apply a display filter;
757 * one of the tap listeners is going to apply a filter;
759 * one of the tap listeners requires a protocol tree;
761 * a postdissector wants field values or protocols on
765 (dfcode != NULL || have_filtering_tap_listeners() ||
766 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
770 packet_list_check_end();
771 /* Don't freeze/thaw the list when doing live capture */
772 /*packet_list_freeze();*/
774 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
776 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
779 gint64 data_offset = 0;
782 /* If any tap listeners require the columns, construct them. */
783 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
785 while (to_read != 0) {
786 wtap_cleareof(cf->frame_set_info.wth);
787 if (!wtap_read(cf->frame_set_info.wth, err, &err_info, &data_offset)) {
790 if (cf->state == FILE_READ_ABORTED) {
791 /* Well, the user decided to exit Wireshark. Break out of the
792 loop, and let the code below (which is called even if there
793 aren't any packets left to read) exit. */
796 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
797 newly_displayed_packets++;
802 CATCH(OutOfMemoryError) {
803 simple_message_box(ESD_TYPE_ERROR, NULL,
804 "More information and workarounds can be found at\n"
805 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
806 "Sorry, but Wireshark has run out of memory and has to terminate now.");
808 /* Could we close the current capture and free up memory from that? */
809 return CF_READ_ABORTED;
811 /* we have to terminate, as we cannot recover from the memory error */
817 /* Update the file encapsulation; it might have changed based on the
818 packets we've read. */
819 cf->lnk_t = wtap_file_encap(cf->frame_set_info.wth);
821 /* Cleanup and release all dfilter resources */
822 dfilter_free(dfcode);
824 epan_dissect_cleanup(&edt);
826 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
827 cf->count, cf->state, *err);*/
829 /* Don't freeze/thaw the list when doing live capture */
830 /*packet_list_thaw();*/
831 /* With the new packet list the first packet
832 * isn't automatically selected.
834 if (!cf->current_frame)
835 packet_list_select_first_row();
837 /* moving to the end of the packet list - if the user requested so and
838 we have some new packets. */
839 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
840 packet_list_moveto_end();
842 if (cf->state == FILE_READ_ABORTED) {
843 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
844 so that our caller can kill off the capture child process;
845 this will cause an EOF on the pipe from the child, so
846 "cf_finish_tail()" will be called, and it will clean up
848 return CF_READ_ABORTED;
849 } else if (*err != 0) {
850 /* We got an error reading the capture file.
851 XXX - pop up a dialog box instead? */
852 if (err_info != NULL) {
853 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
854 wtap_strerror(*err), cf->filename, err_info);
857 g_warning("Error \"%s\" while reading \"%s\"",
858 wtap_strerror(*err), cf->filename);
860 return CF_READ_ERROR;
866 cf_fake_continue_tail(capture_file *cf) {
867 cf->state = FILE_READ_DONE;
871 cf_finish_tail(capture_file *cf, int *err)
878 gboolean create_proto_tree;
882 /* Compile the current display filter.
883 * We assume this will not fail since cf->dfilter is only set in
884 * cf_filter IFF the filter was valid.
886 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
887 g_assert(!cf->dfilter || (compiled && dfcode));
889 /* Get the union of the flags for all tap listeners. */
890 tap_flags = union_of_tap_listener_flags();
892 /* If any tap listeners require the columns, construct them. */
893 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
896 * Determine whether we need to create a protocol tree.
899 * we're going to apply a display filter;
901 * one of the tap listeners is going to apply a filter;
903 * one of the tap listeners requires a protocol tree;
905 * a postdissector wants field values or protocols on
909 (dfcode != NULL || have_filtering_tap_listeners() ||
910 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
912 if (cf->frame_set_info.wth == NULL) {
914 return CF_READ_ERROR;
917 packet_list_check_end();
918 /* Don't freeze/thaw the list when doing live capture */
919 /*packet_list_freeze();*/
921 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
923 while ((wtap_read(cf->frame_set_info.wth, err, &err_info, &data_offset))) {
924 if (cf->state == FILE_READ_ABORTED) {
925 /* Well, the user decided to abort the read. Break out of the
926 loop, and let the code below (which is called even if there
927 aren't any packets left to read) exit. */
930 read_packet(cf, dfcode, &edt, cinfo, data_offset);
933 /* Cleanup and release all dfilter resources */
934 dfilter_free(dfcode);
936 epan_dissect_cleanup(&edt);
938 /* Don't freeze/thaw the list when doing live capture */
939 /*packet_list_thaw();*/
941 if (cf->state == FILE_READ_ABORTED) {
942 /* Well, the user decided to abort the read. We're only called
943 when the child capture process closes the pipe to us (meaning
944 it's probably exited), so we can just close the capture
945 file; we return CF_READ_ABORTED so our caller can do whatever
946 is appropriate when that happens. */
948 return CF_READ_ABORTED;
951 if (auto_scroll_live && cf->count != 0)
952 packet_list_moveto_end();
954 /* We're done reading sequentially through the file. */
955 cf->state = FILE_READ_DONE;
957 /* We're done reading sequentially through the file; close the
958 sequential I/O side, to free up memory it requires. */
959 wtap_sequential_close(cf->frame_set_info.wth);
961 /* Allow the protocol dissectors to free up memory that they
962 * don't need after the sequential run-through of the packets. */
963 postseq_cleanup_all_protocols();
965 /* Update the file encapsulation; it might have changed based on the
966 packets we've read. */
967 cf->lnk_t = wtap_file_encap(cf->frame_set_info.wth);
969 /* Update the details in the file-set dialog, as the capture file
970 * has likely grown since we first stat-ed it */
971 fileset_update_file(cf->filename);
974 /* We got an error reading the capture file.
975 XXX - pop up a dialog box? */
976 if (err_info != NULL) {
977 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
978 wtap_strerror(*err), cf->filename, err_info);
981 g_warning("Error \"%s\" while reading \"%s\"",
982 wtap_strerror(*err), cf->filename);
984 return CF_READ_ERROR;
989 #endif /* HAVE_LIBPCAP */
992 cf_get_display_name(capture_file *cf)
996 /* Return a name to use in displays */
997 if (!cf->is_tempfile) {
998 /* Get the last component of the file name, and use that. */
1000 displayname = g_filename_display_basename(cf->filename);
1002 displayname=g_strdup("(No file)");
1005 /* The file we read is a temporary file from a live capture or
1006 a merge operation; we don't mention its name, but, if it's
1007 from a capture, give the source of the capture. */
1009 displayname = g_strdup(cf->source);
1011 displayname = g_strdup("(Untitled)");
1017 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1023 cf->source = g_strdup(source);
1025 cf->source = g_strdup("");
1029 const gchar *cf_get_tempfile_source(capture_file *cf) {
1037 /* XXX - use a macro instead? */
1039 cf_get_packet_count(capture_file *cf)
1044 /* XXX - use a macro instead? */
1046 cf_is_tempfile(capture_file *cf)
1048 return cf->is_tempfile;
1051 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1053 cf->is_tempfile = is_tempfile;
1057 /* XXX - use a macro instead? */
1058 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1060 cf->drops_known = drops_known;
1063 /* XXX - use a macro instead? */
1064 void cf_set_drops(capture_file *cf, guint32 drops)
1069 /* XXX - use a macro instead? */
1070 gboolean cf_get_drops_known(capture_file *cf)
1072 return cf->drops_known;
1075 /* XXX - use a macro instead? */
1076 guint32 cf_get_drops(capture_file *cf)
1081 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1083 cf->rfcode = rfcode;
1087 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1088 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1089 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1093 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1094 &cf->frame_set_info.ref, cf->frame_set_info.prev_dis);
1095 cf->frame_set_info.prev_cap = fdata;
1097 if (dfcode != NULL) {
1098 epan_dissect_prime_with_dfilter(edt, dfcode);
1101 /* Prepare coloring rules, this ensures that display filter rules containing
1102 * frame.color_rule references are still processed.
1103 * TODO: actually detect that situation or maybe apply other optimizations? */
1104 if (edt->tree && color_filters_used()) {
1105 color_filters_prime_edt(edt);
1106 fdata->flags.need_colorize = 1;
1110 if (!fdata->flags.visited) {
1111 /* This is the first pass, so prime the epan_dissect_t with the
1112 hfids postdissectors want on the first pass. */
1113 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1116 /* Dissect the frame. */
1117 epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1119 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1120 if (dfcode != NULL) {
1121 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1123 if (fdata->flags.passed_dfilter) {
1124 /* This frame passed the display filter but it may depend on other
1125 * (potentially not displayed) frames. Find those frames and mark them
1128 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frame_set_info.frames);
1131 fdata->flags.passed_dfilter = 1;
1133 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1134 cf->displayed_count++;
1136 if (add_to_packet_list) {
1137 /* We fill the needed columns from new_packet_list */
1138 row = packet_list_append(cinfo, fdata);
1141 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1143 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1144 cf->frame_set_info.prev_dis = fdata;
1146 /* If we haven't yet seen the first frame, this is it. */
1147 if (cf->first_displayed == 0)
1148 cf->first_displayed = fdata->num;
1150 /* This is the last frame we've seen so far. */
1151 cf->last_displayed = fdata->num;
1154 epan_dissect_reset(edt);
1158 /* read in a new packet */
1159 /* returns the row of the new packet in the packet list or -1 if not displayed */
1161 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1162 column_info *cinfo, gint64 offset)
1164 struct wtap_pkthdr *phdr = wtap_phdr(cf->frame_set_info.wth);
1165 const guint8 *buf = wtap_buf_ptr(cf->frame_set_info.wth);
1169 gboolean passed = TRUE;
1172 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1173 it's not already there.
1174 XXX - yes, this is O(N), so if every packet had a different
1175 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1176 there are probably going to be a small number of encapsulation types
1178 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1180 /* The frame number of this packet is one more than the count of
1181 frames in the file so far. */
1182 framenum = cf->count + 1;
1184 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1187 epan_dissect_t rf_edt;
1189 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1190 epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
1191 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1192 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1193 epan_dissect_cleanup(&rf_edt);
1197 /* This does a shallow copy of fdlocal, which is good enough. */
1198 fdata = frame_data_sequence_add(cf->frame_set_info.frames, &fdlocal);
1201 if (phdr->opt_comment != NULL)
1202 cf->packet_comment_count++;
1203 cf->f_datalen = offset + fdlocal.cap_len;
1205 if (!cf->redissecting) {
1206 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1207 cinfo, phdr, buf, TRUE);
1215 typedef struct _callback_data_t {
1218 GTimeVal start_time;
1226 merge_callback(merge_event event, int num _U_,
1227 const merge_in_file_t in_files[], const guint in_file_count,
1231 callback_data_t *cb_data = (callback_data_t*) data;
1233 g_assert(cb_data != NULL);
1237 case MERGE_EVENT_INPUT_FILES_OPENED:
1241 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1245 case MERGE_EVENT_READY_TO_MERGE:
1246 /* Get the sum of the sizes of all the files. */
1247 for (i = 0; i < in_file_count; i++)
1248 cb_data->f_len += in_files[i].size;
1250 cb_data->prog_timer = g_timer_new();
1251 g_timer_start(cb_data->prog_timer);
1253 g_get_current_time(&cb_data->start_time);
1256 case MERGE_EVENT_PACKET_WAS_READ:
1258 gint64 data_offset = 0;
1260 /* Get the sum of the data offsets in all of the files. */
1262 for (i = 0; i < in_file_count; i++)
1263 data_offset += in_files[i].data_offset;
1265 /* Create the progress bar if necessary.
1266 We check on every iteration of the loop, so that it takes no
1267 longer than the standard time to create it (otherwise, for a
1268 large file, we might take considerably longer than that standard
1269 time in order to get to the next progress bar step). */
1270 if (cb_data->progbar == NULL) {
1271 cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1272 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1276 * Update the progress bar, but do it only after
1277 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1278 * and packets_bar_update will likely trigger UI paint events, which
1279 * might take a while depending on the platform and display. Reset
1280 * our timer *after* painting.
1282 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1284 gint64 file_pos = 0;
1285 /* Get the sum of the seek positions in all of the files. */
1286 for (i = 0; i < in_file_count; i++)
1287 file_pos += wtap_read_so_far(in_files[i].wth);
1289 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1290 if (progbar_val > 1.0f) {
1291 /* Some file probably grew while we were reading it.
1292 That "shouldn't happen", so we'll just clip the progress
1297 if (cb_data->progbar != NULL) {
1298 gchar status_str[100];
1299 g_snprintf(status_str, sizeof(status_str),
1300 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1301 file_pos / 1024, cb_data->f_len / 1024);
1302 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1304 g_timer_start(cb_data->prog_timer);
1309 case MERGE_EVENT_DONE:
1310 /* We're done merging the files; destroy the progress bar if it was created. */
1311 if (cb_data->progbar != NULL)
1312 destroy_progress_dlg(cb_data->progbar);
1313 g_timer_destroy(cb_data->prog_timer);
1317 return cb_data->stop_flag;
1323 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1324 int in_file_count, char *const *in_filenames,
1325 int file_type, gboolean do_append)
1328 gchar *err_info = NULL;
1330 guint32 err_framenum;
1331 merge_result status;
1332 merge_progress_callback_t cb;
1333 callback_data_t *cb_data = g_new0(callback_data_t, 1);
1335 /* prepare our callback routine */
1336 cb_data->pd_window = pd_window;
1337 cb.callback_func = merge_callback;
1340 cf_callback_invoke(cf_cb_file_merge_started, NULL);
1342 /* merge the files */
1343 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1344 (const char *const *) in_filenames,
1345 in_file_count, do_append,
1346 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1347 "Wireshark", &cb, &err, &err_info,
1348 &err_fileno, &err_framenum);
1356 case MERGE_USER_ABORTED:
1357 /* this isn't really an error, though we will return CF_ERROR later */
1360 case MERGE_ERR_CANT_OPEN_INFILE:
1361 cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
1364 case MERGE_ERR_CANT_OPEN_OUTFILE:
1365 cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
1368 case MERGE_ERR_CANT_READ_INFILE:
1369 cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
1372 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1373 simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
1374 err_framenum, in_filenames[err_fileno]);
1377 case MERGE_ERR_CANT_WRITE_OUTFILE:
1378 cfile_write_failure_alert_box(in_filenames[err_fileno],
1379 *out_filenamep, err, err_info,
1380 err_framenum, file_type);
1383 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1384 cfile_close_failure_alert_box(*out_filenamep, err);
1388 simple_error_message_box("Unknown merge_files error %d", status);
1392 cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1394 if (status != MERGE_OK) {
1395 /* Callers aren't expected to treat an error or an explicit abort
1396 differently - we put up error dialogs ourselves, so they don't
1404 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1406 const char *filter_new = dftext ? dftext : "";
1407 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1410 GTimeVal start_time;
1412 /* if new filter equals old one, do nothing unless told to do so */
1413 if (!force && strcmp(filter_new, filter_old) == 0) {
1419 if (dftext == NULL) {
1420 /* The new filter is an empty filter (i.e., display all packets).
1421 * so leave dfcode==NULL
1425 * We have a filter; make a copy of it (as we'll be saving it),
1426 * and try to compile it.
1428 dftext = g_strdup(dftext);
1429 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1430 /* The attempt failed; report an error. */
1431 simple_message_box(ESD_TYPE_ERROR, NULL,
1432 "See the help for a description of the display filter syntax.",
1433 "\"%s\" isn't a valid display filter: %s",
1441 if (dfcode == NULL) {
1442 /* Yes - free the filter text, and set it to null. */
1448 /* We have a valid filter. Replace the current filter. */
1449 g_free(cf->dfilter);
1450 cf->dfilter = dftext;
1451 g_get_current_time(&start_time);
1454 /* Now rescan the packet list, applying the new filter, but not
1455 throwing away information constructed on a previous pass. */
1456 if (cf->state != FILE_CLOSED) {
1457 if (dftext == NULL) {
1458 rescan_packets(cf, "Resetting", "Filter", FALSE);
1460 rescan_packets(cf, "Filtering", dftext, FALSE);
1464 /* Cleanup and release all dfilter resources */
1465 dfilter_free(dfcode);
1471 cf_reftime_packets(capture_file *cf)
1473 ref_time_packets(cf);
1477 cf_redissect_packets(capture_file *cf)
1479 if (cf->state != FILE_CLOSED) {
1480 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1485 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1486 struct wtap_pkthdr *phdr, Buffer *buf)
1491 if (!wtap_seek_read(cf->frame_set_info.wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1492 cfile_read_failure_alert_box(cf->filename, err, err_info);
1499 cf_read_record(capture_file *cf, frame_data *fdata)
1501 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1504 /* Rescan the list of packets, reconstructing the CList.
1506 "action" describes why we're doing this; it's used in the progress
1509 "action_item" describes what we're doing; it's used in the progress
1512 "redissect" is TRUE if we need to make the dissectors reconstruct
1513 any state information they have (because a preference that affects
1514 some dissector has changed, meaning some dissector might construct
1515 its state differently from the way it was constructed the last time). */
1517 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1519 /* Rescan packets new packet list */
1522 progdlg_t *progbar = NULL;
1523 GTimer *prog_timer = g_timer_new();
1525 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1526 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1527 gboolean selected_frame_seen;
1529 GTimeVal start_time;
1530 gchar status_str[100];
1534 gboolean create_proto_tree;
1536 gboolean add_to_packet_list = FALSE;
1538 guint32 frames_count;
1540 /* Compile the current display filter.
1541 * We assume this will not fail since cf->dfilter is only set in
1542 * cf_filter IFF the filter was valid.
1544 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1545 g_assert(!cf->dfilter || (compiled && dfcode));
1547 /* Get the union of the flags for all tap listeners. */
1548 tap_flags = union_of_tap_listener_flags();
1550 /* If any tap listeners require the columns, construct them. */
1551 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1554 * Determine whether we need to create a protocol tree.
1557 * we're going to apply a display filter;
1559 * one of the tap listeners is going to apply a filter;
1561 * one of the tap listeners requires a protocol tree;
1563 * we're redissecting and a postdissector wants field
1564 * values or protocols on the first pass.
1567 (dfcode != NULL || have_filtering_tap_listeners() ||
1568 (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1569 (redissect && postdissectors_want_hfids()));
1571 reset_tap_listeners();
1572 /* Which frame, if any, is the currently selected frame?
1573 XXX - should the selected frame or the focus frame be the "current"
1574 frame, that frame being the one from which "Find Frame" searches
1576 selected_frame = cf->current_frame;
1578 /* Mark frame num as not found */
1579 selected_frame_num = -1;
1581 /* Freeze the packet list while we redo it, so we don't get any
1582 screen updates while it happens. */
1583 packet_list_freeze();
1586 /* We need to re-initialize all the state information that protocols
1587 keep, because some preference that controls a dissector has changed,
1588 which might cause the state information to be constructed differently
1589 by that dissector. */
1591 /* We might receive new packets while redissecting, and we don't
1592 want to dissect those before their time. */
1593 cf->redissecting = TRUE;
1595 /* 'reset' dissection session */
1596 epan_free(cf->epan);
1597 if (cf->edt && cf->edt->pi.fd) {
1598 /* All pointers in "per frame proto data" for the currently selected
1599 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1600 Free them here to avoid unintended usage in packet_list_clear(). */
1601 frame_data_destroy(cf->edt->pi.fd);
1603 cf->epan = ws_epan_new(cf);
1604 cf->cinfo.epan = cf->epan;
1606 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1607 called via epan_new() / init_dissection() when reloading Lua plugins. */
1608 if (!create_proto_tree && have_filtering_tap_listeners()) {
1609 create_proto_tree = TRUE;
1612 /* We need to redissect the packets so we have to discard our old
1613 * packet list store. */
1614 packet_list_clear();
1615 add_to_packet_list = TRUE;
1618 /* We don't yet know which will be the first and last frames displayed. */
1619 cf->first_displayed = 0;
1620 cf->last_displayed = 0;
1622 /* We currently don't display any packets */
1623 cf->displayed_count = 0;
1625 /* Iterate through the list of frames. Call a routine for each frame
1626 to check whether it should be displayed and, if so, add it to
1627 the display list. */
1628 cf->frame_set_info.ref = NULL;
1629 cf->frame_set_info.prev_dis = NULL;
1630 cf->frame_set_info.prev_cap = NULL;
1633 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1635 g_timer_start(prog_timer);
1636 /* Count of packets at which we've looked. */
1638 /* Progress so far. */
1641 cf->stop_flag = FALSE;
1642 g_get_current_time(&start_time);
1644 /* no previous row yet */
1645 prev_frame_num = -1;
1648 preceding_frame_num = -1;
1649 preceding_frame = NULL;
1650 following_frame_num = -1;
1651 following_frame = NULL;
1653 selected_frame_seen = FALSE;
1655 frames_count = cf->count;
1657 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1659 for (framenum = 1; framenum <= frames_count; framenum++) {
1660 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
1662 /* Create the progress bar if necessary.
1663 We check on every iteration of the loop, so that it takes no
1664 longer than the standard time to create it (otherwise, for a
1665 large file, we might take considerably longer than that standard
1666 time in order to get to the next progress bar step). */
1667 if (progbar == NULL)
1668 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1674 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1675 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1676 * likely trigger UI paint events, which might take a while depending on
1677 * the platform and display. Reset our timer *after* painting.
1679 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1680 /* let's not divide by zero. I should never be started
1681 * with count == 0, so let's assert that
1683 g_assert(cf->count > 0);
1684 progbar_val = (gfloat) count / frames_count;
1686 if (progbar != NULL) {
1687 g_snprintf(status_str, sizeof(status_str),
1688 "%4u of %u frames", count, frames_count);
1689 update_progress_dlg(progbar, progbar_val, status_str);
1692 g_timer_start(prog_timer);
1695 if (cf->stop_flag) {
1696 /* Well, the user decided to abort the filtering. Just stop.
1698 XXX - go back to the previous filter? Users probably just
1699 want not to wait for a filtering operation to finish;
1700 unless we cancel by having no filter, reverting to the
1701 previous filter will probably be even more expensive than
1702 continuing the filtering, as it involves going back to the
1703 beginning and filtering, and even with no filter we currently
1704 have to re-generate the entire clist, which is also expensive.
1706 I'm not sure what Network Monitor does, but it doesn't appear
1707 to give you an unfiltered display if you cancel. */
1714 /* Since all state for the frame was destroyed, mark the frame
1715 * as not visited, free the GSList referring to the state
1716 * data (the per-frame data itself was freed by
1717 * "init_dissection()"), and null out the GSList pointer. */
1718 frame_data_reset(fdata);
1719 frames_count = cf->count;
1722 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1723 fdata->flags.dependent_of_displayed = 0;
1725 if (!cf_read_record(cf, fdata))
1726 break; /* error reading the frame */
1728 /* If the previous frame is displayed, and we haven't yet seen the
1729 selected frame, remember that frame - it's the closest one we've
1730 yet seen before the selected frame. */
1731 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1732 preceding_frame_num = prev_frame_num;
1733 preceding_frame = prev_frame;
1736 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1738 ws_buffer_start_ptr(&cf->buf),
1739 add_to_packet_list);
1741 /* If this frame is displayed, and this is the first frame we've
1742 seen displayed after the selected frame, remember this frame -
1743 it's the closest one we've yet seen at or after the selected
1745 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1746 following_frame_num = fdata->num;
1747 following_frame = fdata;
1749 if (fdata == selected_frame) {
1750 selected_frame_seen = TRUE;
1751 if (fdata->flags.passed_dfilter)
1752 selected_frame_num = fdata->num;
1755 /* Remember this frame - it'll be the previous frame
1756 on the next pass through the loop. */
1757 prev_frame_num = fdata->num;
1761 epan_dissect_cleanup(&edt);
1763 /* We are done redissecting the packet list. */
1764 cf->redissecting = FALSE;
1767 frames_count = cf->count;
1768 /* Clear out what remains of the visited flags and per-frame data
1771 XXX - that may cause various forms of bogosity when dissecting
1772 these frames, as they won't have been seen by this sequential
1773 pass, but the only alternative I see is to keep scanning them
1774 even though the user requested that the scan stop, and that
1775 would leave the user stuck with an Wireshark grinding on
1776 until it finishes. Should we just stick them with that? */
1777 for (; framenum <= frames_count; framenum++) {
1778 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
1779 frame_data_reset(fdata);
1783 /* We're done filtering the packets; destroy the progress bar if it
1785 if (progbar != NULL)
1786 destroy_progress_dlg(progbar);
1787 g_timer_destroy(prog_timer);
1789 /* Unfreeze the packet list. */
1790 if (!add_to_packet_list)
1791 packet_list_recreate_visible_rows();
1793 /* Compute the time it took to filter the file */
1794 compute_elapsed(cf, &start_time);
1798 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1800 if (selected_frame_num == -1) {
1801 /* The selected frame didn't pass the filter. */
1802 if (selected_frame == NULL) {
1803 /* That's because there *was* no selected frame. Make the first
1804 displayed frame the current frame. */
1805 selected_frame_num = 0;
1807 /* Find the nearest displayed frame to the selected frame (whether
1808 it's before or after that frame) and make that the current frame.
1809 If the next and previous displayed frames are equidistant from the
1810 selected frame, choose the next one. */
1811 g_assert(following_frame == NULL ||
1812 following_frame->num >= selected_frame->num);
1813 g_assert(preceding_frame == NULL ||
1814 preceding_frame->num <= selected_frame->num);
1815 if (following_frame == NULL) {
1816 /* No frame after the selected frame passed the filter, so we
1817 have to select the last displayed frame before the selected
1819 selected_frame_num = preceding_frame_num;
1820 selected_frame = preceding_frame;
1821 } else if (preceding_frame == NULL) {
1822 /* No frame before the selected frame passed the filter, so we
1823 have to select the first displayed frame after the selected
1825 selected_frame_num = following_frame_num;
1826 selected_frame = following_frame;
1828 /* Frames before and after the selected frame passed the filter, so
1829 we'll select the previous frame */
1830 selected_frame_num = preceding_frame_num;
1831 selected_frame = preceding_frame;
1836 if (selected_frame_num == -1) {
1837 /* There are no frames displayed at all. */
1838 cf_unselect_packet(cf);
1840 /* Either the frame that was selected passed the filter, or we've
1841 found the nearest displayed frame to that frame. Select it, make
1842 it the focus row, and make it visible. */
1843 /* Set to invalid to force update of packet list and packet details */
1844 cf->current_row = -1;
1845 if (selected_frame_num == 0) {
1846 packet_list_select_first_row();
1848 if (!packet_list_select_row_from_data(selected_frame)) {
1849 /* We didn't find a row corresponding to this frame.
1850 This means that the frame isn't being displayed currently,
1851 so we can't select it. */
1852 simple_message_box(ESD_TYPE_INFO, NULL,
1853 "The capture file is probably not fully dissected.",
1854 "End of capture exceeded.");
1859 /* Cleanup and release all dfilter resources */
1860 dfilter_free(dfcode);
1865 * Scan through all frame data and recalculate the ref time
1866 * without rereading the file.
1867 * XXX - do we need a progres bar or is this fast enough?
1870 ref_time_packets(capture_file *cf)
1876 cf->frame_set_info.ref = NULL;
1877 cf->frame_set_info.prev_dis = NULL;
1880 for (framenum = 1; framenum <= cf->count; framenum++) {
1881 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
1883 /* just add some value here until we know if it is being displayed or not */
1884 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1890 /* If we don't have the time stamp of the first packet in the
1891 capture, it's because this is the first packet. Save the time
1892 stamp of this packet as the time stamp of the first packet. */
1893 if (cf->frame_set_info.ref == NULL)
1894 cf->frame_set_info.ref = fdata;
1895 /* if this frames is marked as a reference time frame, reset
1896 firstsec and firstusec to this frame */
1897 if (fdata->flags.ref_time)
1898 cf->frame_set_info.ref = fdata;
1900 /* If we don't have the time stamp of the previous displayed packet,
1901 it's because this is the first displayed packet. Save the time
1902 stamp of this packet as the time stamp of the previous displayed
1904 if (cf->frame_set_info.prev_dis == NULL) {
1905 cf->frame_set_info.prev_dis = fdata;
1908 /* Get the time elapsed between the first packet and this packet. */
1909 fdata->frame_ref_num = (fdata != cf->frame_set_info.ref) ? cf->frame_set_info.ref->num : 0;
1910 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->frame_set_info.ref->abs_ts);
1912 /* If it's greater than the current elapsed time, set the elapsed time
1913 to it (we check for "greater than" so as not to be confused by
1914 time moving backwards). */
1915 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1916 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1917 cf->elapsed_time = rel_ts;
1920 /* If this frame is displayed, get the time elapsed between the
1921 previous displayed packet and this packet. */
1922 if ( fdata->flags.passed_dfilter ) {
1923 fdata->prev_dis_num = cf->frame_set_info.prev_dis->num;
1924 cf->frame_set_info.prev_dis = fdata;
1930 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1931 /* This frame either passed the display filter list or is marked as
1932 a time reference frame. All time reference frames are displayed
1933 even if they don't pass the display filter */
1934 if (fdata->flags.ref_time) {
1935 /* if this was a TIME REF frame we should reset the cum_bytes field */
1936 cf->cum_bytes = fdata->pkt_len;
1937 fdata->cum_bytes = cf->cum_bytes;
1939 /* increase cum_bytes with this packets length */
1940 cf->cum_bytes += fdata->pkt_len;
1953 process_specified_records(capture_file *cf, packet_range_t *range,
1954 const char *string1, const char *string2, gboolean terminate_is_stop,
1955 gboolean (*callback)(capture_file *, frame_data *,
1956 struct wtap_pkthdr *, const guint8 *, void *),
1957 void *callback_args,
1958 gboolean show_progress_bar)
1963 psp_return_t ret = PSP_FINISHED;
1965 progdlg_t *progbar = NULL;
1966 GTimer *prog_timer = g_timer_new();
1969 GTimeVal progbar_start_time;
1970 gchar progbar_status_str[100];
1971 range_process_e process_this;
1972 struct wtap_pkthdr phdr;
1974 wtap_phdr_init(&phdr);
1975 ws_buffer_init(&buf, 1500);
1977 g_timer_start(prog_timer);
1978 /* Count of packets at which we've looked. */
1980 /* Progress so far. */
1983 cf->stop_flag = FALSE;
1984 g_get_current_time(&progbar_start_time);
1987 packet_range_process_init(range);
1989 /* Iterate through all the packets, printing the packets that
1990 were selected by the current display filter. */
1991 for (framenum = 1; framenum <= cf->count; framenum++) {
1992 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
1994 /* Create the progress bar if necessary.
1995 We check on every iteration of the loop, so that it takes no
1996 longer than the standard time to create it (otherwise, for a
1997 large file, we might take considerably longer than that standard
1998 time in order to get to the next progress bar step). */
1999 if (show_progress_bar && progbar == NULL)
2000 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2003 &progbar_start_time,
2007 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
2008 * has elapsed. Calling update_progress_dlg and packets_bar_update will
2009 * likely trigger UI paint events, which might take a while depending on
2010 * the platform and display. Reset our timer *after* painting.
2012 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2013 /* let's not divide by zero. I should never be started
2014 * with count == 0, so let's assert that
2016 g_assert(cf->count > 0);
2017 progbar_val = (gfloat) progbar_count / cf->count;
2019 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2020 "%4u of %u packets", progbar_count, cf->count);
2021 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2023 g_timer_start(prog_timer);
2026 if (cf->stop_flag) {
2027 /* Well, the user decided to abort the operation. Just stop,
2028 and arrange to return PSP_STOPPED to our caller, so they know
2029 it was stopped explicitly. */
2036 if (range != NULL) {
2037 /* do we have to process this packet? */
2038 process_this = packet_range_process_packet(range, fdata);
2039 if (process_this == range_process_next) {
2040 /* this packet uninteresting, continue with next one */
2042 } else if (process_this == range_processing_finished) {
2043 /* all interesting packets processed, stop the loop */
2048 /* Get the packet */
2049 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2050 /* Attempt to get the packet failed. */
2054 /* Process the packet */
2055 if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2056 /* Callback failed. We assume it reported the error appropriately. */
2062 /* We're done printing the packets; destroy the progress bar if
2064 if (progbar != NULL)
2065 destroy_progress_dlg(progbar);
2066 g_timer_destroy(prog_timer);
2068 wtap_phdr_cleanup(&phdr);
2069 ws_buffer_free(&buf);
2077 } retap_callback_args_t;
2080 retap_packet(capture_file *cf, frame_data *fdata,
2081 struct wtap_pkthdr *phdr, const guint8 *pd,
2084 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2086 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2087 epan_dissect_reset(&args->edt);
2093 cf_retap_packets(capture_file *cf)
2095 packet_range_t range;
2096 retap_callback_args_t callback_args;
2097 gboolean create_proto_tree;
2101 /* Presumably the user closed the capture file. */
2103 return CF_READ_ABORTED;
2106 cf_callback_invoke(cf_cb_file_retap_started, cf);
2108 /* Get the union of the flags for all tap listeners. */
2109 tap_flags = union_of_tap_listener_flags();
2111 /* If any tap listeners require the columns, construct them. */
2112 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2115 * Determine whether we need to create a protocol tree.
2118 * one of the tap listeners is going to apply a filter;
2120 * one of the tap listeners requires a protocol tree.
2123 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2125 /* Reset the tap listeners. */
2126 reset_tap_listeners();
2128 epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2130 /* Iterate through the list of packets, dissecting all packets and
2131 re-running the taps. */
2132 packet_range_init(&range, cf);
2133 packet_range_process_init(&range);
2135 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2136 "all packets", TRUE, retap_packet,
2137 &callback_args, TRUE);
2139 epan_dissect_cleanup(&callback_args.edt);
2141 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2145 /* Completed successfully. */
2149 /* Well, the user decided to abort the refiltering.
2150 Return CF_READ_ABORTED so our caller knows they did that. */
2151 return CF_READ_ABORTED;
2154 /* Error while retapping. */
2155 return CF_READ_ERROR;
2158 g_assert_not_reached();
2163 print_args_t *print_args;
2164 gboolean print_header_line;
2165 char *header_line_buf;
2166 int header_line_buf_len;
2167 gboolean print_formfeed;
2168 gboolean print_separator;
2172 int num_visible_cols;
2175 } print_callback_args_t;
2178 print_packet(capture_file *cf, frame_data *fdata,
2179 struct wtap_pkthdr *phdr, const guint8 *pd,
2182 print_callback_args_t *args = (print_callback_args_t *)argsp;
2188 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2189 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2190 col_item_t* col_item;
2192 /* Fill in the column information if we're printing the summary
2194 if (args->print_args->print_summary) {
2195 col_custom_prime_edt(&args->edt, &cf->cinfo);
2196 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2197 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2199 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2201 if (args->print_formfeed) {
2202 if (!new_page(args->print_args->stream))
2205 if (args->print_separator) {
2206 if (!print_line(args->print_args->stream, 0, ""))
2212 * We generate bookmarks, if the output format supports them.
2213 * The name is "__frameN__".
2215 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2217 if (args->print_args->print_summary) {
2218 if (!args->print_args->print_col_headings)
2219 args->print_header_line = FALSE;
2220 if (args->print_header_line) {
2221 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2223 args->print_header_line = FALSE; /* we might not need to print any more */
2225 cp = &args->line_buf[0];
2227 for (i = 0; i < args->num_visible_cols; i++) {
2228 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2229 /* Find the length of the string for this column. */
2230 column_len = (int) strlen(col_item->col_data);
2231 if (args->col_widths[i] > column_len)
2232 column_len = args->col_widths[i];
2234 /* Make sure there's room in the line buffer for the column; if not,
2235 double its length. */
2236 line_len += column_len + 1; /* "+1" for space */
2237 if (line_len > args->line_buf_len) {
2238 cp_off = (int) (cp - args->line_buf);
2239 args->line_buf_len = 2 * line_len;
2240 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2241 cp = args->line_buf + cp_off;
2244 /* Right-justify the packet number column. */
2245 if (col_item->col_fmt == COL_NUMBER)
2246 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2248 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2250 if (i != args->num_visible_cols - 1)
2256 * Generate a bookmark, using the summary line as the title.
2258 if (!print_bookmark(args->print_args->stream, bookmark_name,
2262 if (!print_line(args->print_args->stream, 0, args->line_buf))
2266 * Generate a bookmark, using "Frame N" as the title, as we're not
2267 * printing the summary line.
2269 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2270 if (!print_bookmark(args->print_args->stream, bookmark_name,
2273 } /* if (print_summary) */
2275 if (args->print_args->print_dissections != print_dissections_none) {
2276 if (args->print_args->print_summary) {
2277 /* Separate the summary line from the tree with a blank line. */
2278 if (!print_line(args->print_args->stream, 0, ""))
2282 /* Print the information in that tree. */
2283 if (!proto_tree_print(args->print_args->print_dissections,
2284 args->print_args->print_hex, &args->edt, NULL,
2285 args->print_args->stream))
2288 /* Print a blank line if we print anything after this (aka more than one packet). */
2289 args->print_separator = TRUE;
2291 /* Print a header line if we print any more packet summaries */
2292 if (args->print_args->print_col_headings)
2293 args->print_header_line = TRUE;
2296 if (args->print_args->print_hex) {
2297 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2298 if (!print_line(args->print_args->stream, 0, ""))
2301 /* Print the full packet data as hex. */
2302 if (!print_hex_data(args->print_args->stream, &args->edt))
2305 /* Print a blank line if we print anything after this (aka more than one packet). */
2306 args->print_separator = TRUE;
2308 /* Print a header line if we print any more packet summaries */
2309 if (args->print_args->print_col_headings)
2310 args->print_header_line = TRUE;
2311 } /* if (args->print_args->print_dissections != print_dissections_none) */
2313 epan_dissect_reset(&args->edt);
2315 /* do we want to have a formfeed between each packet from now on? */
2316 if (args->print_args->print_formfeed) {
2317 args->print_formfeed = TRUE;
2323 epan_dissect_reset(&args->edt);
2328 cf_print_packets(capture_file *cf, print_args_t *print_args,
2329 gboolean show_progress_bar)
2331 print_callback_args_t callback_args;
2334 int i, cp_off, column_len, line_len;
2335 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2339 gboolean proto_tree_needed;
2341 callback_args.print_args = print_args;
2342 callback_args.print_header_line = print_args->print_col_headings;
2343 callback_args.header_line_buf = NULL;
2344 callback_args.header_line_buf_len = 256;
2345 callback_args.print_formfeed = FALSE;
2346 callback_args.print_separator = FALSE;
2347 callback_args.line_buf = NULL;
2348 callback_args.line_buf_len = 256;
2349 callback_args.col_widths = NULL;
2350 callback_args.num_visible_cols = 0;
2351 callback_args.visible_cols = NULL;
2353 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2354 destroy_print_stream(print_args->stream);
2355 return CF_PRINT_WRITE_ERROR;
2358 if (print_args->print_summary) {
2359 /* We're printing packet summaries. Allocate the header line buffer
2360 and get the column widths. */
2361 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2363 /* Find the number of visible columns and the last visible column */
2364 for (i = 0; i < prefs.num_cols; i++) {
2366 clp = g_list_nth(prefs.col_list, i);
2367 if (clp == NULL) /* Sanity check, Invalid column requested */
2370 cfmt = (fmt_data *) clp->data;
2371 if (cfmt->visible) {
2373 last_visible_col = i;
2377 /* Find the widths for each of the columns - maximum of the
2378 width of the title and the width of the data - and construct
2379 a buffer with a line containing the column titles. */
2380 callback_args.num_visible_cols = num_visible_col;
2381 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2382 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2383 cp = &callback_args.header_line_buf[0];
2385 visible_col_count = 0;
2386 for (i = 0; i < cf->cinfo.num_cols; i++) {
2388 clp = g_list_nth(prefs.col_list, i);
2389 if (clp == NULL) /* Sanity check, Invalid column requested */
2392 cfmt = (fmt_data *) clp->data;
2393 if (cfmt->visible == FALSE)
2396 /* Save the order of visible columns */
2397 callback_args.visible_cols[visible_col_count] = i;
2399 /* Don't pad the last column. */
2400 if (i == last_visible_col)
2401 callback_args.col_widths[visible_col_count] = 0;
2403 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2404 data_width = get_column_char_width(get_column_format(i));
2405 if (data_width > callback_args.col_widths[visible_col_count])
2406 callback_args.col_widths[visible_col_count] = data_width;
2409 /* Find the length of the string for this column. */
2410 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2411 if (callback_args.col_widths[i] > column_len)
2412 column_len = callback_args.col_widths[visible_col_count];
2414 /* Make sure there's room in the line buffer for the column; if not,
2415 double its length. */
2416 line_len += column_len + 1; /* "+1" for space */
2417 if (line_len > callback_args.header_line_buf_len) {
2418 cp_off = (int) (cp - callback_args.header_line_buf);
2419 callback_args.header_line_buf_len = 2 * line_len;
2420 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2421 callback_args.header_line_buf_len + 1);
2422 cp = callback_args.header_line_buf + cp_off;
2425 /* Right-justify the packet number column. */
2426 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2427 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2429 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2431 if (i != cf->cinfo.num_cols - 1)
2434 visible_col_count++;
2438 /* Now start out the main line buffer with the same length as the
2439 header line buffer. */
2440 callback_args.line_buf_len = callback_args.header_line_buf_len;
2441 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2442 } /* if (print_summary) */
2444 /* Create the protocol tree, and make it visible, if we're printing
2445 the dissection or the hex data.
2446 XXX - do we need it if we're just printing the hex data? */
2448 callback_args.print_args->print_dissections != print_dissections_none ||
2449 callback_args.print_args->print_hex ||
2450 have_custom_cols(&cf->cinfo) || have_field_extractors();
2451 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2453 /* Iterate through the list of packets, printing the packets we were
2455 ret = process_specified_records(cf, &print_args->range, "Printing",
2456 "selected packets", TRUE, print_packet,
2457 &callback_args, show_progress_bar);
2458 epan_dissect_cleanup(&callback_args.edt);
2459 g_free(callback_args.header_line_buf);
2460 g_free(callback_args.line_buf);
2461 g_free(callback_args.col_widths);
2462 g_free(callback_args.visible_cols);
2467 /* Completed successfully. */
2471 /* Well, the user decided to abort the printing.
2473 XXX - note that what got generated before they did that
2474 will get printed if we're piping to a print program; we'd
2475 have to write to a file and then hand that to the print
2476 program to make it actually not print anything. */
2480 /* Error while printing.
2482 XXX - note that what got generated before they did that
2483 will get printed if we're piping to a print program; we'd
2484 have to write to a file and then hand that to the print
2485 program to make it actually not print anything. */
2486 destroy_print_stream(print_args->stream);
2487 return CF_PRINT_WRITE_ERROR;
2490 if (!print_finale(print_args->stream)) {
2491 destroy_print_stream(print_args->stream);
2492 return CF_PRINT_WRITE_ERROR;
2495 if (!destroy_print_stream(print_args->stream))
2496 return CF_PRINT_WRITE_ERROR;
2504 print_args_t *print_args;
2505 } write_packet_callback_args_t;
2508 write_pdml_packet(capture_file *cf, frame_data *fdata,
2509 struct wtap_pkthdr *phdr, const guint8 *pd,
2512 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2514 /* Create the protocol tree, but don't fill in the column information. */
2515 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2517 /* Write out the information in that tree. */
2518 write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, args->fh, FALSE);
2520 epan_dissect_reset(&args->edt);
2522 return !ferror(args->fh);
2526 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2528 write_packet_callback_args_t callback_args;
2532 fh = ws_fopen(print_args->file, "w");
2534 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2536 write_pdml_preamble(fh, cf->filename);
2539 return CF_PRINT_WRITE_ERROR;
2542 callback_args.fh = fh;
2543 callback_args.print_args = print_args;
2544 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2546 /* Iterate through the list of packets, printing the packets we were
2548 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2549 "selected packets", TRUE,
2550 write_pdml_packet, &callback_args, TRUE);
2552 epan_dissect_cleanup(&callback_args.edt);
2557 /* Completed successfully. */
2561 /* Well, the user decided to abort the printing. */
2565 /* Error while printing. */
2567 return CF_PRINT_WRITE_ERROR;
2570 write_pdml_finale(fh);
2573 return CF_PRINT_WRITE_ERROR;
2576 /* XXX - check for an error */
2583 write_psml_packet(capture_file *cf, frame_data *fdata,
2584 struct wtap_pkthdr *phdr, const guint8 *pd,
2587 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2589 /* Fill in the column information */
2590 col_custom_prime_edt(&args->edt, &cf->cinfo);
2591 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2592 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2594 /* Write out the column information. */
2595 write_psml_columns(&args->edt, args->fh, FALSE);
2597 epan_dissect_reset(&args->edt);
2599 return !ferror(args->fh);
2603 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2605 write_packet_callback_args_t callback_args;
2609 gboolean proto_tree_needed;
2611 fh = ws_fopen(print_args->file, "w");
2613 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2615 write_psml_preamble(&cf->cinfo, fh);
2618 return CF_PRINT_WRITE_ERROR;
2621 callback_args.fh = fh;
2622 callback_args.print_args = print_args;
2624 /* Fill in the column information, only create the protocol tree
2625 if having custom columns or field extractors. */
2626 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2627 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2629 /* Iterate through the list of packets, printing the packets we were
2631 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2632 "selected packets", TRUE,
2633 write_psml_packet, &callback_args, TRUE);
2635 epan_dissect_cleanup(&callback_args.edt);
2640 /* Completed successfully. */
2644 /* Well, the user decided to abort the printing. */
2648 /* Error while printing. */
2650 return CF_PRINT_WRITE_ERROR;
2653 write_psml_finale(fh);
2656 return CF_PRINT_WRITE_ERROR;
2659 /* XXX - check for an error */
2666 write_csv_packet(capture_file *cf, frame_data *fdata,
2667 struct wtap_pkthdr *phdr, const guint8 *pd,
2670 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2672 /* Fill in the column information */
2673 col_custom_prime_edt(&args->edt, &cf->cinfo);
2674 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2675 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2677 /* Write out the column information. */
2678 write_csv_columns(&args->edt, args->fh);
2680 epan_dissect_reset(&args->edt);
2682 return !ferror(args->fh);
2686 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2688 write_packet_callback_args_t callback_args;
2689 gboolean proto_tree_needed;
2693 fh = ws_fopen(print_args->file, "w");
2695 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2697 write_csv_column_titles(&cf->cinfo, fh);
2700 return CF_PRINT_WRITE_ERROR;
2703 callback_args.fh = fh;
2704 callback_args.print_args = print_args;
2706 /* only create the protocol tree if having custom columns or field extractors. */
2707 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2708 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2710 /* Iterate through the list of packets, printing the packets we were
2712 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2713 "selected packets", TRUE,
2714 write_csv_packet, &callback_args, TRUE);
2716 epan_dissect_cleanup(&callback_args.edt);
2721 /* Completed successfully. */
2725 /* Well, the user decided to abort the printing. */
2729 /* Error while printing. */
2731 return CF_PRINT_WRITE_ERROR;
2734 /* XXX - check for an error */
2741 carrays_write_packet(capture_file *cf, frame_data *fdata,
2742 struct wtap_pkthdr *phdr,
2743 const guint8 *pd, void *argsp)
2745 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2747 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2748 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2749 epan_dissect_reset(&args->edt);
2751 return !ferror(args->fh);
2755 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2757 write_packet_callback_args_t callback_args;
2761 fh = ws_fopen(print_args->file, "w");
2764 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2768 return CF_PRINT_WRITE_ERROR;
2771 callback_args.fh = fh;
2772 callback_args.print_args = print_args;
2773 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2775 /* Iterate through the list of packets, printing the packets we were
2777 ret = process_specified_records(cf, &print_args->range,
2779 "selected packets", TRUE,
2780 carrays_write_packet, &callback_args, TRUE);
2782 epan_dissect_cleanup(&callback_args.edt);
2786 /* Completed successfully. */
2789 /* Well, the user decided to abort the printing. */
2792 /* Error while printing. */
2794 return CF_PRINT_WRITE_ERROR;
2802 write_json_packet(capture_file *cf, frame_data *fdata,
2803 struct wtap_pkthdr *phdr, const guint8 *pd,
2806 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2808 /* Create the protocol tree, but don't fill in the column information. */
2809 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2811 /* Write out the information in that tree. */
2812 write_json_proto_tree(NULL, args->print_args->print_dissections,
2813 args->print_args->print_hex, NULL, PF_NONE,
2814 &args->edt, proto_node_group_children_by_unique, args->fh);
2816 epan_dissect_reset(&args->edt);
2818 return !ferror(args->fh);
2822 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2824 write_packet_callback_args_t callback_args;
2828 fh = ws_fopen(print_args->file, "w");
2830 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2832 write_json_preamble(fh);
2835 return CF_PRINT_WRITE_ERROR;
2838 callback_args.fh = fh;
2839 callback_args.print_args = print_args;
2840 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2842 /* Iterate through the list of packets, printing the packets we were
2844 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2845 "selected packets", TRUE,
2846 write_json_packet, &callback_args, TRUE);
2848 epan_dissect_cleanup(&callback_args.edt);
2853 /* Completed successfully. */
2857 /* Well, the user decided to abort the printing. */
2861 /* Error while printing. */
2863 return CF_PRINT_WRITE_ERROR;
2866 write_json_finale(fh);
2869 return CF_PRINT_WRITE_ERROR;
2872 /* XXX - check for an error */
2879 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2880 search_direction dir)
2884 mdata.string = string;
2885 mdata.string_len = strlen(string);
2886 return find_packet(cf, match_protocol_tree, &mdata, dir);
2890 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2892 mdata->frame_matched = FALSE;
2893 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2894 mdata->string_len = strlen(mdata->string);
2896 /* Iterate through all the nodes looking for matching text */
2897 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2898 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2902 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2904 match_data *mdata = (match_data *)criterion;
2907 /* Load the frame's data. */
2908 if (!cf_read_record(cf, fdata)) {
2909 /* Attempt to get the packet failed. */
2913 /* Construct the protocol tree, including the displayed text */
2914 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2915 /* We don't need the column information */
2916 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
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->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
3031 /* Find the Info column */
3032 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3033 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3034 /* Found it. See if we match. */
3035 info_column = edt.pi.cinfo->columns[colx].col_data;
3036 info_column_len = strlen(info_column);
3038 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3039 result = MR_MATCHED;
3043 for (i = 0; i < info_column_len; i++) {
3044 c_char = info_column[i];
3046 c_char = g_ascii_toupper(c_char);
3047 if (c_char == string[c_match]) {
3049 if (c_match == string_len) {
3050 result = MR_MATCHED;
3060 epan_dissect_cleanup(&edt);
3067 } cbs_t; /* "Counted byte string" */
3071 * The current match_* routines only support ASCII case insensitivity and don't
3072 * convert UTF-8 inputs to UTF-16 for matching.
3074 * We could modify them to use the GLib Unicode routines or the International
3075 * Components for Unicode library but it's not apparent that we could do so
3076 * without consuming a lot more CPU and memory or that searching would be
3077 * significantly better.
3081 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3082 search_direction dir)
3087 info.data_len = string_size;
3089 /* Regex, String or hex search? */
3091 /* Regular Expression search */
3092 return find_packet(cf, match_regex, NULL, dir);
3093 } else if (cf->string) {
3094 /* String search - what type of string? */
3095 switch (cf->scs_type) {
3097 case SCS_NARROW_AND_WIDE:
3098 return find_packet(cf, match_narrow_and_wide, &info, dir);
3101 return find_packet(cf, match_narrow, &info, dir);
3104 return find_packet(cf, match_wide, &info, dir);
3107 g_assert_not_reached();
3111 return find_packet(cf, match_binary, &info, dir);
3115 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3117 cbs_t *info = (cbs_t *)criterion;
3118 const guint8 *ascii_text = info->data;
3119 size_t textlen = info->data_len;
3120 match_result result;
3127 /* Load the frame's data. */
3128 if (!cf_read_record(cf, fdata)) {
3129 /* Attempt to get the packet failed. */
3133 result = MR_NOTMATCHED;
3134 buf_len = fdata->cap_len;
3135 pd = ws_buffer_start_ptr(&cf->buf);
3137 while (i < buf_len) {
3140 c_char = g_ascii_toupper(c_char);
3141 if (c_char != '\0') {
3142 if (c_char == ascii_text[c_match]) {
3144 if (c_match == textlen) {
3145 result = MR_MATCHED;
3146 cf->search_pos = i; /* Save the position of the last character
3147 for highlighting the field. */
3148 cf->search_len = (guint32)textlen;
3153 g_assert(i>=c_match);
3154 i -= (guint32)c_match;
3164 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3167 cbs_t *info = (cbs_t *)criterion;
3168 const guint8 *ascii_text = info->data;
3169 size_t textlen = info->data_len;
3170 match_result result;
3176 /* Load the frame's data. */
3177 if (!cf_read_record(cf, fdata)) {
3178 /* Attempt to get the packet failed. */
3182 result = MR_NOTMATCHED;
3183 buf_len = fdata->cap_len;
3184 pd = ws_buffer_start_ptr(&cf->buf);
3186 while (i < buf_len) {
3189 c_char = g_ascii_toupper(c_char);
3190 if (c_char == ascii_text[c_match]) {
3192 if (c_match == textlen) {
3193 result = MR_MATCHED;
3194 cf->search_pos = i; /* Save the position of the last character
3195 for highlighting the field. */
3196 cf->search_len = (guint32)textlen;
3201 g_assert(i>=c_match);
3202 i -= (guint32)c_match;
3212 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3214 cbs_t *info = (cbs_t *)criterion;
3215 const guint8 *ascii_text = info->data;
3216 size_t textlen = info->data_len;
3217 match_result result;
3224 /* Load the frame's data. */
3225 if (!cf_read_record(cf, fdata)) {
3226 /* Attempt to get the packet failed. */
3230 result = MR_NOTMATCHED;
3231 buf_len = fdata->cap_len;
3232 pd = ws_buffer_start_ptr(&cf->buf);
3234 while (i < buf_len) {
3237 c_char = g_ascii_toupper(c_char);
3238 if (c_char == ascii_text[c_match]) {
3240 if (c_match == textlen) {
3241 result = MR_MATCHED;
3242 cf->search_pos = i; /* Save the position of the last character
3243 for highlighting the field. */
3244 cf->search_len = (guint32)textlen;
3250 g_assert(i>=(c_match*2));
3251 i -= (guint32)c_match*2;
3260 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3262 cbs_t *info = (cbs_t *)criterion;
3263 const guint8 *binary_data = info->data;
3264 size_t datalen = info->data_len;
3265 match_result result;
3271 /* Load the frame's data. */
3272 if (!cf_read_record(cf, fdata)) {
3273 /* Attempt to get the packet failed. */
3277 result = MR_NOTMATCHED;
3278 buf_len = fdata->cap_len;
3279 pd = ws_buffer_start_ptr(&cf->buf);
3281 while (i < buf_len) {
3282 if (pd[i] == binary_data[c_match]) {
3284 if (c_match == datalen) {
3285 result = MR_MATCHED;
3286 cf->search_pos = i; /* Save the position of the last character
3287 for highlighting the field. */
3288 cf->search_len = (guint32)datalen;
3293 g_assert(i>=c_match);
3294 i -= (guint32)c_match;
3303 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3305 match_result result = MR_NOTMATCHED;
3306 GMatchInfo *match_info = NULL;
3308 /* Load the frame's data. */
3309 if (!cf_read_record(cf, fdata)) {
3310 /* Attempt to get the packet failed. */
3314 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3315 0, (GRegexMatchFlags) 0, &match_info, NULL))
3317 gint start_pos = 0, end_pos = 0;
3318 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3319 cf->search_pos = end_pos - 1;
3320 cf->search_len = end_pos - start_pos;
3321 result = MR_MATCHED;
3327 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3328 search_direction dir)
3330 return find_packet(cf, match_dfilter, sfcode, dir);
3334 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3335 search_direction dir)
3340 if (!dfilter_compile(filter, &sfcode, NULL)) {
3342 * XXX - this shouldn't happen, as the filter string is machine
3347 if (sfcode == NULL) {
3349 * XXX - this shouldn't happen, as the filter string is machine
3354 result = find_packet(cf, match_dfilter, sfcode, dir);
3355 dfilter_free(sfcode);
3360 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3362 dfilter_t *sfcode = (dfilter_t *)criterion;
3364 match_result result;
3366 /* Load the frame's data. */
3367 if (!cf_read_record(cf, fdata)) {
3368 /* Attempt to get the packet failed. */
3372 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3373 epan_dissect_prime_with_dfilter(&edt, sfcode);
3374 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3375 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3376 epan_dissect_cleanup(&edt);
3381 cf_find_packet_marked(capture_file *cf, search_direction dir)
3383 return find_packet(cf, match_marked, NULL, dir);
3387 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3389 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3393 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3395 return find_packet(cf, match_time_reference, NULL, dir);
3399 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3401 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3405 find_packet(capture_file *cf,
3406 match_result (*match_function)(capture_file *, frame_data *, void *),
3407 void *criterion, search_direction dir)
3409 frame_data *start_fd;
3412 frame_data *new_fd = NULL;
3413 progdlg_t *progbar = NULL;
3414 GTimer *prog_timer = g_timer_new();
3418 GTimeVal start_time;
3419 gchar status_str[100];
3421 match_result result;
3423 start_fd = cf->current_frame;
3424 if (start_fd != NULL) {
3425 /* Iterate through the list of packets, starting at the packet we've
3426 picked, calling a routine to run the filter on the packet, see if
3427 it matches, and stop if so. */
3429 framenum = start_fd->num;
3431 g_timer_start(prog_timer);
3432 /* Progress so far. */
3435 cf->stop_flag = FALSE;
3436 g_get_current_time(&start_time);
3438 title = cf->sfilter?cf->sfilter:"";
3440 /* Create the progress bar if necessary.
3441 We check on every iteration of the loop, so that it takes no
3442 longer than the standard time to create it (otherwise, for a
3443 large file, we might take considerably longer than that standard
3444 time in order to get to the next progress bar step). */
3445 if (progbar == NULL)
3446 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3447 FALSE, &cf->stop_flag, &start_time, progbar_val);
3450 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3451 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3452 * likely trigger UI paint events, which might take a while depending on
3453 * the platform and display. Reset our timer *after* painting.
3455 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3456 /* let's not divide by zero. I should never be started
3457 * with count == 0, so let's assert that
3459 g_assert(cf->count > 0);
3461 progbar_val = (gfloat) count / cf->count;
3463 g_snprintf(status_str, sizeof(status_str),
3464 "%4u of %u packets", count, cf->count);
3465 update_progress_dlg(progbar, progbar_val, status_str);
3467 g_timer_start(prog_timer);
3470 if (cf->stop_flag) {
3471 /* Well, the user decided to abort the search. Go back to the
3472 frame where we started. */
3477 /* Go past the current frame. */
3478 if (dir == SD_BACKWARD) {
3479 /* Go on to the previous frame. */
3480 if (framenum == 1) {
3482 * XXX - other apps have a bit more of a detailed message
3483 * for this, and instead of offering "OK" and "Cancel",
3484 * they offer things such as "Continue" and "Cancel";
3485 * we need an API for popping up alert boxes with
3486 * {Verb} and "Cancel".
3489 if (prefs.gui_find_wrap)
3491 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3492 framenum = cf->count; /* wrap around */
3496 statusbar_push_temporary_msg("Search reached the beginning.");
3497 framenum = start_fd->num; /* stay on previous packet */
3502 /* Go on to the next frame. */
3503 if (framenum == cf->count) {
3504 if (prefs.gui_find_wrap)
3506 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3507 framenum = 1; /* wrap around */
3511 statusbar_push_temporary_msg("Search reached the end.");
3512 framenum = start_fd->num; /* stay on previous packet */
3517 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
3521 /* Is this packet in the display? */
3522 if (fdata->flags.passed_dfilter) {
3523 /* Yes. Does it match the search criterion? */
3524 result = (*match_function)(cf, fdata, criterion);
3525 if (result == MR_ERROR) {
3526 /* Error; our caller has reported the error. Go back to the frame
3527 where we started. */
3530 } else if (result == MR_MATCHED) {
3531 /* Yes. Go to the new frame. */
3537 if (fdata == start_fd) {
3538 /* We're back to the frame we were on originally, and that frame
3539 doesn't match the search filter. The search failed. */
3544 /* We're done scanning the packets; destroy the progress bar if it
3546 if (progbar != NULL)
3547 destroy_progress_dlg(progbar);
3548 g_timer_destroy(prog_timer);
3551 if (new_fd != NULL) {
3552 /* Find and select */
3553 cf->search_in_progress = TRUE;
3554 found = packet_list_select_row_from_data(new_fd);
3555 cf->search_in_progress = FALSE;
3556 cf->search_pos = 0; /* Reset the position */
3557 cf->search_len = 0; /* Reset length */
3559 /* We didn't find a row corresponding to this frame.
3560 This means that the frame isn't being displayed currently,
3561 so we can't select it. */
3562 simple_message_box(ESD_TYPE_INFO, NULL,
3563 "The capture file is probably not fully dissected.",
3564 "End of capture exceeded.");
3567 return TRUE; /* success */
3569 return FALSE; /* failure */
3573 cf_goto_frame(capture_file *cf, guint fnumber)
3577 if (cf == NULL || cf->frame_set_info.frames == NULL) {
3578 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3579 statusbar_push_temporary_msg("There is no file loaded");
3580 return FALSE; /* we failed to go to that packet */
3583 fdata = frame_data_sequence_find(cf->frame_set_info.frames, fnumber);
3585 if (fdata == NULL) {
3586 /* we didn't find a packet with that packet number */
3587 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3588 return FALSE; /* we failed to go to that packet */
3590 if (!fdata->flags.passed_dfilter) {
3591 /* that packet currently isn't displayed */
3592 /* XXX - add it to the set of displayed packets? */
3593 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3594 return FALSE; /* we failed to go to that packet */
3597 if (!packet_list_select_row_from_data(fdata)) {
3598 /* We didn't find a row corresponding to this frame.
3599 This means that the frame isn't being displayed currently,
3600 so we can't select it. */
3601 simple_message_box(ESD_TYPE_INFO, NULL,
3602 "The capture file is probably not fully dissected.",
3603 "End of capture exceeded.");
3606 return TRUE; /* we got to that packet */
3610 * Go to frame specified by currently selected protocol tree item.
3613 cf_goto_framenum(capture_file *cf)
3615 header_field_info *hfinfo;
3618 if (cf->finfo_selected) {
3619 hfinfo = cf->finfo_selected->hfinfo;
3621 if (hfinfo->type == FT_FRAMENUM) {
3622 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3624 return cf_goto_frame(cf, framenum);
3631 /* Select the packet on a given row. */
3633 cf_select_packet(capture_file *cf, int row)
3635 epan_dissect_t *old_edt;
3638 /* Get the frame data struct pointer for this frame */
3639 fdata = packet_list_get_row_data(row);
3641 if (fdata == NULL) {
3645 /* Get the data in that frame. */
3646 if (!cf_read_record (cf, fdata)) {
3650 /* Record that this frame is the current frame. */
3651 cf->current_frame = fdata;
3652 cf->current_row = row;
3655 /* Create the logical protocol tree. */
3656 /* We don't need the columns here. */
3657 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3659 tap_build_interesting(cf->edt);
3660 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3661 cf->current_frame, NULL);
3663 dfilter_macro_build_ftv_cache(cf->edt->tree);
3665 cf_callback_invoke(cf_cb_packet_selected, cf);
3667 if (old_edt != NULL)
3668 epan_dissect_free(old_edt);
3672 /* Unselect the selected packet, if any. */
3674 cf_unselect_packet(capture_file *cf)
3676 epan_dissect_t *old_edt = cf->edt;
3680 /* No packet is selected. */
3681 cf->current_frame = NULL;
3682 cf->current_row = 0;
3684 cf_callback_invoke(cf_cb_packet_unselected, cf);
3686 /* No protocol tree means no selected field. */
3687 cf_unselect_field(cf);
3689 /* Destroy the epan_dissect_t for the unselected packet. */
3690 if (old_edt != NULL)
3691 epan_dissect_free(old_edt);
3694 /* Unset the selected protocol tree field, if any. */
3696 cf_unselect_field(capture_file *cf)
3698 cf->finfo_selected = NULL;
3700 cf_callback_invoke(cf_cb_field_unselected, cf);
3704 * Mark a particular frame.
3707 cf_mark_frame(capture_file *cf, frame_data *frame)
3709 if (! frame->flags.marked) {
3710 frame->flags.marked = TRUE;
3711 if (cf->count > cf->marked_count)
3717 * Unmark a particular frame.
3720 cf_unmark_frame(capture_file *cf, frame_data *frame)
3722 if (frame->flags.marked) {
3723 frame->flags.marked = FALSE;
3724 if (cf->marked_count > 0)
3730 * Ignore a particular frame.
3733 cf_ignore_frame(capture_file *cf, frame_data *frame)
3735 if (! frame->flags.ignored) {
3736 frame->flags.ignored = TRUE;
3737 if (cf->count > cf->ignored_count)
3738 cf->ignored_count++;
3743 * Un-ignore a particular frame.
3746 cf_unignore_frame(capture_file *cf, frame_data *frame)
3748 if (frame->flags.ignored) {
3749 frame->flags.ignored = FALSE;
3750 if (cf->ignored_count > 0)
3751 cf->ignored_count--;
3756 * Read the section comment.
3759 cf_read_section_comment(capture_file *cf)
3761 wtap_block_t shb_inf;
3765 /* XXX - support multiple SHBs */
3766 shb_inf = wtap_file_get_shb(cf->frame_set_info.wth);
3768 /* Get the first comment from the SHB. */
3769 /* XXX - support multiple comments */
3770 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3776 * Modify the section comment.
3779 cf_update_section_comment(capture_file *cf, gchar *comment)
3781 wtap_block_t shb_inf;
3785 /* XXX - support multiple SHBs */
3786 shb_inf = wtap_file_get_shb(cf->frame_set_info.wth);
3788 /* Get the first comment from the SHB. */
3789 /* XXX - support multiple comments */
3790 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3791 /* There's no comment - add one. */
3792 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3794 /* See if the comment has changed or not */
3795 if (strcmp(shb_comment, comment) == 0) {
3800 /* The comment has changed, let's update it */
3801 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3803 /* Mark the file as having unsaved changes */
3804 cf->unsaved_changes = TRUE;
3808 cf_get_user_packet_comment(frame_set *fs, const frame_data *fd)
3810 if (fs->frames_user_comments)
3811 return (const char *)g_tree_lookup(fs->frames_user_comments, fd);
3818 * Get the comment on a packet (record).
3819 * If the comment has been edited, it returns the result of the edit,
3820 * otherwise it returns the comment from the file.
3823 cf_get_packet_comment(capture_file *cf, const frame_data *fd)
3827 /* fetch user comment */
3828 if (fd->flags.has_user_comment)
3829 return g_strdup(cf_get_user_packet_comment(&cf->frame_set_info, fd));
3831 /* fetch phdr comment */
3832 if (fd->flags.has_phdr_comment) {
3833 struct wtap_pkthdr phdr; /* Packet header */
3834 Buffer buf; /* Packet data */
3836 wtap_phdr_init(&phdr);
3837 ws_buffer_init(&buf, 1500);
3839 if (!cf_read_record_r(cf, fd, &phdr, &buf))
3840 { /* XXX, what we can do here? */ }
3842 comment = phdr.opt_comment;
3843 wtap_phdr_cleanup(&phdr);
3844 ws_buffer_free(&buf);
3851 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3853 const frame_data *fdata1 = (const frame_data *) a;
3854 const frame_data *fdata2 = (const frame_data *) b;
3856 return (fdata1->num < fdata2->num) ? -1 :
3857 (fdata1->num > fdata2->num) ? 1 :
3862 * Update(replace) the comment on a capture from a frame
3865 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3867 char *pkt_comment = cf_get_packet_comment(cf, fd);
3869 /* Check if the comment has changed */
3870 if (!g_strcmp0(pkt_comment, new_comment)) {
3871 g_free(pkt_comment);
3874 g_free(pkt_comment);
3877 cf->packet_comment_count--;
3880 cf->packet_comment_count++;
3882 fd->flags.has_user_comment = TRUE;
3884 if (!cf->frame_set_info.frames_user_comments)
3885 cf->frame_set_info.frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
3887 /* insert new packet comment */
3888 g_tree_replace(cf->frame_set_info.frames_user_comments, fd, g_strdup(new_comment));
3890 expert_update_comment_count(cf->packet_comment_count);
3892 /* OK, we have unsaved changes. */
3893 cf->unsaved_changes = TRUE;
3898 * What types of comments does this capture file have?
3901 cf_comment_types(capture_file *cf)
3903 guint32 comment_types = 0;
3905 if (cf_read_section_comment(cf) != NULL)
3906 comment_types |= WTAP_COMMENT_PER_SECTION;
3907 if (cf->packet_comment_count != 0)
3908 comment_types |= WTAP_COMMENT_PER_PACKET;
3909 return comment_types;
3913 * Add a resolved address to this file's list of resolved addresses.
3916 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
3919 * XXX - support multiple resolved address lists, and add to the one
3920 * attached to this file?
3922 if (!add_ip_name_from_string(addr, name))
3925 /* OK, we have unsaved changes. */
3926 cf->unsaved_changes = TRUE;
3934 } save_callback_args_t;
3937 * Save a capture to a file, in a particular format, saving either
3938 * all packets, all currently-displayed packets, or all marked packets.
3940 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3941 * up a message box for the failure.
3944 save_record(capture_file *cf, frame_data *fdata,
3945 struct wtap_pkthdr *phdr, const guint8 *pd,
3948 save_callback_args_t *args = (save_callback_args_t *)argsp;
3949 struct wtap_pkthdr hdr;
3952 const char *pkt_comment;
3954 if (fdata->flags.has_user_comment)
3955 pkt_comment = cf_get_user_packet_comment(&cf->frame_set_info, fdata);
3957 pkt_comment = phdr->opt_comment;
3959 /* init the wtap header for saving */
3960 /* TODO: reuse phdr */
3961 /* XXX - these are the only flags that correspond to data that we have
3962 in the frame_data structure and that matter on a per-packet basis.
3964 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
3965 and "on the wire" lengths, or it doesn't.
3967 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
3970 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
3971 from the packet flags. */
3972 hdr.rec_type = phdr->rec_type;
3973 hdr.presence_flags = 0;
3974 if (fdata->flags.has_ts)
3975 hdr.presence_flags |= WTAP_HAS_TS;
3976 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
3977 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
3978 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
3979 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
3981 hdr.caplen = phdr->caplen;
3982 hdr.len = phdr->len;
3983 hdr.pkt_encap = phdr->pkt_encap;
3985 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
3987 hdr.pack_flags = phdr->pack_flags;
3988 hdr.opt_comment = g_strdup(pkt_comment);
3989 hdr.has_comment_changed = fdata->flags.has_user_comment ? TRUE : FALSE;
3992 hdr.pseudo_header = phdr->pseudo_header;
3995 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
3997 /* and save the packet */
3998 if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
3999 cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
4004 g_free(hdr.opt_comment);
4009 * Can this capture file be written out in any format using Wiretap
4010 * rather than by copying the raw data?
4013 cf_can_write_with_wiretap(capture_file *cf)
4015 /* We don't care whether we support the comments in this file or not;
4016 if we can't, we'll offer the user the option of discarding the
4018 return wtap_dump_can_write(cf->linktypes, 0);
4022 * Should we let the user do a save?
4026 * the file has unsaved changes, and we can save it in some
4027 * format through Wiretap
4031 * the file is a temporary file and has no unsaved changes (so
4032 * that "saving" it just means copying it).
4034 * XXX - we shouldn't allow files to be edited if they can't be saved,
4035 * so cf->unsaved_changes should be true only if the file can be saved.
4037 * We don't care whether we support the comments in this file or not;
4038 * if we can't, we'll offer the user the option of discarding the
4042 cf_can_save(capture_file *cf)
4044 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4045 /* Saved changes, and we can write it out with Wiretap. */
4049 if (cf->is_tempfile && !cf->unsaved_changes) {
4051 * Temporary file with no unsaved changes, so we can just do a
4057 /* Nothing to save. */
4062 * Should we let the user do a "save as"?
4066 * we can save it in some format through Wiretap
4070 * the file is a temporary file and has no unsaved changes (so
4071 * that "saving" it just means copying it).
4073 * XXX - we shouldn't allow files to be edited if they can't be saved,
4074 * so cf->unsaved_changes should be true only if the file can be saved.
4076 * We don't care whether we support the comments in this file or not;
4077 * if we can't, we'll offer the user the option of discarding the
4081 cf_can_save_as(capture_file *cf)
4083 if (wtap_dump_can_write(cf->linktypes, 0)) {
4084 /* We can write it out with Wiretap. */
4088 if (cf->is_tempfile && !cf->unsaved_changes) {
4090 * Temporary file with no unsaved changes, so we can just do a
4096 /* Nothing to save. */
4101 * Does this file have unsaved data?
4104 cf_has_unsaved_data(capture_file *cf)
4107 * If this is a temporary file, or a file with unsaved changes, it
4110 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4114 * Quick scan to find packet offsets.
4116 static cf_read_status_t
4117 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4119 const struct wtap_pkthdr *phdr;
4124 progdlg_t *progbar = NULL;
4125 GTimer *prog_timer = g_timer_new();
4128 GTimeVal start_time;
4129 gchar status_str[100];
4134 /* Close the old handle. */
4135 wtap_close(cf->frame_set_info.wth);
4137 /* Open the new file. */
4138 /* XXX: this will go through all open_routines for a matching one. But right
4139 now rescan_file() is only used when a file is being saved to a different
4140 format than the original, and the user is not given a choice of which
4141 reader to use (only which format to save it in), so doing this makes
4143 cf->frame_set_info.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4144 if (cf->frame_set_info.wth == NULL) {
4145 cfile_open_failure_alert_box(fname, err, err_info);
4146 return CF_READ_ERROR;
4149 /* We're scanning a file whose contents should be the same as what
4150 we had before, so we don't discard dissection state etc.. */
4153 /* Set the file name because we need it to set the follow stream filter.
4154 XXX - is that still true? We need it for other reasons, though,
4156 cf->filename = g_strdup(fname);
4158 /* Indicate whether it's a permanent or temporary file. */
4159 cf->is_tempfile = is_tempfile;
4161 /* No user changes yet. */
4162 cf->unsaved_changes = FALSE;
4164 cf->cd_t = wtap_file_type_subtype(cf->frame_set_info.wth);
4165 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4167 cf->snap = wtap_snapshot_length(cf->frame_set_info.wth);
4169 name_ptr = g_filename_display_basename(cf->filename);
4171 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4173 /* Record whether the file is compressed.
4174 XXX - do we know this at open time? */
4175 cf->iscompressed = wtap_iscompressed(cf->frame_set_info.wth);
4177 /* Find the size of the file. */
4178 size = wtap_file_size(cf->frame_set_info.wth, NULL);
4180 g_timer_start(prog_timer);
4182 cf->stop_flag = FALSE;
4183 g_get_current_time(&start_time);
4186 phdr = wtap_phdr(cf->frame_set_info.wth);
4187 while ((wtap_read(cf->frame_set_info.wth, &err, &err_info, &data_offset))) {
4189 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
4190 fdata->file_off = data_offset;
4193 cf->f_datalen = wtap_read_so_far(cf->frame_set_info.wth);
4195 /* Create the progress bar if necessary. */
4196 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4197 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4198 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4199 TRUE, &cf->stop_flag, &start_time, progbar_val);
4203 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4204 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4205 * likely trigger UI paint events, which might take a while depending on
4206 * the platform and display. Reset our timer *after* painting.
4208 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4209 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4210 /* update the packet bar content on the first run or frequently on very large files */
4211 update_progress_dlg(progbar, progbar_val, status_str);
4212 compute_elapsed(cf, &start_time);
4213 packets_bar_update();
4214 g_timer_start(prog_timer);
4218 if (cf->stop_flag) {
4219 /* Well, the user decided to abort the rescan. Sadly, as this
4220 isn't a reread, recovering is difficult, so we'll just
4221 close the current capture. */
4225 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4226 it's not already there.
4227 XXX - yes, this is O(N), so if every packet had a different
4228 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4229 there are probably going to be a small number of encapsulation types
4231 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4234 /* Free the display name */
4237 /* We're done reading the file; destroy the progress bar if it was created. */
4238 if (progbar != NULL)
4239 destroy_progress_dlg(progbar);
4240 g_timer_destroy(prog_timer);
4242 /* We're done reading sequentially through the file. */
4243 cf->state = FILE_READ_DONE;
4245 /* Close the sequential I/O side, to free up memory it requires. */
4246 wtap_sequential_close(cf->frame_set_info.wth);
4248 /* compute the time it took to load the file */
4249 compute_elapsed(cf, &start_time);
4251 /* Set the file encapsulation type now; we don't know what it is until
4252 we've looked at all the packets, as we don't know until then whether
4253 there's more than one type (and thus whether it's
4254 WTAP_ENCAP_PER_PACKET). */
4255 cf->lnk_t = wtap_file_encap(cf->frame_set_info.wth);
4257 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4259 if (cf->stop_flag) {
4260 /* Our caller will give up at this point. */
4261 return CF_READ_ABORTED;
4265 /* Put up a message box noting that the read failed somewhere along
4266 the line. Don't throw out the stuff we managed to read, though,
4268 cfile_read_failure_alert_box(NULL, err, err_info);
4269 return CF_READ_ERROR;
4275 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4276 gboolean compressed, gboolean discard_comments,
4277 gboolean dont_reopen)
4280 gchar *fname_new = NULL;
4283 addrinfo_lists_t *addr_lists;
4287 gchar *display_basename;
4294 save_callback_args_t callback_args;
4295 gboolean needs_reload = FALSE;
4297 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4299 addr_lists = get_addrinfo_list();
4301 if (save_format == cf->cd_t && compressed == cf->iscompressed
4302 && !discard_comments && !cf->unsaved_changes
4303 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4304 /* We're saving in the format it's already in, and we're
4305 not discarding comments, and there are no changes we have
4306 in memory that aren't saved to the file, and we have no name
4307 resolution blocks to write, so we can just move or copy the raw data. */
4309 if (cf->is_tempfile) {
4310 /* The file being saved is a temporary file from a live
4311 capture, so it doesn't need to stay around under that name;
4312 first, try renaming the capture buffer file to the new name.
4313 This acts as a "safe save", in that, if the file already
4314 exists, the existing file will be removed only if the rename
4317 Sadly, on Windows, as we have the current capture file
4318 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4319 (to cause the rename to remove an existing target), as
4320 done by ws_stdio_rename() (ws_rename() is #defined to
4321 be ws_stdio_rename() on Windows) will fail.
4323 According to the MSDN documentation for CreateFile(), if,
4324 when we open a capture file, we were to directly do a CreateFile(),
4325 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4326 convert it to a file descriptor with _open_osfhandle(),
4327 that would allow the file to be renamed out from under us.
4329 However, that doesn't work in practice. Perhaps the problem
4330 is that the process doing the rename is the process that
4331 has the file open. */
4333 if (ws_rename(cf->filename, fname) == 0) {
4334 /* That succeeded - there's no need to copy the source file. */
4335 how_to_save = SAVE_WITH_MOVE;
4337 if (errno == EXDEV) {
4338 /* They're on different file systems, so we have to copy the
4340 how_to_save = SAVE_WITH_COPY;
4342 /* The rename failed, but not because they're on different
4343 file systems - put up an error message. (Or should we
4344 just punt and try to copy? The only reason why I'd
4345 expect the rename to fail and the copy to succeed would
4346 be if we didn't have permission to remove the file from
4347 the temporary directory, and that might be fixable - but
4348 is it worth requiring the user to go off and fix it?) */
4349 cf_rename_failure_alert_box(fname, errno);
4354 how_to_save = SAVE_WITH_COPY;
4357 /* It's a permanent file, so we should copy it, and not remove the
4359 how_to_save = SAVE_WITH_COPY;
4362 if (how_to_save == SAVE_WITH_COPY) {
4363 /* Copy the file, if we haven't moved it. If we're overwriting
4364 an existing file, we do it with a "safe save", by writing
4365 to a new file and, if the write succeeds, renaming the
4366 new file on top of the old file. */
4367 if (file_exists(fname)) {
4368 fname_new = g_strdup_printf("%s~", fname);
4369 if (!copy_file_binary_mode(cf->filename, fname_new))
4372 if (!copy_file_binary_mode(cf->filename, fname))
4377 /* Either we're saving in a different format or we're saving changes,
4378 such as added, modified, or removed comments, that haven't yet
4379 been written to the underlying file; we can't do that by copying
4380 or moving the capture file, we have to do it by writing the packets
4383 GArray *shb_hdrs = NULL;
4384 wtapng_iface_descriptions_t *idb_inf = NULL;
4385 GArray *nrb_hdrs = NULL;
4388 /* XXX: what free's this shb_hdr? */
4389 shb_hdrs = wtap_file_get_shb_for_new_file(cf->frame_set_info.wth);
4390 idb_inf = wtap_file_get_idb_info(cf->frame_set_info.wth);
4391 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->frame_set_info.wth);
4393 /* Determine what file encapsulation type we should use. */
4394 encap = wtap_dump_file_encap_type(cf->linktypes);
4396 if (file_exists(fname)) {
4397 /* We're overwriting an existing file; write out to a new file,
4398 and, if that succeeds, rename the new file on top of the
4399 old file. That makes this a "safe save", so that we don't
4400 lose the old file if we have a problem writing out the new
4401 file. (If the existing file is the current capture file,
4402 we *HAVE* to do that, otherwise we're overwriting the file
4403 from which we're reading the packets that we're writing!) */
4404 fname_new = g_strdup_printf("%s~", fname);
4405 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4406 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4408 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4409 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4415 cfile_dump_open_failure_alert_box(fname, err, save_format);
4419 /* Add address resolution */
4420 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4422 /* Iterate through the list of packets, processing all the packets. */
4423 callback_args.pdh = pdh;
4424 callback_args.fname = fname;
4425 callback_args.file_type = save_format;
4426 switch (process_specified_records(cf, NULL, "Saving", "packets",
4427 TRUE, save_record, &callback_args, TRUE)) {
4430 /* Completed successfully. */
4434 /* The user decided to abort the saving.
4435 If we're writing to a temporary file, remove it.
4436 XXX - should we do so even if we're not writing to a
4438 wtap_dump_close(pdh, &err);
4439 if (fname_new != NULL)
4440 ws_unlink(fname_new);
4441 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4442 return CF_WRITE_ABORTED;
4445 /* Error while saving.
4446 If we're writing to a temporary file, remove it. */
4447 if (fname_new != NULL)
4448 ws_unlink(fname_new);
4449 wtap_dump_close(pdh, &err);
4453 needs_reload = wtap_dump_get_needs_reload(pdh);
4455 if (!wtap_dump_close(pdh, &err)) {
4456 cfile_close_failure_alert_box(fname, err);
4460 how_to_save = SAVE_WITH_WTAP;
4463 if (fname_new != NULL) {
4464 /* We wrote out to fname_new, and should rename it on top of
4465 fname. fname_new is now closed, so that should be possible even
4466 on Windows. However, on Windows, we first need to close whatever
4467 file descriptors we have open for fname. */
4469 wtap_fdclose(cf->frame_set_info.wth);
4471 /* Now do the rename. */
4472 if (ws_rename(fname_new, fname) == -1) {
4473 /* Well, the rename failed. */
4474 cf_rename_failure_alert_box(fname, errno);
4476 /* Attempt to reopen the random file descriptor using the
4477 current file's filename. (At this point, the sequential
4478 file descriptor is closed.) */
4479 if (!wtap_fdreopen(cf->frame_set_info.wth, cf->filename, &err)) {
4480 /* Oh, well, we're screwed. */
4481 display_basename = g_filename_display_basename(cf->filename);
4482 simple_error_message_box(
4483 file_open_error_message(err, FALSE), display_basename);
4484 g_free(display_basename);
4491 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4492 cf->unsaved_changes = FALSE;
4495 switch (how_to_save) {
4497 case SAVE_WITH_MOVE:
4498 /* We just moved the file, so the wtap structure refers to the
4499 new file, and all the information other than the filename
4500 and the "is temporary" status applies to the new file; just
4502 g_free(cf->filename);
4503 cf->filename = g_strdup(fname);
4504 cf->is_tempfile = FALSE;
4505 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4508 case SAVE_WITH_COPY:
4509 /* We just copied the file, s all the information other than
4510 the wtap structure, the filename, and the "is temporary"
4511 status applies to the new file; just update that. */
4512 wtap_close(cf->frame_set_info.wth);
4513 /* Although we're just "copying" and then opening the copy, it will
4514 try all open_routine readers to open the copy, so we need to
4515 reset the cfile's open_type. */
4516 cf->open_type = WTAP_TYPE_AUTO;
4517 cf->frame_set_info.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4518 if (cf->frame_set_info.wth == NULL) {
4519 cfile_open_failure_alert_box(fname, err, err_info);
4522 g_free(cf->filename);
4523 cf->filename = g_strdup(fname);
4524 cf->is_tempfile = FALSE;
4526 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4529 case SAVE_WITH_WTAP:
4530 /* Open and read the file we saved to.
4532 XXX - this is somewhat of a waste; we already have the
4533 packets, all this gets us is updated file type information
4534 (which we could just stuff into "cf"), and having the new
4535 file be the one we have opened and from which we're reading
4536 the data, and it means we have to spend time opening and
4537 reading the file, which could be a significant amount of
4538 time if the file is large.
4540 If the capture-file-writing code were to return the
4541 seek offset of each packet it writes, we could save that
4542 in the frame_data structure for the frame, and just open
4543 the file without reading it again...
4545 ...as long as, for gzipped files, the process of writing
4546 out the file *also* generates the information needed to
4547 support fast random access to the compressed file. */
4548 /* rescan_file will cause us to try all open_routines, so
4549 reset cfile's open_type */
4550 cf->open_type = WTAP_TYPE_AUTO;
4551 /* There are cases when SAVE_WITH_WTAP can result in new packets
4552 being written to the file, e.g ERF records
4553 In that case, we need to reload the whole file */
4555 if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) {
4556 if (cf_read(cf, TRUE) != CF_READ_OK) {
4557 /* The rescan failed; just close the file. Either
4558 a dialog was popped up for the failure, so the
4559 user knows what happened, or they stopped the
4560 rescan, in which case they know what happened. */
4561 /* XXX: This is inconsistent with normal open/reload behaviour. */
4567 if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4568 /* The rescan failed; just close the file. Either
4569 a dialog was popped up for the failure, so the
4570 user knows what happened, or they stopped the
4571 rescan, in which case they know what happened. */
4578 /* If we were told to discard the comments, do so. */
4579 if (discard_comments) {
4580 /* Remove SHB comment, if any. */
4581 wtap_write_shb_comment(cf->frame_set_info.wth, NULL);
4583 /* remove all user comments */
4584 for (framenum = 1; framenum <= cf->count; framenum++) {
4585 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
4587 fdata->flags.has_phdr_comment = FALSE;
4588 fdata->flags.has_user_comment = FALSE;
4591 if (cf->frame_set_info.frames_user_comments) {
4592 g_tree_destroy(cf->frame_set_info.frames_user_comments);
4593 cf->frame_set_info.frames_user_comments = NULL;
4596 cf->packet_comment_count = 0;
4602 if (fname_new != NULL) {
4603 /* We were trying to write to a temporary file; get rid of it if it
4604 exists. (We don't care whether this fails, as, if it fails,
4605 there's not much we can do about it. I guess if it failed for
4606 a reason other than "it doesn't exist", we could report an
4607 error, so the user knows there's a junk file that they might
4608 want to clean up.) */
4609 ws_unlink(fname_new);
4612 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4613 return CF_WRITE_ERROR;
4617 cf_export_specified_packets(capture_file *cf, const char *fname,
4618 packet_range_t *range, guint save_format,
4619 gboolean compressed)
4621 gchar *fname_new = NULL;
4624 save_callback_args_t callback_args;
4625 GArray *shb_hdrs = NULL;
4626 wtapng_iface_descriptions_t *idb_inf = NULL;
4627 GArray *nrb_hdrs = NULL;
4630 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4632 packet_range_process_init(range);
4634 /* We're writing out specified packets from the specified capture
4635 file to another file. Even if all captured packets are to be
4636 written, don't special-case the operation - read each packet
4637 and then write it out if it's one of the specified ones. */
4639 /* XXX: what free's this shb_hdr? */
4640 shb_hdrs = wtap_file_get_shb_for_new_file(cf->frame_set_info.wth);
4641 idb_inf = wtap_file_get_idb_info(cf->frame_set_info.wth);
4642 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->frame_set_info.wth);
4644 /* Determine what file encapsulation type we should use. */
4645 encap = wtap_dump_file_encap_type(cf->linktypes);
4647 if (file_exists(fname)) {
4648 /* We're overwriting an existing file; write out to a new file,
4649 and, if that succeeds, rename the new file on top of the
4650 old file. That makes this a "safe save", so that we don't
4651 lose the old file if we have a problem writing out the new
4652 file. (If the existing file is the current capture file,
4653 we *HAVE* to do that, otherwise we're overwriting the file
4654 from which we're reading the packets that we're writing!) */
4655 fname_new = g_strdup_printf("%s~", fname);
4656 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4657 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4659 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4660 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4666 cfile_dump_open_failure_alert_box(fname, err, save_format);
4670 /* Add address resolution */
4671 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4673 /* Iterate through the list of packets, processing the packets we were
4676 XXX - we've already called "packet_range_process_init(range)", but
4677 "process_specified_records()" will do it again. Fortunately,
4678 that's harmless in this case, as we haven't done anything to
4679 "range" since we initialized it. */
4680 callback_args.pdh = pdh;
4681 callback_args.fname = fname;
4682 callback_args.file_type = save_format;
4683 switch (process_specified_records(cf, range, "Writing", "specified records",
4684 TRUE, save_record, &callback_args, TRUE)) {
4687 /* Completed successfully. */
4691 /* The user decided to abort the saving.
4692 If we're writing to a temporary file, remove it.
4693 XXX - should we do so even if we're not writing to a
4695 wtap_dump_close(pdh, &err);
4696 if (fname_new != NULL)
4697 ws_unlink(fname_new);
4698 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4699 return CF_WRITE_ABORTED;
4703 /* Error while saving.
4704 If we're writing to a temporary file, remove it. */
4705 if (fname_new != NULL)
4706 ws_unlink(fname_new);
4707 wtap_dump_close(pdh, &err);
4711 if (!wtap_dump_close(pdh, &err)) {
4712 cfile_close_failure_alert_box(fname, err);
4716 if (fname_new != NULL) {
4717 /* We wrote out to fname_new, and should rename it on top of
4718 fname; fname is now closed, so that should be possible even
4719 on Windows. Do the rename. */
4720 if (ws_rename(fname_new, fname) == -1) {
4721 /* Well, the rename failed. */
4722 cf_rename_failure_alert_box(fname, errno);
4727 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4731 if (fname_new != NULL) {
4732 /* We were trying to write to a temporary file; get rid of it if it
4733 exists. (We don't care whether this fails, as, if it fails,
4734 there's not much we can do about it. I guess if it failed for
4735 a reason other than "it doesn't exist", we could report an
4736 error, so the user knows there's a junk file that they might
4737 want to clean up.) */
4738 ws_unlink(fname_new);
4741 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4742 return CF_WRITE_ERROR;
4746 * XXX - whether we mention the source pathname, the target pathname,
4747 * or both depends on the error and on what we find if we look for
4748 * one or both of them.
4751 cf_rename_failure_alert_box(const char *filename, int err)
4753 gchar *display_basename;
4755 display_basename = g_filename_display_basename(filename);
4759 /* XXX - should check whether the source exists and, if not,
4760 report it as the problem and, if so, report the destination
4762 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4767 /* XXX - if we're doing a rename after a safe save, we should
4768 probably say something else. */
4769 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4774 /* XXX - this should probably mention both the source and destination
4776 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4777 display_basename, wtap_strerror(err));
4780 g_free(display_basename);
4783 /* Reload the current capture file. */
4785 cf_reload(capture_file *cf) {
4787 gboolean is_tempfile;
4790 /* If the file could be opened, "cf_open()" calls "cf_close()"
4791 to get rid of state for the old capture file before filling in state
4792 for the new capture file. "cf_close()" will remove the file if
4793 it's a temporary file; we don't want that to happen (for one thing,
4794 it'd prevent subsequent reopens from working). Remember whether it's
4795 a temporary file, mark it as not being a temporary file, and then
4796 reopen it as the type of file it was.
4798 Also, "cf_close()" will free "cf->filename", so we must make
4799 a copy of it first. */
4800 filename = g_strdup(cf->filename);
4801 is_tempfile = cf->is_tempfile;
4802 cf->is_tempfile = FALSE;
4803 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4804 switch (cf_read(cf, TRUE)) {
4808 /* Just because we got an error, that doesn't mean we were unable
4809 to read any of the file; we handle what we could get from the
4813 case CF_READ_ABORTED:
4814 /* The user bailed out of re-reading the capture file; the
4815 capture file has been closed - just free the capture file name
4816 string and return (without changing the last containing
4822 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4823 Instead, the file was left open, so we should restore "cf->is_tempfile"
4826 XXX - change the menu? Presumably "cf_open()" will do that;
4827 make sure it does! */
4828 cf->is_tempfile = is_tempfile;
4830 /* "cf_open()" made a copy of the file name we handed it, so
4831 we should free up our copy. */
4841 * indent-tabs-mode: nil
4844 * ex: set shiftwidth=2 tabstop=8 expandtab:
4845 * :indentSize=2:tabSize=8:noTabs=true: