4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include <wsutil/tempfile.h>
34 #include <wsutil/file_util.h>
35 #include <wsutil/filesystem.h>
36 #include <version_info.h>
38 #include <wiretap/merge.h>
40 #include <epan/exceptions.h>
41 #include <epan/epan-int.h>
42 #include <epan/epan.h>
43 #include <epan/column.h>
44 #include <epan/packet.h>
45 #include <epan/column-utils.h>
46 #include <epan/expert.h>
47 #include <epan/prefs.h>
48 #include <epan/dfilter/dfilter.h>
49 #include <epan/epan_dissect.h>
51 #include <epan/dissectors/packet-ber.h>
52 #include <epan/timestamp.h>
53 #include <epan/dfilter/dfilter-macro.h>
54 #include <epan/strutil.h>
55 #include <epan/addr_resolv.h>
56 #include <epan/color_filters.h>
61 #include "frame_tvbuff.h"
63 #include "ui/alert_box.h"
64 #include "ui/simple_dialog.h"
65 #include "ui/main_statusbar.h"
66 #include "ui/progress_dlg.h"
67 #include "ui/ui_util.h"
69 /* Needed for addrinfo */
70 #ifdef HAVE_SYS_TYPES_H
71 # include <sys/types.h>
74 #ifdef HAVE_SYS_SOCKET_H
75 #include <sys/socket.h>
78 #ifdef HAVE_NETINET_IN_H
79 # include <netinet/in.h>
86 #ifdef HAVE_WINSOCK2_H
87 # include <winsock2.h>
91 # include <ws2tcpip.h>
95 gboolean auto_scroll_live; /* GTK+ only? */
98 static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
99 column_info *cinfo, gint64 offset);
101 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
108 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
110 static void match_subtree_text(proto_node *node, gpointer data);
111 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
113 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
115 static match_result match_narrow(capture_file *cf, frame_data *fdata,
117 static match_result match_wide(capture_file *cf, frame_data *fdata,
119 static match_result match_binary(capture_file *cf, frame_data *fdata,
121 static match_result match_regex(capture_file *cf, frame_data *fdata,
123 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
125 static match_result match_marked(capture_file *cf, frame_data *fdata,
127 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
129 static gboolean find_packet(capture_file *cf,
130 match_result (*match_function)(capture_file *, frame_data *, void *),
131 void *criterion, search_direction dir);
133 static const char *cf_get_user_packet_comment(capture_file *cf, const frame_data *fd);
135 static void cf_rename_failure_alert_box(const char *filename, int err);
136 static void ref_time_packets(capture_file *cf);
138 /* Seconds spent processing packets between pushing UI updates. */
139 #define PROGBAR_UPDATE_INTERVAL 0.150
141 /* Show the progress bar after this many seconds. */
142 #define PROGBAR_SHOW_DELAY 0.5
145 * We could probably use g_signal_...() instead of the callbacks below but that
146 * would require linking our CLI programs to libgobject and creating an object
147 * instance for the signals.
150 cf_callback_t cb_fct;
152 } cf_callback_data_t;
154 static GList *cf_callbacks = NULL;
157 cf_callback_invoke(int event, gpointer data)
159 cf_callback_data_t *cb;
160 GList *cb_item = cf_callbacks;
162 /* there should be at least one interested */
163 g_assert(cb_item != NULL);
165 while (cb_item != NULL) {
166 cb = (cf_callback_data_t *)cb_item->data;
167 cb->cb_fct(event, data, cb->user_data);
168 cb_item = g_list_next(cb_item);
174 cf_callback_add(cf_callback_t func, gpointer user_data)
176 cf_callback_data_t *cb;
178 cb = g_new(cf_callback_data_t,1);
180 cb->user_data = user_data;
182 cf_callbacks = g_list_prepend(cf_callbacks, cb);
186 cf_callback_remove(cf_callback_t func, gpointer user_data)
188 cf_callback_data_t *cb;
189 GList *cb_item = cf_callbacks;
191 while (cb_item != NULL) {
192 cb = (cf_callback_data_t *)cb_item->data;
193 if (cb->cb_fct == func && cb->user_data == user_data) {
194 cf_callbacks = g_list_remove(cf_callbacks, cb);
198 cb_item = g_list_next(cb_item);
201 g_assert_not_reached();
205 cf_timestamp_auto_precision(capture_file *cf)
209 /* don't try to get the file's precision if none is opened */
210 if (cf->state == FILE_CLOSED) {
214 /* Set the column widths of those columns that show the time in
215 "command-line-specified" format. */
216 for (i = 0; i < cf->cinfo.num_cols; i++) {
217 if (col_has_time_fmt(&cf->cinfo, i)) {
218 packet_list_resize_column(i);
224 cf_get_computed_elapsed(capture_file *cf)
226 return cf->computed_elapsed;
230 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
233 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
238 g_get_current_time(&time_now);
240 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
241 time_now.tv_usec - start_time->tv_usec;
243 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
246 static const nstime_t *
247 ws_get_frame_ts(void *data, guint32 frame_num)
249 capture_file *cf = (capture_file *) data;
251 if (cf->prev_dis && cf->prev_dis->num == frame_num)
252 return &cf->prev_dis->abs_ts;
254 if (cf->prev_cap && cf->prev_cap->num == frame_num)
255 return &cf->prev_cap->abs_ts;
258 frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
260 return (fd) ? &fd->abs_ts : NULL;
267 ws_get_user_comment(void *data, const frame_data *fd)
269 capture_file *cf = (capture_file *) data;
271 return cf_get_user_packet_comment(cf, fd);
275 ws_epan_new(capture_file *cf)
277 epan_t *epan = epan_new();
280 epan->get_frame_ts = ws_get_frame_ts;
281 epan->get_interface_name = cap_file_get_interface_name;
282 epan->get_interface_description = cap_file_get_interface_description;
283 epan->get_user_comment = ws_get_user_comment;
289 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
294 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
298 /* The open succeeded. Close whatever capture file we had open,
299 and fill in the information for this file. */
302 /* Initialize the packet header. */
303 wtap_phdr_init(&cf->phdr);
305 /* XXX - we really want to initialize this after we've read all
306 the packets, so we know how much we'll ultimately need. */
307 ws_buffer_init(&cf->buf, 1500);
309 /* Create new epan session for dissection.
310 * (The old one was freed in cf_close().)
312 cf->epan = ws_epan_new(cf);
314 /* We're about to start reading the file. */
315 cf->state = FILE_READ_IN_PROGRESS;
320 /* Set the file name because we need it to set the follow stream filter.
321 XXX - is that still true? We need it for other reasons, though,
323 cf->filename = g_strdup(fname);
325 /* Indicate whether it's a permanent or temporary file. */
326 cf->is_tempfile = is_tempfile;
328 /* No user changes yet. */
329 cf->unsaved_changes = FALSE;
331 cf->computed_elapsed = 0;
333 cf->cd_t = wtap_file_type_subtype(cf->wth);
334 cf->open_type = type;
335 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
337 cf->packet_comment_count = 0;
338 cf->displayed_count = 0;
339 cf->marked_count = 0;
340 cf->ignored_count = 0;
341 cf->ref_time_count = 0;
342 cf->drops_known = FALSE;
344 cf->snap = wtap_snapshot_length(cf->wth);
346 /* Allocate a frame_data_sequence for the frames in this file */
347 cf->frames = new_frame_data_sequence();
349 nstime_set_zero(&cf->elapsed_time);
355 packet_list_queue_draw();
356 cf_callback_invoke(cf_cb_file_opened, cf);
358 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
359 /* tell the BER dissector the file name */
360 ber_set_filename(cf->filename);
363 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
364 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
369 cfile_open_failure_alert_box(fname, *err, err_info);
374 * Add an encapsulation type to cf->linktypes.
377 cf_add_encapsulation_type(capture_file *cf, int encap)
381 for (i = 0; i < cf->linktypes->len; i++) {
382 if (g_array_index(cf->linktypes, gint, i) == encap)
383 return; /* it's already there */
385 /* It's not already there - add it. */
386 g_array_append_val(cf->linktypes, encap);
389 /* Reset everything to a pristine state */
391 cf_close(capture_file *cf)
393 cf->stop_flag = FALSE;
394 if (cf->state == FILE_CLOSED)
395 return; /* Nothing to do */
397 /* Die if we're in the middle of reading a file. */
398 g_assert(cf->state != FILE_READ_IN_PROGRESS);
400 cf_callback_invoke(cf_cb_file_closing, cf);
402 /* close things, if not already closed before */
403 color_filters_cleanup();
409 /* We have no file open... */
410 if (cf->filename != NULL) {
411 /* If it's a temporary file, remove it. */
413 ws_unlink(cf->filename);
414 g_free(cf->filename);
417 /* ...which means we have no changes to that file to save. */
418 cf->unsaved_changes = FALSE;
420 /* no open_routine type */
421 cf->open_type = WTAP_TYPE_AUTO;
423 /* Clean up the packet header. */
424 wtap_phdr_cleanup(&cf->phdr);
426 /* Free up the packet buffer. */
427 ws_buffer_free(&cf->buf);
429 dfilter_free(cf->rfcode);
431 if (cf->frames != NULL) {
432 free_frame_data_sequence(cf->frames);
435 #ifdef WANT_PACKET_EDITOR
436 if (cf->edited_frames) {
437 g_tree_destroy(cf->edited_frames);
438 cf->edited_frames = NULL;
441 if (cf->frames_user_comments) {
442 g_tree_destroy(cf->frames_user_comments);
443 cf->frames_user_comments = NULL;
445 cf_unselect_packet(cf); /* nothing to select */
446 cf->first_displayed = 0;
447 cf->last_displayed = 0;
449 /* No frames, no frame selected, no field in that frame selected. */
451 cf->current_frame = 0;
453 cf->finfo_selected = NULL;
455 /* No frame link-layer types, either. */
456 if (cf->linktypes != NULL) {
457 g_array_free(cf->linktypes, TRUE);
458 cf->linktypes = NULL;
461 /* Clear the packet list. */
462 packet_list_freeze();
467 nstime_set_zero(&cf->elapsed_time);
469 reset_tap_listeners();
474 /* We have no file open. */
475 cf->state = FILE_CLOSED;
477 cf_callback_invoke(cf_cb_file_closed, cf);
481 * TRUE if the progress dialog doesn't exist and it looks like we'll
482 * take > 2s to load, FALSE otherwise.
484 static inline gboolean
485 progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
489 if (progdlg) return FALSE;
490 elapsed = g_timer_elapsed(prog_timer, NULL);
491 if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
492 || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
499 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
503 progbar_val = (gfloat) file_pos / (gfloat) size;
504 if (progbar_val > 1.0) {
506 /* The file probably grew while we were reading it.
507 * Update file size, and try again.
509 size = wtap_file_size(cf->wth, NULL);
512 progbar_val = (gfloat) file_pos / (gfloat) size;
514 /* If it's still > 1, either "wtap_file_size()" failed (in which
515 * case there's not much we can do about it), or the file
516 * *shrank* (in which case there's not much we can do about
517 * it); just clip the progress value at 1.0.
519 if (progbar_val > 1.0f)
523 g_snprintf(status_str, status_size,
524 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
525 file_pos / 1024, size / 1024);
531 cf_read(capture_file *cf, gboolean reloading)
534 gchar *err_info = NULL;
536 progdlg_t *volatile progbar = NULL;
537 GTimer *prog_timer = g_timer_new();
541 volatile gboolean create_proto_tree;
544 volatile gboolean is_read_aborted = FALSE;
546 /* Compile the current display filter.
547 * We assume this will not fail since cf->dfilter is only set in
548 * cf_filter IFF the filter was valid.
550 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
551 g_assert(!cf->dfilter || (compiled && dfcode));
553 /* Get the union of the flags for all tap listeners. */
554 tap_flags = union_of_tap_listener_flags();
557 * Determine whether we need to create a protocol tree.
560 * we're going to apply a display filter;
562 * one of the tap listeners is going to apply a filter;
564 * one of the tap listeners requires a protocol tree;
566 * a postdissector wants field values or protocols on
570 (dfcode != NULL || have_filtering_tap_listeners() ||
571 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
573 reset_tap_listeners();
575 name_ptr = g_filename_display_basename(cf->filename);
578 cf_callback_invoke(cf_cb_file_reload_started, cf);
580 cf_callback_invoke(cf_cb_file_read_started, cf);
582 /* Record whether the file is compressed.
583 XXX - do we know this at open time? */
584 cf->iscompressed = wtap_iscompressed(cf->wth);
586 /* The packet list window will be empty until the file is completly loaded */
587 packet_list_freeze();
589 cf->stop_flag = FALSE;
590 g_get_current_time(&start_time);
592 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
602 gchar status_str[100];
606 /* If any tap listeners require the columns, construct them. */
607 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
609 /* Find the size of the file. */
610 size = wtap_file_size(cf->wth, NULL);
612 g_timer_start(prog_timer);
614 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
617 file_pos = wtap_read_so_far(cf->wth);
619 /* Create the progress bar if necessary. */
620 if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
621 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
623 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
624 TRUE, &cf->stop_flag, &start_time, progbar_val);
626 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
627 TRUE, &cf->stop_flag, &start_time, progbar_val);
631 * Update the progress bar, but do it only after
632 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
633 * and packets_bar_update will likely trigger UI paint events, which
634 * might take a while depending on the platform and display. Reset
635 * our timer *after* painting.
637 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
638 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
639 /* update the packet bar content on the first run or frequently on very large files */
640 update_progress_dlg(progbar, progbar_val, status_str);
641 compute_elapsed(cf, &start_time);
642 packets_bar_update();
643 g_timer_start(prog_timer);
647 if (cf->state == FILE_READ_ABORTED) {
648 /* Well, the user decided to exit Wireshark. Break out of the
649 loop, and let the code below (which is called even if there
650 aren't any packets left to read) exit. */
651 is_read_aborted = TRUE;
655 /* Well, the user decided to abort the read. He/She will be warned and
656 it might be enough for him/her to work with the already loaded
658 This is especially true for very large capture files, where you don't
659 want to wait loading the whole file (which may last minutes or even
660 hours even on fast machines) just to see that it was the wrong file. */
663 read_packet(cf, dfcode, &edt, cinfo, data_offset);
666 CATCH(OutOfMemoryError) {
667 simple_message_box(ESD_TYPE_ERROR, NULL,
668 "More information and workarounds can be found at\n"
669 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
670 "Sorry, but Wireshark has run out of memory and has to terminate now.");
672 /* Could we close the current capture and free up memory from that? */
674 /* we have to terminate, as we cannot recover from the memory error */
680 /* Free the display name */
683 /* Cleanup and release all dfilter resources */
684 if (dfcode != NULL) {
685 dfilter_free(dfcode);
688 epan_dissect_cleanup(&edt);
690 /* We're done reading the file; destroy the progress bar if it was created. */
692 destroy_progress_dlg(progbar);
693 g_timer_destroy(prog_timer);
695 /* We're done reading sequentially through the file. */
696 cf->state = FILE_READ_DONE;
698 /* Close the sequential I/O side, to free up memory it requires. */
699 wtap_sequential_close(cf->wth);
701 /* Allow the protocol dissectors to free up memory that they
702 * don't need after the sequential run-through of the packets. */
703 postseq_cleanup_all_protocols();
705 /* compute the time it took to load the file */
706 compute_elapsed(cf, &start_time);
708 /* Set the file encapsulation type now; we don't know what it is until
709 we've looked at all the packets, as we don't know until then whether
710 there's more than one type (and thus whether it's
711 WTAP_ENCAP_PER_PACKET). */
712 cf->lnk_t = wtap_file_encap(cf->wth);
714 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
719 cf_callback_invoke(cf_cb_file_reload_finished, cf);
721 cf_callback_invoke(cf_cb_file_read_finished, cf);
723 /* If we have any displayed packets to select, select the first of those
724 packets by making the first row the selected row. */
725 if (cf->first_displayed != 0) {
726 packet_list_select_first_row();
729 if (is_read_aborted) {
731 * Well, the user decided to exit Wireshark while reading this *offline*
732 * capture file (Live captures are handled by something like
733 * cf_continue_tail). Clean up accordingly.
736 return CF_READ_ABORTED;
740 simple_message_box(ESD_TYPE_WARN, NULL,
741 "The remaining packets in the file were discarded.\n"
743 "As a lot of packets from the original file will be missing,\n"
744 "remember to be careful when saving the current content to a file.\n",
745 "File loading was cancelled.");
746 return CF_READ_ERROR;
750 /* Put up a message box noting that the read failed somewhere along
751 the line. Don't throw out the stuff we managed to read, though,
753 cfile_read_failure_alert_box(NULL, err, err_info);
754 return CF_READ_ERROR;
761 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
764 volatile int newly_displayed_packets = 0;
767 gboolean create_proto_tree;
771 /* Compile the current display filter.
772 * We assume this will not fail since cf->dfilter is only set in
773 * cf_filter IFF the filter was valid.
775 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
776 g_assert(!cf->dfilter || (compiled && dfcode));
778 /* Get the union of the flags for all tap listeners. */
779 tap_flags = union_of_tap_listener_flags();
782 * Determine whether we need to create a protocol tree.
785 * we're going to apply a display filter;
787 * one of the tap listeners is going to apply a filter;
789 * one of the tap listeners requires a protocol tree;
791 * a postdissector wants field values or protocols on
795 (dfcode != NULL || have_filtering_tap_listeners() ||
796 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
800 packet_list_check_end();
801 /* Don't freeze/thaw the list when doing live capture */
802 /*packet_list_freeze();*/
804 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
806 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
809 gint64 data_offset = 0;
812 /* If any tap listeners require the columns, construct them. */
813 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
815 while (to_read != 0) {
816 wtap_cleareof(cf->wth);
817 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
820 if (cf->state == FILE_READ_ABORTED) {
821 /* Well, the user decided to exit Wireshark. Break out of the
822 loop, and let the code below (which is called even if there
823 aren't any packets left to read) exit. */
826 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
827 newly_displayed_packets++;
832 CATCH(OutOfMemoryError) {
833 simple_message_box(ESD_TYPE_ERROR, NULL,
834 "More information and workarounds can be found at\n"
835 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
836 "Sorry, but Wireshark has run out of memory and has to terminate now.");
838 /* Could we close the current capture and free up memory from that? */
839 return CF_READ_ABORTED;
841 /* we have to terminate, as we cannot recover from the memory error */
847 /* Update the file encapsulation; it might have changed based on the
848 packets we've read. */
849 cf->lnk_t = wtap_file_encap(cf->wth);
851 /* Cleanup and release all dfilter resources */
852 if (dfcode != NULL) {
853 dfilter_free(dfcode);
856 epan_dissect_cleanup(&edt);
858 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
859 cf->count, cf->state, *err);*/
861 /* Don't freeze/thaw the list when doing live capture */
862 /*packet_list_thaw();*/
863 /* With the new packet list the first packet
864 * isn't automatically selected.
866 if (!cf->current_frame)
867 packet_list_select_first_row();
869 /* moving to the end of the packet list - if the user requested so and
870 we have some new packets. */
871 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
872 packet_list_moveto_end();
874 if (cf->state == FILE_READ_ABORTED) {
875 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
876 so that our caller can kill off the capture child process;
877 this will cause an EOF on the pipe from the child, so
878 "cf_finish_tail()" will be called, and it will clean up
880 return CF_READ_ABORTED;
881 } else if (*err != 0) {
882 /* We got an error reading the capture file.
883 XXX - pop up a dialog box instead? */
884 if (err_info != NULL) {
885 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
886 wtap_strerror(*err), cf->filename, err_info);
889 g_warning("Error \"%s\" while reading \"%s\"",
890 wtap_strerror(*err), cf->filename);
892 return CF_READ_ERROR;
898 cf_fake_continue_tail(capture_file *cf) {
899 cf->state = FILE_READ_DONE;
903 cf_finish_tail(capture_file *cf, int *err)
910 gboolean create_proto_tree;
914 /* Compile the current display filter.
915 * We assume this will not fail since cf->dfilter is only set in
916 * cf_filter IFF the filter was valid.
918 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
919 g_assert(!cf->dfilter || (compiled && dfcode));
921 /* Get the union of the flags for all tap listeners. */
922 tap_flags = union_of_tap_listener_flags();
924 /* If any tap listeners require the columns, construct them. */
925 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
928 * Determine whether we need to create a protocol tree.
931 * we're going to apply a display filter;
933 * one of the tap listeners is going to apply a filter;
935 * one of the tap listeners requires a protocol tree;
937 * a postdissector wants field values or protocols on
941 (dfcode != NULL || have_filtering_tap_listeners() ||
942 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
944 if (cf->wth == NULL) {
946 return CF_READ_ERROR;
949 packet_list_check_end();
950 /* Don't freeze/thaw the list when doing live capture */
951 /*packet_list_freeze();*/
953 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
955 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
956 if (cf->state == FILE_READ_ABORTED) {
957 /* Well, the user decided to abort the read. Break out of the
958 loop, and let the code below (which is called even if there
959 aren't any packets left to read) exit. */
962 read_packet(cf, dfcode, &edt, cinfo, data_offset);
965 /* Cleanup and release all dfilter resources */
966 if (dfcode != NULL) {
967 dfilter_free(dfcode);
970 epan_dissect_cleanup(&edt);
972 /* Don't freeze/thaw the list when doing live capture */
973 /*packet_list_thaw();*/
975 if (cf->state == FILE_READ_ABORTED) {
976 /* Well, the user decided to abort the read. We're only called
977 when the child capture process closes the pipe to us (meaning
978 it's probably exited), so we can just close the capture
979 file; we return CF_READ_ABORTED so our caller can do whatever
980 is appropriate when that happens. */
982 return CF_READ_ABORTED;
985 if (auto_scroll_live && cf->count != 0)
986 packet_list_moveto_end();
988 /* We're done reading sequentially through the file. */
989 cf->state = FILE_READ_DONE;
991 /* We're done reading sequentially through the file; close the
992 sequential I/O side, to free up memory it requires. */
993 wtap_sequential_close(cf->wth);
995 /* Allow the protocol dissectors to free up memory that they
996 * don't need after the sequential run-through of the packets. */
997 postseq_cleanup_all_protocols();
999 /* Update the file encapsulation; it might have changed based on the
1000 packets we've read. */
1001 cf->lnk_t = wtap_file_encap(cf->wth);
1003 /* Update the details in the file-set dialog, as the capture file
1004 * has likely grown since we first stat-ed it */
1005 fileset_update_file(cf->filename);
1008 /* We got an error reading the capture file.
1009 XXX - pop up a dialog box? */
1010 if (err_info != NULL) {
1011 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
1012 wtap_strerror(*err), cf->filename, err_info);
1015 g_warning("Error \"%s\" while reading \"%s\"",
1016 wtap_strerror(*err), cf->filename);
1018 return CF_READ_ERROR;
1023 #endif /* HAVE_LIBPCAP */
1026 cf_get_display_name(capture_file *cf)
1030 /* Return a name to use in displays */
1031 if (!cf->is_tempfile) {
1032 /* Get the last component of the file name, and use that. */
1034 displayname = g_filename_display_basename(cf->filename);
1036 displayname=g_strdup("(No file)");
1039 /* The file we read is a temporary file from a live capture or
1040 a merge operation; we don't mention its name, but, if it's
1041 from a capture, give the source of the capture. */
1043 displayname = g_strdup(cf->source);
1045 displayname = g_strdup("(Untitled)");
1051 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1057 cf->source = g_strdup(source);
1059 cf->source = g_strdup("");
1063 const gchar *cf_get_tempfile_source(capture_file *cf) {
1071 /* XXX - use a macro instead? */
1073 cf_get_packet_count(capture_file *cf)
1078 /* XXX - use a macro instead? */
1080 cf_is_tempfile(capture_file *cf)
1082 return cf->is_tempfile;
1085 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1087 cf->is_tempfile = is_tempfile;
1091 /* XXX - use a macro instead? */
1092 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1094 cf->drops_known = drops_known;
1097 /* XXX - use a macro instead? */
1098 void cf_set_drops(capture_file *cf, guint32 drops)
1103 /* XXX - use a macro instead? */
1104 gboolean cf_get_drops_known(capture_file *cf)
1106 return cf->drops_known;
1109 /* XXX - use a macro instead? */
1110 guint32 cf_get_drops(capture_file *cf)
1115 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1117 cf->rfcode = rfcode;
1121 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1122 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1123 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1127 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1128 &cf->ref, cf->prev_dis);
1129 cf->prev_cap = fdata;
1131 if (dfcode != NULL) {
1132 epan_dissect_prime_with_dfilter(edt, dfcode);
1135 /* Prepare coloring rules, this ensures that display filter rules containing
1136 * frame.color_rule references are still processed.
1137 * TODO: actually detect that situation or maybe apply other optimizations? */
1138 if (edt->tree && color_filters_used()) {
1139 color_filters_prime_edt(edt);
1140 fdata->flags.need_colorize = 1;
1144 if (!fdata->flags.visited) {
1145 /* This is the first pass, so prime the epan_dissect_t with the
1146 hfids postdissectors want on the first pass. */
1147 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1150 /* Dissect the frame. */
1151 epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1153 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1154 if (dfcode != NULL) {
1155 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1157 if (fdata->flags.passed_dfilter) {
1158 /* This frame passed the display filter but it may depend on other
1159 * (potentially not displayed) frames. Find those frames and mark them
1162 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
1165 fdata->flags.passed_dfilter = 1;
1167 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1168 cf->displayed_count++;
1170 if (add_to_packet_list) {
1171 /* We fill the needed columns from new_packet_list */
1172 row = packet_list_append(cinfo, fdata);
1175 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1177 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1178 cf->prev_dis = fdata;
1180 /* If we haven't yet seen the first frame, this is it. */
1181 if (cf->first_displayed == 0)
1182 cf->first_displayed = fdata->num;
1184 /* This is the last frame we've seen so far. */
1185 cf->last_displayed = fdata->num;
1188 epan_dissect_reset(edt);
1192 /* read in a new packet */
1193 /* returns the row of the new packet in the packet list or -1 if not displayed */
1195 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1196 column_info *cinfo, gint64 offset)
1198 struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1199 const guint8 *buf = wtap_buf_ptr(cf->wth);
1203 gboolean passed = TRUE;
1206 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1207 it's not already there.
1208 XXX - yes, this is O(N), so if every packet had a different
1209 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1210 there are probably going to be a small number of encapsulation types
1212 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1214 /* The frame number of this packet is one more than the count of
1215 frames in the file so far. */
1216 framenum = cf->count + 1;
1218 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1221 epan_dissect_t rf_edt;
1223 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1224 epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
1225 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1226 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1227 epan_dissect_cleanup(&rf_edt);
1231 /* This does a shallow copy of fdlocal, which is good enough. */
1232 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1235 if (phdr->opt_comment != NULL)
1236 cf->packet_comment_count++;
1237 cf->f_datalen = offset + fdlocal.cap_len;
1239 if (!cf->redissecting) {
1240 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1241 cinfo, phdr, buf, TRUE);
1249 typedef struct _callback_data_t {
1252 GTimeVal start_time;
1260 merge_callback(merge_event event, int num _U_,
1261 const merge_in_file_t in_files[], const guint in_file_count,
1265 callback_data_t *cb_data = (callback_data_t*) data;
1267 g_assert(cb_data != NULL);
1271 case MERGE_EVENT_INPUT_FILES_OPENED:
1275 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1279 case MERGE_EVENT_READY_TO_MERGE:
1280 /* Get the sum of the sizes of all the files. */
1281 for (i = 0; i < in_file_count; i++)
1282 cb_data->f_len += in_files[i].size;
1284 cb_data->prog_timer = g_timer_new();
1285 g_timer_start(cb_data->prog_timer);
1287 g_get_current_time(&cb_data->start_time);
1290 case MERGE_EVENT_PACKET_WAS_READ:
1292 gint64 data_offset = 0;
1294 /* Get the sum of the data offsets in all of the files. */
1296 for (i = 0; i < in_file_count; i++)
1297 data_offset += in_files[i].data_offset;
1299 /* Create the progress bar if necessary.
1300 We check on every iteration of the loop, so that it takes no
1301 longer than the standard time to create it (otherwise, for a
1302 large file, we might take considerably longer than that standard
1303 time in order to get to the next progress bar step). */
1304 if (cb_data->progbar == NULL) {
1305 cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1306 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1310 * Update the progress bar, but do it only after
1311 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1312 * and packets_bar_update will likely trigger UI paint events, which
1313 * might take a while depending on the platform and display. Reset
1314 * our timer *after* painting.
1316 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1318 gint64 file_pos = 0;
1319 /* Get the sum of the seek positions in all of the files. */
1320 for (i = 0; i < in_file_count; i++)
1321 file_pos += wtap_read_so_far(in_files[i].wth);
1323 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1324 if (progbar_val > 1.0f) {
1325 /* Some file probably grew while we were reading it.
1326 That "shouldn't happen", so we'll just clip the progress
1331 if (cb_data->progbar != NULL) {
1332 gchar status_str[100];
1333 g_snprintf(status_str, sizeof(status_str),
1334 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1335 file_pos / 1024, cb_data->f_len / 1024);
1336 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1338 g_timer_start(cb_data->prog_timer);
1343 case MERGE_EVENT_DONE:
1344 /* We're done merging the files; destroy the progress bar if it was created. */
1345 if (cb_data->progbar != NULL)
1346 destroy_progress_dlg(cb_data->progbar);
1347 g_timer_destroy(cb_data->prog_timer);
1351 return cb_data->stop_flag;
1357 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1358 int in_file_count, char *const *in_filenames,
1359 int file_type, gboolean do_append)
1362 gchar *err_info = NULL;
1364 guint32 err_framenum;
1365 merge_result status;
1366 merge_progress_callback_t cb;
1367 callback_data_t *cb_data = g_new0(callback_data_t, 1);
1369 /* prepare our callback routine */
1370 cb_data->pd_window = pd_window;
1371 cb.callback_func = merge_callback;
1374 cf_callback_invoke(cf_cb_file_merge_started, NULL);
1376 /* merge the files */
1377 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1378 (const char *const *) in_filenames,
1379 in_file_count, do_append,
1380 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1381 "Wireshark", &cb, &err, &err_info,
1382 &err_fileno, &err_framenum);
1390 case MERGE_USER_ABORTED:
1391 /* this isn't really an error, though we will return CF_ERROR later */
1394 case MERGE_ERR_CANT_OPEN_INFILE:
1395 cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
1398 case MERGE_ERR_CANT_OPEN_OUTFILE:
1399 cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
1402 case MERGE_ERR_CANT_READ_INFILE:
1403 cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
1406 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1407 simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
1408 err_framenum, in_filenames[err_fileno]);
1411 case MERGE_ERR_CANT_WRITE_OUTFILE:
1412 cfile_write_failure_alert_box(in_filenames[err_fileno],
1413 *out_filenamep, err, err_info,
1414 err_framenum, file_type);
1417 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1418 cfile_close_failure_alert_box(*out_filenamep, err);
1422 simple_error_message_box("Unknown merge_files error %d", status);
1426 cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1428 if (status != MERGE_OK) {
1429 /* Callers aren't expected to treat an error or an explicit abort
1430 differently - we put up error dialogs ourselves, so they don't
1438 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1440 const char *filter_new = dftext ? dftext : "";
1441 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1444 GTimeVal start_time;
1446 /* if new filter equals old one, do nothing unless told to do so */
1447 if (!force && strcmp(filter_new, filter_old) == 0) {
1453 if (dftext == NULL) {
1454 /* The new filter is an empty filter (i.e., display all packets).
1455 * so leave dfcode==NULL
1459 * We have a filter; make a copy of it (as we'll be saving it),
1460 * and try to compile it.
1462 dftext = g_strdup(dftext);
1463 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1464 /* The attempt failed; report an error. */
1465 simple_message_box(ESD_TYPE_ERROR, NULL,
1466 "See the help for a description of the display filter syntax.",
1467 "\"%s\" isn't a valid display filter: %s",
1475 if (dfcode == NULL) {
1476 /* Yes - free the filter text, and set it to null. */
1482 /* We have a valid filter. Replace the current filter. */
1483 g_free(cf->dfilter);
1484 cf->dfilter = dftext;
1485 g_get_current_time(&start_time);
1488 /* Now rescan the packet list, applying the new filter, but not
1489 throwing away information constructed on a previous pass. */
1490 if (cf->state != FILE_CLOSED) {
1491 if (dftext == NULL) {
1492 rescan_packets(cf, "Resetting", "Filter", FALSE);
1494 rescan_packets(cf, "Filtering", dftext, FALSE);
1498 /* Cleanup and release all dfilter resources */
1499 dfilter_free(dfcode);
1505 cf_reftime_packets(capture_file *cf)
1507 ref_time_packets(cf);
1511 cf_redissect_packets(capture_file *cf)
1513 if (cf->state != FILE_CLOSED) {
1514 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1519 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1520 struct wtap_pkthdr *phdr, Buffer *buf)
1525 #ifdef WANT_PACKET_EDITOR
1526 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1527 if (G_UNLIKELY(fdata->file_off == -1)) {
1528 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1531 simple_error_message_box("fdata->file_off == -1, but can't find modified frame.");
1535 *phdr = frame->phdr;
1536 ws_buffer_assure_space(buf, frame->phdr.caplen);
1537 memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
1542 if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1543 cfile_read_failure_alert_box(cf->filename, err, err_info);
1550 cf_read_record(capture_file *cf, frame_data *fdata)
1552 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1555 /* Rescan the list of packets, reconstructing the CList.
1557 "action" describes why we're doing this; it's used in the progress
1560 "action_item" describes what we're doing; it's used in the progress
1563 "redissect" is TRUE if we need to make the dissectors reconstruct
1564 any state information they have (because a preference that affects
1565 some dissector has changed, meaning some dissector might construct
1566 its state differently from the way it was constructed the last time). */
1568 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1570 /* Rescan packets new packet list */
1573 progdlg_t *progbar = NULL;
1574 GTimer *prog_timer = g_timer_new();
1576 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1577 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1578 gboolean selected_frame_seen;
1580 GTimeVal start_time;
1581 gchar status_str[100];
1585 gboolean create_proto_tree;
1587 gboolean add_to_packet_list = FALSE;
1589 guint32 frames_count;
1591 /* Compile the current display filter.
1592 * We assume this will not fail since cf->dfilter is only set in
1593 * cf_filter IFF the filter was valid.
1595 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1596 g_assert(!cf->dfilter || (compiled && dfcode));
1598 /* Get the union of the flags for all tap listeners. */
1599 tap_flags = union_of_tap_listener_flags();
1601 /* If any tap listeners require the columns, construct them. */
1602 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1605 * Determine whether we need to create a protocol tree.
1608 * we're going to apply a display filter;
1610 * one of the tap listeners is going to apply a filter;
1612 * one of the tap listeners requires a protocol tree;
1614 * we're redissecting and a postdissector wants field
1615 * values or protocols on the first pass.
1618 (dfcode != NULL || have_filtering_tap_listeners() ||
1619 (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1620 (redissect && postdissectors_want_hfids()));
1622 reset_tap_listeners();
1623 /* Which frame, if any, is the currently selected frame?
1624 XXX - should the selected frame or the focus frame be the "current"
1625 frame, that frame being the one from which "Find Frame" searches
1627 selected_frame = cf->current_frame;
1629 /* Mark frame num as not found */
1630 selected_frame_num = -1;
1632 /* Freeze the packet list while we redo it, so we don't get any
1633 screen updates while it happens. */
1634 packet_list_freeze();
1637 /* We need to re-initialize all the state information that protocols
1638 keep, because some preference that controls a dissector has changed,
1639 which might cause the state information to be constructed differently
1640 by that dissector. */
1642 /* We might receive new packets while redissecting, and we don't
1643 want to dissect those before their time. */
1644 cf->redissecting = TRUE;
1646 /* 'reset' dissection session */
1647 epan_free(cf->epan);
1648 if (cf->edt && cf->edt->pi.fd) {
1649 /* All pointers in "per frame proto data" for the currently selected
1650 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1651 Free them here to avoid unintended usage in packet_list_clear(). */
1652 frame_data_destroy(cf->edt->pi.fd);
1654 cf->epan = ws_epan_new(cf);
1655 cf->cinfo.epan = cf->epan;
1657 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1658 called via epan_new() / init_dissection() when reloading Lua plugins. */
1659 if (!create_proto_tree && have_filtering_tap_listeners()) {
1660 create_proto_tree = TRUE;
1663 /* We need to redissect the packets so we have to discard our old
1664 * packet list store. */
1665 packet_list_clear();
1666 add_to_packet_list = TRUE;
1669 /* We don't yet know which will be the first and last frames displayed. */
1670 cf->first_displayed = 0;
1671 cf->last_displayed = 0;
1673 /* We currently don't display any packets */
1674 cf->displayed_count = 0;
1676 /* Iterate through the list of frames. Call a routine for each frame
1677 to check whether it should be displayed and, if so, add it to
1678 the display list. */
1680 cf->prev_dis = NULL;
1681 cf->prev_cap = NULL;
1684 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1686 g_timer_start(prog_timer);
1687 /* Count of packets at which we've looked. */
1689 /* Progress so far. */
1692 cf->stop_flag = FALSE;
1693 g_get_current_time(&start_time);
1695 /* no previous row yet */
1696 prev_frame_num = -1;
1699 preceding_frame_num = -1;
1700 preceding_frame = NULL;
1701 following_frame_num = -1;
1702 following_frame = NULL;
1704 selected_frame_seen = FALSE;
1706 frames_count = cf->count;
1708 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1710 for (framenum = 1; framenum <= frames_count; framenum++) {
1711 fdata = frame_data_sequence_find(cf->frames, framenum);
1713 /* Create the progress bar if necessary.
1714 We check on every iteration of the loop, so that it takes no
1715 longer than the standard time to create it (otherwise, for a
1716 large file, we might take considerably longer than that standard
1717 time in order to get to the next progress bar step). */
1718 if (progbar == NULL)
1719 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1725 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1726 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1727 * likely trigger UI paint events, which might take a while depending on
1728 * the platform and display. Reset our timer *after* painting.
1730 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1731 /* let's not divide by zero. I should never be started
1732 * with count == 0, so let's assert that
1734 g_assert(cf->count > 0);
1735 progbar_val = (gfloat) count / frames_count;
1737 if (progbar != NULL) {
1738 g_snprintf(status_str, sizeof(status_str),
1739 "%4u of %u frames", count, frames_count);
1740 update_progress_dlg(progbar, progbar_val, status_str);
1743 g_timer_start(prog_timer);
1746 if (cf->stop_flag) {
1747 /* Well, the user decided to abort the filtering. Just stop.
1749 XXX - go back to the previous filter? Users probably just
1750 want not to wait for a filtering operation to finish;
1751 unless we cancel by having no filter, reverting to the
1752 previous filter will probably be even more expensive than
1753 continuing the filtering, as it involves going back to the
1754 beginning and filtering, and even with no filter we currently
1755 have to re-generate the entire clist, which is also expensive.
1757 I'm not sure what Network Monitor does, but it doesn't appear
1758 to give you an unfiltered display if you cancel. */
1765 /* Since all state for the frame was destroyed, mark the frame
1766 * as not visited, free the GSList referring to the state
1767 * data (the per-frame data itself was freed by
1768 * "init_dissection()"), and null out the GSList pointer. */
1769 frame_data_reset(fdata);
1770 frames_count = cf->count;
1773 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1774 fdata->flags.dependent_of_displayed = 0;
1776 if (!cf_read_record(cf, fdata))
1777 break; /* error reading the frame */
1779 /* If the previous frame is displayed, and we haven't yet seen the
1780 selected frame, remember that frame - it's the closest one we've
1781 yet seen before the selected frame. */
1782 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1783 preceding_frame_num = prev_frame_num;
1784 preceding_frame = prev_frame;
1787 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1789 ws_buffer_start_ptr(&cf->buf),
1790 add_to_packet_list);
1792 /* If this frame is displayed, and this is the first frame we've
1793 seen displayed after the selected frame, remember this frame -
1794 it's the closest one we've yet seen at or after the selected
1796 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1797 following_frame_num = fdata->num;
1798 following_frame = fdata;
1800 if (fdata == selected_frame) {
1801 selected_frame_seen = TRUE;
1802 if (fdata->flags.passed_dfilter)
1803 selected_frame_num = fdata->num;
1806 /* Remember this frame - it'll be the previous frame
1807 on the next pass through the loop. */
1808 prev_frame_num = fdata->num;
1812 epan_dissect_cleanup(&edt);
1814 /* We are done redissecting the packet list. */
1815 cf->redissecting = FALSE;
1818 frames_count = cf->count;
1819 /* Clear out what remains of the visited flags and per-frame data
1822 XXX - that may cause various forms of bogosity when dissecting
1823 these frames, as they won't have been seen by this sequential
1824 pass, but the only alternative I see is to keep scanning them
1825 even though the user requested that the scan stop, and that
1826 would leave the user stuck with an Wireshark grinding on
1827 until it finishes. Should we just stick them with that? */
1828 for (; framenum <= frames_count; framenum++) {
1829 fdata = frame_data_sequence_find(cf->frames, framenum);
1830 frame_data_reset(fdata);
1834 /* We're done filtering the packets; destroy the progress bar if it
1836 if (progbar != NULL)
1837 destroy_progress_dlg(progbar);
1838 g_timer_destroy(prog_timer);
1840 /* Unfreeze the packet list. */
1841 if (!add_to_packet_list)
1842 packet_list_recreate_visible_rows();
1844 /* Compute the time it took to filter the file */
1845 compute_elapsed(cf, &start_time);
1849 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1851 if (selected_frame_num == -1) {
1852 /* The selected frame didn't pass the filter. */
1853 if (selected_frame == NULL) {
1854 /* That's because there *was* no selected frame. Make the first
1855 displayed frame the current frame. */
1856 selected_frame_num = 0;
1858 /* Find the nearest displayed frame to the selected frame (whether
1859 it's before or after that frame) and make that the current frame.
1860 If the next and previous displayed frames are equidistant from the
1861 selected frame, choose the next one. */
1862 g_assert(following_frame == NULL ||
1863 following_frame->num >= selected_frame->num);
1864 g_assert(preceding_frame == NULL ||
1865 preceding_frame->num <= selected_frame->num);
1866 if (following_frame == NULL) {
1867 /* No frame after the selected frame passed the filter, so we
1868 have to select the last displayed frame before the selected
1870 selected_frame_num = preceding_frame_num;
1871 selected_frame = preceding_frame;
1872 } else if (preceding_frame == NULL) {
1873 /* No frame before the selected frame passed the filter, so we
1874 have to select the first displayed frame after the selected
1876 selected_frame_num = following_frame_num;
1877 selected_frame = following_frame;
1879 /* Frames before and after the selected frame passed the filter, so
1880 we'll select the previous frame */
1881 selected_frame_num = preceding_frame_num;
1882 selected_frame = preceding_frame;
1887 if (selected_frame_num == -1) {
1888 /* There are no frames displayed at all. */
1889 cf_unselect_packet(cf);
1891 /* Either the frame that was selected passed the filter, or we've
1892 found the nearest displayed frame to that frame. Select it, make
1893 it the focus row, and make it visible. */
1894 /* Set to invalid to force update of packet list and packet details */
1895 cf->current_row = -1;
1896 if (selected_frame_num == 0) {
1897 packet_list_select_first_row();
1899 if (!packet_list_select_row_from_data(selected_frame)) {
1900 /* We didn't find a row corresponding to this frame.
1901 This means that the frame isn't being displayed currently,
1902 so we can't select it. */
1903 simple_message_box(ESD_TYPE_INFO, NULL,
1904 "The capture file is probably not fully dissected.",
1905 "End of capture exceeded.");
1910 /* Cleanup and release all dfilter resources */
1911 dfilter_free(dfcode);
1916 * Scan through all frame data and recalculate the ref time
1917 * without rereading the file.
1918 * XXX - do we need a progres bar or is this fast enough?
1921 ref_time_packets(capture_file *cf)
1928 cf->prev_dis = NULL;
1931 for (framenum = 1; framenum <= cf->count; framenum++) {
1932 fdata = frame_data_sequence_find(cf->frames, framenum);
1934 /* just add some value here until we know if it is being displayed or not */
1935 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1941 /* If we don't have the time stamp of the first packet in the
1942 capture, it's because this is the first packet. Save the time
1943 stamp of this packet as the time stamp of the first packet. */
1944 if (cf->ref == NULL)
1946 /* if this frames is marked as a reference time frame, reset
1947 firstsec and firstusec to this frame */
1948 if (fdata->flags.ref_time)
1951 /* If we don't have the time stamp of the previous displayed packet,
1952 it's because this is the first displayed packet. Save the time
1953 stamp of this packet as the time stamp of the previous displayed
1955 if (cf->prev_dis == NULL) {
1956 cf->prev_dis = fdata;
1959 /* Get the time elapsed between the first packet and this packet. */
1960 fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
1961 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
1963 /* If it's greater than the current elapsed time, set the elapsed time
1964 to it (we check for "greater than" so as not to be confused by
1965 time moving backwards). */
1966 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1967 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1968 cf->elapsed_time = rel_ts;
1971 /* If this frame is displayed, get the time elapsed between the
1972 previous displayed packet and this packet. */
1973 if ( fdata->flags.passed_dfilter ) {
1974 fdata->prev_dis_num = cf->prev_dis->num;
1975 cf->prev_dis = fdata;
1981 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1982 /* This frame either passed the display filter list or is marked as
1983 a time reference frame. All time reference frames are displayed
1984 even if they don't pass the display filter */
1985 if (fdata->flags.ref_time) {
1986 /* if this was a TIME REF frame we should reset the cum_bytes field */
1987 cf->cum_bytes = fdata->pkt_len;
1988 fdata->cum_bytes = cf->cum_bytes;
1990 /* increase cum_bytes with this packets length */
1991 cf->cum_bytes += fdata->pkt_len;
2004 process_specified_records(capture_file *cf, packet_range_t *range,
2005 const char *string1, const char *string2, gboolean terminate_is_stop,
2006 gboolean (*callback)(capture_file *, frame_data *,
2007 struct wtap_pkthdr *, const guint8 *, void *),
2008 void *callback_args,
2009 gboolean show_progress_bar)
2014 psp_return_t ret = PSP_FINISHED;
2016 progdlg_t *progbar = NULL;
2017 GTimer *prog_timer = g_timer_new();
2020 GTimeVal progbar_start_time;
2021 gchar progbar_status_str[100];
2022 range_process_e process_this;
2023 struct wtap_pkthdr phdr;
2025 wtap_phdr_init(&phdr);
2026 ws_buffer_init(&buf, 1500);
2028 g_timer_start(prog_timer);
2029 /* Count of packets at which we've looked. */
2031 /* Progress so far. */
2034 cf->stop_flag = FALSE;
2035 g_get_current_time(&progbar_start_time);
2038 packet_range_process_init(range);
2040 /* Iterate through all the packets, printing the packets that
2041 were selected by the current display filter. */
2042 for (framenum = 1; framenum <= cf->count; framenum++) {
2043 fdata = frame_data_sequence_find(cf->frames, framenum);
2045 /* Create the progress bar if necessary.
2046 We check on every iteration of the loop, so that it takes no
2047 longer than the standard time to create it (otherwise, for a
2048 large file, we might take considerably longer than that standard
2049 time in order to get to the next progress bar step). */
2050 if (show_progress_bar && progbar == NULL)
2051 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2054 &progbar_start_time,
2058 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
2059 * has elapsed. Calling update_progress_dlg and packets_bar_update will
2060 * likely trigger UI paint events, which might take a while depending on
2061 * the platform and display. Reset our timer *after* painting.
2063 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2064 /* let's not divide by zero. I should never be started
2065 * with count == 0, so let's assert that
2067 g_assert(cf->count > 0);
2068 progbar_val = (gfloat) progbar_count / cf->count;
2070 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2071 "%4u of %u packets", progbar_count, cf->count);
2072 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2074 g_timer_start(prog_timer);
2077 if (cf->stop_flag) {
2078 /* Well, the user decided to abort the operation. Just stop,
2079 and arrange to return PSP_STOPPED to our caller, so they know
2080 it was stopped explicitly. */
2087 if (range != NULL) {
2088 /* do we have to process this packet? */
2089 process_this = packet_range_process_packet(range, fdata);
2090 if (process_this == range_process_next) {
2091 /* this packet uninteresting, continue with next one */
2093 } else if (process_this == range_processing_finished) {
2094 /* all interesting packets processed, stop the loop */
2099 /* Get the packet */
2100 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2101 /* Attempt to get the packet failed. */
2105 /* Process the packet */
2106 if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2107 /* Callback failed. We assume it reported the error appropriately. */
2113 /* We're done printing the packets; destroy the progress bar if
2115 if (progbar != NULL)
2116 destroy_progress_dlg(progbar);
2117 g_timer_destroy(prog_timer);
2119 wtap_phdr_cleanup(&phdr);
2120 ws_buffer_free(&buf);
2128 } retap_callback_args_t;
2131 retap_packet(capture_file *cf, frame_data *fdata,
2132 struct wtap_pkthdr *phdr, const guint8 *pd,
2135 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2137 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2138 epan_dissect_reset(&args->edt);
2144 cf_retap_packets(capture_file *cf)
2146 packet_range_t range;
2147 retap_callback_args_t callback_args;
2148 gboolean create_proto_tree;
2152 /* Presumably the user closed the capture file. */
2154 return CF_READ_ABORTED;
2157 cf_callback_invoke(cf_cb_file_retap_started, cf);
2159 /* Get the union of the flags for all tap listeners. */
2160 tap_flags = union_of_tap_listener_flags();
2162 /* If any tap listeners require the columns, construct them. */
2163 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2166 * Determine whether we need to create a protocol tree.
2169 * one of the tap listeners is going to apply a filter;
2171 * one of the tap listeners requires a protocol tree.
2174 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2176 /* Reset the tap listeners. */
2177 reset_tap_listeners();
2179 epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2181 /* Iterate through the list of packets, dissecting all packets and
2182 re-running the taps. */
2183 packet_range_init(&range, cf);
2184 packet_range_process_init(&range);
2186 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2187 "all packets", TRUE, retap_packet,
2188 &callback_args, TRUE);
2190 epan_dissect_cleanup(&callback_args.edt);
2192 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2196 /* Completed successfully. */
2200 /* Well, the user decided to abort the refiltering.
2201 Return CF_READ_ABORTED so our caller knows they did that. */
2202 return CF_READ_ABORTED;
2205 /* Error while retapping. */
2206 return CF_READ_ERROR;
2209 g_assert_not_reached();
2214 print_args_t *print_args;
2215 gboolean print_header_line;
2216 char *header_line_buf;
2217 int header_line_buf_len;
2218 gboolean print_formfeed;
2219 gboolean print_separator;
2223 int num_visible_cols;
2226 } print_callback_args_t;
2229 print_packet(capture_file *cf, frame_data *fdata,
2230 struct wtap_pkthdr *phdr, const guint8 *pd,
2233 print_callback_args_t *args = (print_callback_args_t *)argsp;
2239 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2240 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2241 col_item_t* col_item;
2243 /* Fill in the column information if we're printing the summary
2245 if (args->print_args->print_summary) {
2246 col_custom_prime_edt(&args->edt, &cf->cinfo);
2247 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2248 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2250 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2252 if (args->print_formfeed) {
2253 if (!new_page(args->print_args->stream))
2256 if (args->print_separator) {
2257 if (!print_line(args->print_args->stream, 0, ""))
2263 * We generate bookmarks, if the output format supports them.
2264 * The name is "__frameN__".
2266 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2268 if (args->print_args->print_summary) {
2269 if (!args->print_args->print_col_headings)
2270 args->print_header_line = FALSE;
2271 if (args->print_header_line) {
2272 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2274 args->print_header_line = FALSE; /* we might not need to print any more */
2276 cp = &args->line_buf[0];
2278 for (i = 0; i < args->num_visible_cols; i++) {
2279 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2280 /* Find the length of the string for this column. */
2281 column_len = (int) strlen(col_item->col_data);
2282 if (args->col_widths[i] > column_len)
2283 column_len = args->col_widths[i];
2285 /* Make sure there's room in the line buffer for the column; if not,
2286 double its length. */
2287 line_len += column_len + 1; /* "+1" for space */
2288 if (line_len > args->line_buf_len) {
2289 cp_off = (int) (cp - args->line_buf);
2290 args->line_buf_len = 2 * line_len;
2291 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2292 cp = args->line_buf + cp_off;
2295 /* Right-justify the packet number column. */
2296 if (col_item->col_fmt == COL_NUMBER)
2297 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2299 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2301 if (i != args->num_visible_cols - 1)
2307 * Generate a bookmark, using the summary line as the title.
2309 if (!print_bookmark(args->print_args->stream, bookmark_name,
2313 if (!print_line(args->print_args->stream, 0, args->line_buf))
2317 * Generate a bookmark, using "Frame N" as the title, as we're not
2318 * printing the summary line.
2320 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2321 if (!print_bookmark(args->print_args->stream, bookmark_name,
2324 } /* if (print_summary) */
2326 if (args->print_args->print_dissections != print_dissections_none) {
2327 if (args->print_args->print_summary) {
2328 /* Separate the summary line from the tree with a blank line. */
2329 if (!print_line(args->print_args->stream, 0, ""))
2333 /* Print the information in that tree. */
2334 if (!proto_tree_print(args->print_args->print_dissections,
2335 args->print_args->print_hex, &args->edt, NULL,
2336 args->print_args->stream))
2339 /* Print a blank line if we print anything after this (aka more than one packet). */
2340 args->print_separator = TRUE;
2342 /* Print a header line if we print any more packet summaries */
2343 if (args->print_args->print_col_headings)
2344 args->print_header_line = TRUE;
2347 if (args->print_args->print_hex) {
2348 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2349 if (!print_line(args->print_args->stream, 0, ""))
2352 /* Print the full packet data as hex. */
2353 if (!print_hex_data(args->print_args->stream, &args->edt))
2356 /* Print a blank line if we print anything after this (aka more than one packet). */
2357 args->print_separator = TRUE;
2359 /* Print a header line if we print any more packet summaries */
2360 if (args->print_args->print_col_headings)
2361 args->print_header_line = TRUE;
2362 } /* if (args->print_args->print_dissections != print_dissections_none) */
2364 epan_dissect_reset(&args->edt);
2366 /* do we want to have a formfeed between each packet from now on? */
2367 if (args->print_args->print_formfeed) {
2368 args->print_formfeed = TRUE;
2374 epan_dissect_reset(&args->edt);
2379 cf_print_packets(capture_file *cf, print_args_t *print_args,
2380 gboolean show_progress_bar)
2382 print_callback_args_t callback_args;
2385 int i, cp_off, column_len, line_len;
2386 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2390 gboolean proto_tree_needed;
2392 callback_args.print_args = print_args;
2393 callback_args.print_header_line = print_args->print_col_headings;
2394 callback_args.header_line_buf = NULL;
2395 callback_args.header_line_buf_len = 256;
2396 callback_args.print_formfeed = FALSE;
2397 callback_args.print_separator = FALSE;
2398 callback_args.line_buf = NULL;
2399 callback_args.line_buf_len = 256;
2400 callback_args.col_widths = NULL;
2401 callback_args.num_visible_cols = 0;
2402 callback_args.visible_cols = NULL;
2404 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2405 destroy_print_stream(print_args->stream);
2406 return CF_PRINT_WRITE_ERROR;
2409 if (print_args->print_summary) {
2410 /* We're printing packet summaries. Allocate the header line buffer
2411 and get the column widths. */
2412 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2414 /* Find the number of visible columns and the last visible column */
2415 for (i = 0; i < prefs.num_cols; i++) {
2417 clp = g_list_nth(prefs.col_list, i);
2418 if (clp == NULL) /* Sanity check, Invalid column requested */
2421 cfmt = (fmt_data *) clp->data;
2422 if (cfmt->visible) {
2424 last_visible_col = i;
2428 /* Find the widths for each of the columns - maximum of the
2429 width of the title and the width of the data - and construct
2430 a buffer with a line containing the column titles. */
2431 callback_args.num_visible_cols = num_visible_col;
2432 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2433 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2434 cp = &callback_args.header_line_buf[0];
2436 visible_col_count = 0;
2437 for (i = 0; i < cf->cinfo.num_cols; i++) {
2439 clp = g_list_nth(prefs.col_list, i);
2440 if (clp == NULL) /* Sanity check, Invalid column requested */
2443 cfmt = (fmt_data *) clp->data;
2444 if (cfmt->visible == FALSE)
2447 /* Save the order of visible columns */
2448 callback_args.visible_cols[visible_col_count] = i;
2450 /* Don't pad the last column. */
2451 if (i == last_visible_col)
2452 callback_args.col_widths[visible_col_count] = 0;
2454 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2455 data_width = get_column_char_width(get_column_format(i));
2456 if (data_width > callback_args.col_widths[visible_col_count])
2457 callback_args.col_widths[visible_col_count] = data_width;
2460 /* Find the length of the string for this column. */
2461 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2462 if (callback_args.col_widths[i] > column_len)
2463 column_len = callback_args.col_widths[visible_col_count];
2465 /* Make sure there's room in the line buffer for the column; if not,
2466 double its length. */
2467 line_len += column_len + 1; /* "+1" for space */
2468 if (line_len > callback_args.header_line_buf_len) {
2469 cp_off = (int) (cp - callback_args.header_line_buf);
2470 callback_args.header_line_buf_len = 2 * line_len;
2471 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2472 callback_args.header_line_buf_len + 1);
2473 cp = callback_args.header_line_buf + cp_off;
2476 /* Right-justify the packet number column. */
2477 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2478 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2480 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2482 if (i != cf->cinfo.num_cols - 1)
2485 visible_col_count++;
2489 /* Now start out the main line buffer with the same length as the
2490 header line buffer. */
2491 callback_args.line_buf_len = callback_args.header_line_buf_len;
2492 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2493 } /* if (print_summary) */
2495 /* Create the protocol tree, and make it visible, if we're printing
2496 the dissection or the hex data.
2497 XXX - do we need it if we're just printing the hex data? */
2499 callback_args.print_args->print_dissections != print_dissections_none ||
2500 callback_args.print_args->print_hex ||
2501 have_custom_cols(&cf->cinfo) || have_field_extractors();
2502 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2504 /* Iterate through the list of packets, printing the packets we were
2506 ret = process_specified_records(cf, &print_args->range, "Printing",
2507 "selected packets", TRUE, print_packet,
2508 &callback_args, show_progress_bar);
2509 epan_dissect_cleanup(&callback_args.edt);
2510 g_free(callback_args.header_line_buf);
2511 g_free(callback_args.line_buf);
2512 g_free(callback_args.col_widths);
2513 g_free(callback_args.visible_cols);
2518 /* Completed successfully. */
2522 /* Well, the user decided to abort the printing.
2524 XXX - note that what got generated before they did that
2525 will get printed if we're piping to a print program; we'd
2526 have to write to a file and then hand that to the print
2527 program to make it actually not print anything. */
2531 /* Error while printing.
2533 XXX - note that what got generated before they did that
2534 will get printed if we're piping to a print program; we'd
2535 have to write to a file and then hand that to the print
2536 program to make it actually not print anything. */
2537 destroy_print_stream(print_args->stream);
2538 return CF_PRINT_WRITE_ERROR;
2541 if (!print_finale(print_args->stream)) {
2542 destroy_print_stream(print_args->stream);
2543 return CF_PRINT_WRITE_ERROR;
2546 if (!destroy_print_stream(print_args->stream))
2547 return CF_PRINT_WRITE_ERROR;
2555 print_args_t *print_args;
2556 } write_packet_callback_args_t;
2559 write_pdml_packet(capture_file *cf, frame_data *fdata,
2560 struct wtap_pkthdr *phdr, const guint8 *pd,
2563 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2565 /* Create the protocol tree, but don't fill in the column information. */
2566 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2568 /* Write out the information in that tree. */
2569 write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, args->fh, FALSE);
2571 epan_dissect_reset(&args->edt);
2573 return !ferror(args->fh);
2577 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2579 write_packet_callback_args_t callback_args;
2583 fh = ws_fopen(print_args->file, "w");
2585 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2587 write_pdml_preamble(fh, cf->filename);
2590 return CF_PRINT_WRITE_ERROR;
2593 callback_args.fh = fh;
2594 callback_args.print_args = print_args;
2595 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2597 /* Iterate through the list of packets, printing the packets we were
2599 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2600 "selected packets", TRUE,
2601 write_pdml_packet, &callback_args, TRUE);
2603 epan_dissect_cleanup(&callback_args.edt);
2608 /* Completed successfully. */
2612 /* Well, the user decided to abort the printing. */
2616 /* Error while printing. */
2618 return CF_PRINT_WRITE_ERROR;
2621 write_pdml_finale(fh);
2624 return CF_PRINT_WRITE_ERROR;
2627 /* XXX - check for an error */
2634 write_psml_packet(capture_file *cf, frame_data *fdata,
2635 struct wtap_pkthdr *phdr, const guint8 *pd,
2638 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2640 /* Fill in the column information */
2641 col_custom_prime_edt(&args->edt, &cf->cinfo);
2642 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2643 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2645 /* Write out the column information. */
2646 write_psml_columns(&args->edt, args->fh, FALSE);
2648 epan_dissect_reset(&args->edt);
2650 return !ferror(args->fh);
2654 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2656 write_packet_callback_args_t callback_args;
2660 gboolean proto_tree_needed;
2662 fh = ws_fopen(print_args->file, "w");
2664 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2666 write_psml_preamble(&cf->cinfo, fh);
2669 return CF_PRINT_WRITE_ERROR;
2672 callback_args.fh = fh;
2673 callback_args.print_args = print_args;
2675 /* Fill in the column information, only create the protocol tree
2676 if having custom columns or field extractors. */
2677 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2678 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2680 /* Iterate through the list of packets, printing the packets we were
2682 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2683 "selected packets", TRUE,
2684 write_psml_packet, &callback_args, TRUE);
2686 epan_dissect_cleanup(&callback_args.edt);
2691 /* Completed successfully. */
2695 /* Well, the user decided to abort the printing. */
2699 /* Error while printing. */
2701 return CF_PRINT_WRITE_ERROR;
2704 write_psml_finale(fh);
2707 return CF_PRINT_WRITE_ERROR;
2710 /* XXX - check for an error */
2717 write_csv_packet(capture_file *cf, frame_data *fdata,
2718 struct wtap_pkthdr *phdr, const guint8 *pd,
2721 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2723 /* Fill in the column information */
2724 col_custom_prime_edt(&args->edt, &cf->cinfo);
2725 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2726 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2728 /* Write out the column information. */
2729 write_csv_columns(&args->edt, args->fh);
2731 epan_dissect_reset(&args->edt);
2733 return !ferror(args->fh);
2737 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2739 write_packet_callback_args_t callback_args;
2740 gboolean proto_tree_needed;
2744 fh = ws_fopen(print_args->file, "w");
2746 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2748 write_csv_column_titles(&cf->cinfo, fh);
2751 return CF_PRINT_WRITE_ERROR;
2754 callback_args.fh = fh;
2755 callback_args.print_args = print_args;
2757 /* only create the protocol tree if having custom columns or field extractors. */
2758 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2759 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2761 /* Iterate through the list of packets, printing the packets we were
2763 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2764 "selected packets", TRUE,
2765 write_csv_packet, &callback_args, TRUE);
2767 epan_dissect_cleanup(&callback_args.edt);
2772 /* Completed successfully. */
2776 /* Well, the user decided to abort the printing. */
2780 /* Error while printing. */
2782 return CF_PRINT_WRITE_ERROR;
2785 /* XXX - check for an error */
2792 carrays_write_packet(capture_file *cf, frame_data *fdata,
2793 struct wtap_pkthdr *phdr,
2794 const guint8 *pd, void *argsp)
2796 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2798 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2799 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2800 epan_dissect_reset(&args->edt);
2802 return !ferror(args->fh);
2806 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2808 write_packet_callback_args_t callback_args;
2812 fh = ws_fopen(print_args->file, "w");
2815 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2819 return CF_PRINT_WRITE_ERROR;
2822 callback_args.fh = fh;
2823 callback_args.print_args = print_args;
2824 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2826 /* Iterate through the list of packets, printing the packets we were
2828 ret = process_specified_records(cf, &print_args->range,
2830 "selected packets", TRUE,
2831 carrays_write_packet, &callback_args, TRUE);
2833 epan_dissect_cleanup(&callback_args.edt);
2837 /* Completed successfully. */
2840 /* Well, the user decided to abort the printing. */
2843 /* Error while printing. */
2845 return CF_PRINT_WRITE_ERROR;
2853 write_json_packet(capture_file *cf, frame_data *fdata,
2854 struct wtap_pkthdr *phdr, const guint8 *pd,
2857 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2859 /* Create the protocol tree, but don't fill in the column information. */
2860 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2862 /* Write out the information in that tree. */
2863 write_json_proto_tree(NULL, args->print_args->print_dissections,
2864 args->print_args->print_hex, NULL, PF_NONE,
2865 &args->edt, proto_node_group_children_by_unique, args->fh);
2867 epan_dissect_reset(&args->edt);
2869 return !ferror(args->fh);
2873 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2875 write_packet_callback_args_t callback_args;
2879 fh = ws_fopen(print_args->file, "w");
2881 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2883 write_json_preamble(fh);
2886 return CF_PRINT_WRITE_ERROR;
2889 callback_args.fh = fh;
2890 callback_args.print_args = print_args;
2891 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2893 /* Iterate through the list of packets, printing the packets we were
2895 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2896 "selected packets", TRUE,
2897 write_json_packet, &callback_args, TRUE);
2899 epan_dissect_cleanup(&callback_args.edt);
2904 /* Completed successfully. */
2908 /* Well, the user decided to abort the printing. */
2912 /* Error while printing. */
2914 return CF_PRINT_WRITE_ERROR;
2917 write_json_finale(fh);
2920 return CF_PRINT_WRITE_ERROR;
2923 /* XXX - check for an error */
2930 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2931 search_direction dir)
2935 mdata.string = string;
2936 mdata.string_len = strlen(string);
2937 return find_packet(cf, match_protocol_tree, &mdata, dir);
2941 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2943 mdata->frame_matched = FALSE;
2944 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2945 mdata->string_len = strlen(mdata->string);
2947 /* Iterate through all the nodes looking for matching text */
2948 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2949 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2953 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2955 match_data *mdata = (match_data *)criterion;
2958 /* Load the frame's data. */
2959 if (!cf_read_record(cf, fdata)) {
2960 /* Attempt to get the packet failed. */
2964 /* Construct the protocol tree, including the displayed text */
2965 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2966 /* We don't need the column information */
2967 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
2969 /* Iterate through all the nodes, seeing if they have text that matches. */
2971 mdata->frame_matched = FALSE;
2972 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2973 epan_dissect_cleanup(&edt);
2974 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2978 match_subtree_text(proto_node *node, gpointer data)
2980 match_data *mdata = (match_data *) data;
2981 const gchar *string = mdata->string;
2982 size_t string_len = mdata->string_len;
2983 capture_file *cf = mdata->cf;
2984 field_info *fi = PNODE_FINFO(node);
2985 gchar label_str[ITEM_LABEL_LENGTH];
2992 /* dissection with an invisible proto tree? */
2995 if (mdata->frame_matched) {
2996 /* We already had a match; don't bother doing any more work. */
3000 /* Don't match invisible entries. */
3001 if (PROTO_ITEM_IS_HIDDEN(node))
3004 /* was a free format label produced? */
3006 label_ptr = fi->rep->representation;
3008 /* no, make a generic label */
3009 label_ptr = label_str;
3010 proto_item_fill_label(fi, label_str);
3014 if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
3015 mdata->frame_matched = TRUE;
3020 /* Does that label match? */
3021 label_len = strlen(label_ptr);
3022 for (i = 0; i < label_len; i++) {
3023 c_char = label_ptr[i];
3025 c_char = g_ascii_toupper(c_char);
3026 if (c_char == string[c_match]) {
3028 if (c_match == string_len) {
3029 /* No need to look further; we have a match */
3030 mdata->frame_matched = TRUE;
3039 /* Recurse into the subtree, if it exists */
3040 if (node->first_child != NULL)
3041 proto_tree_children_foreach(node, match_subtree_text, mdata);
3045 cf_find_packet_summary_line(capture_file *cf, const char *string,
3046 search_direction dir)
3050 mdata.string = string;
3051 mdata.string_len = strlen(string);
3052 return find_packet(cf, match_summary_line, &mdata, dir);
3056 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3058 match_data *mdata = (match_data *)criterion;
3059 const gchar *string = mdata->string;
3060 size_t string_len = mdata->string_len;
3062 const char *info_column;
3063 size_t info_column_len;
3064 match_result result = MR_NOTMATCHED;
3070 /* Load the frame's data. */
3071 if (!cf_read_record(cf, fdata)) {
3072 /* Attempt to get the packet failed. */
3076 /* Don't bother constructing the protocol tree */
3077 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3078 /* Get the column information */
3079 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
3082 /* Find the Info column */
3083 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3084 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3085 /* Found it. See if we match. */
3086 info_column = edt.pi.cinfo->columns[colx].col_data;
3087 info_column_len = strlen(info_column);
3089 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3090 result = MR_MATCHED;
3094 for (i = 0; i < info_column_len; i++) {
3095 c_char = info_column[i];
3097 c_char = g_ascii_toupper(c_char);
3098 if (c_char == string[c_match]) {
3100 if (c_match == string_len) {
3101 result = MR_MATCHED;
3111 epan_dissect_cleanup(&edt);
3118 } cbs_t; /* "Counted byte string" */
3122 * The current match_* routines only support ASCII case insensitivity and don't
3123 * convert UTF-8 inputs to UTF-16 for matching.
3125 * We could modify them to use the GLib Unicode routines or the International
3126 * Components for Unicode library but it's not apparent that we could do so
3127 * without consuming a lot more CPU and memory or that searching would be
3128 * significantly better.
3132 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3133 search_direction dir)
3138 info.data_len = string_size;
3140 /* Regex, String or hex search? */
3142 /* Regular Expression search */
3143 return find_packet(cf, match_regex, NULL, dir);
3144 } else if (cf->string) {
3145 /* String search - what type of string? */
3146 switch (cf->scs_type) {
3148 case SCS_NARROW_AND_WIDE:
3149 return find_packet(cf, match_narrow_and_wide, &info, dir);
3152 return find_packet(cf, match_narrow, &info, dir);
3155 return find_packet(cf, match_wide, &info, dir);
3158 g_assert_not_reached();
3162 return find_packet(cf, match_binary, &info, dir);
3166 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3168 cbs_t *info = (cbs_t *)criterion;
3169 const guint8 *ascii_text = info->data;
3170 size_t textlen = info->data_len;
3171 match_result result;
3178 /* Load the frame's data. */
3179 if (!cf_read_record(cf, fdata)) {
3180 /* Attempt to get the packet failed. */
3184 result = MR_NOTMATCHED;
3185 buf_len = fdata->cap_len;
3186 pd = ws_buffer_start_ptr(&cf->buf);
3188 while (i < buf_len) {
3191 c_char = g_ascii_toupper(c_char);
3192 if (c_char != '\0') {
3193 if (c_char == ascii_text[c_match]) {
3195 if (c_match == textlen) {
3196 result = MR_MATCHED;
3197 cf->search_pos = i; /* Save the position of the last character
3198 for highlighting the field. */
3199 cf->search_len = (guint32)textlen;
3204 g_assert(i>=c_match);
3205 i -= (guint32)c_match;
3215 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3218 cbs_t *info = (cbs_t *)criterion;
3219 const guint8 *ascii_text = info->data;
3220 size_t textlen = info->data_len;
3221 match_result result;
3227 /* Load the frame's data. */
3228 if (!cf_read_record(cf, fdata)) {
3229 /* Attempt to get the packet failed. */
3233 result = MR_NOTMATCHED;
3234 buf_len = fdata->cap_len;
3235 pd = ws_buffer_start_ptr(&cf->buf);
3237 while (i < buf_len) {
3240 c_char = g_ascii_toupper(c_char);
3241 if (c_char == ascii_text[c_match]) {
3243 if (c_match == textlen) {
3244 result = MR_MATCHED;
3245 cf->search_pos = i; /* Save the position of the last character
3246 for highlighting the field. */
3247 cf->search_len = (guint32)textlen;
3252 g_assert(i>=c_match);
3253 i -= (guint32)c_match;
3263 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3265 cbs_t *info = (cbs_t *)criterion;
3266 const guint8 *ascii_text = info->data;
3267 size_t textlen = info->data_len;
3268 match_result result;
3275 /* Load the frame's data. */
3276 if (!cf_read_record(cf, fdata)) {
3277 /* Attempt to get the packet failed. */
3281 result = MR_NOTMATCHED;
3282 buf_len = fdata->cap_len;
3283 pd = ws_buffer_start_ptr(&cf->buf);
3285 while (i < buf_len) {
3288 c_char = g_ascii_toupper(c_char);
3289 if (c_char == ascii_text[c_match]) {
3291 if (c_match == textlen) {
3292 result = MR_MATCHED;
3293 cf->search_pos = i; /* Save the position of the last character
3294 for highlighting the field. */
3295 cf->search_len = (guint32)textlen;
3301 g_assert(i>=(c_match*2));
3302 i -= (guint32)c_match*2;
3311 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3313 cbs_t *info = (cbs_t *)criterion;
3314 const guint8 *binary_data = info->data;
3315 size_t datalen = info->data_len;
3316 match_result result;
3322 /* Load the frame's data. */
3323 if (!cf_read_record(cf, fdata)) {
3324 /* Attempt to get the packet failed. */
3328 result = MR_NOTMATCHED;
3329 buf_len = fdata->cap_len;
3330 pd = ws_buffer_start_ptr(&cf->buf);
3332 while (i < buf_len) {
3333 if (pd[i] == binary_data[c_match]) {
3335 if (c_match == datalen) {
3336 result = MR_MATCHED;
3337 cf->search_pos = i; /* Save the position of the last character
3338 for highlighting the field. */
3339 cf->search_len = (guint32)datalen;
3344 g_assert(i>=c_match);
3345 i -= (guint32)c_match;
3354 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3356 match_result result = MR_NOTMATCHED;
3357 GMatchInfo *match_info = NULL;
3359 /* Load the frame's data. */
3360 if (!cf_read_record(cf, fdata)) {
3361 /* Attempt to get the packet failed. */
3365 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3366 0, (GRegexMatchFlags) 0, &match_info, NULL))
3368 gint start_pos = 0, end_pos = 0;
3369 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3370 cf->search_pos = end_pos - 1;
3371 cf->search_len = end_pos - start_pos;
3372 result = MR_MATCHED;
3378 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3379 search_direction dir)
3381 return find_packet(cf, match_dfilter, sfcode, dir);
3385 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3386 search_direction dir)
3391 if (!dfilter_compile(filter, &sfcode, NULL)) {
3393 * XXX - this shouldn't happen, as the filter string is machine
3398 if (sfcode == NULL) {
3400 * XXX - this shouldn't happen, as the filter string is machine
3405 result = find_packet(cf, match_dfilter, sfcode, dir);
3406 dfilter_free(sfcode);
3411 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3413 dfilter_t *sfcode = (dfilter_t *)criterion;
3415 match_result result;
3417 /* Load the frame's data. */
3418 if (!cf_read_record(cf, fdata)) {
3419 /* Attempt to get the packet failed. */
3423 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3424 epan_dissect_prime_with_dfilter(&edt, sfcode);
3425 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3426 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3427 epan_dissect_cleanup(&edt);
3432 cf_find_packet_marked(capture_file *cf, search_direction dir)
3434 return find_packet(cf, match_marked, NULL, dir);
3438 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3440 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3444 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3446 return find_packet(cf, match_time_reference, NULL, dir);
3450 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3452 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3456 find_packet(capture_file *cf,
3457 match_result (*match_function)(capture_file *, frame_data *, void *),
3458 void *criterion, search_direction dir)
3460 frame_data *start_fd;
3463 frame_data *new_fd = NULL;
3464 progdlg_t *progbar = NULL;
3465 GTimer *prog_timer = g_timer_new();
3469 GTimeVal start_time;
3470 gchar status_str[100];
3472 match_result result;
3474 start_fd = cf->current_frame;
3475 if (start_fd != NULL) {
3476 /* Iterate through the list of packets, starting at the packet we've
3477 picked, calling a routine to run the filter on the packet, see if
3478 it matches, and stop if so. */
3480 framenum = start_fd->num;
3482 g_timer_start(prog_timer);
3483 /* Progress so far. */
3486 cf->stop_flag = FALSE;
3487 g_get_current_time(&start_time);
3489 title = cf->sfilter?cf->sfilter:"";
3491 /* Create the progress bar if necessary.
3492 We check on every iteration of the loop, so that it takes no
3493 longer than the standard time to create it (otherwise, for a
3494 large file, we might take considerably longer than that standard
3495 time in order to get to the next progress bar step). */
3496 if (progbar == NULL)
3497 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3498 FALSE, &cf->stop_flag, &start_time, progbar_val);
3501 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3502 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3503 * likely trigger UI paint events, which might take a while depending on
3504 * the platform and display. Reset our timer *after* painting.
3506 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3507 /* let's not divide by zero. I should never be started
3508 * with count == 0, so let's assert that
3510 g_assert(cf->count > 0);
3512 progbar_val = (gfloat) count / cf->count;
3514 g_snprintf(status_str, sizeof(status_str),
3515 "%4u of %u packets", count, cf->count);
3516 update_progress_dlg(progbar, progbar_val, status_str);
3518 g_timer_start(prog_timer);
3521 if (cf->stop_flag) {
3522 /* Well, the user decided to abort the search. Go back to the
3523 frame where we started. */
3528 /* Go past the current frame. */
3529 if (dir == SD_BACKWARD) {
3530 /* Go on to the previous frame. */
3531 if (framenum == 1) {
3533 * XXX - other apps have a bit more of a detailed message
3534 * for this, and instead of offering "OK" and "Cancel",
3535 * they offer things such as "Continue" and "Cancel";
3536 * we need an API for popping up alert boxes with
3537 * {Verb} and "Cancel".
3540 if (prefs.gui_find_wrap)
3542 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3543 framenum = cf->count; /* wrap around */
3547 statusbar_push_temporary_msg("Search reached the beginning.");
3548 framenum = start_fd->num; /* stay on previous packet */
3553 /* Go on to the next frame. */
3554 if (framenum == cf->count) {
3555 if (prefs.gui_find_wrap)
3557 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3558 framenum = 1; /* wrap around */
3562 statusbar_push_temporary_msg("Search reached the end.");
3563 framenum = start_fd->num; /* stay on previous packet */
3568 fdata = frame_data_sequence_find(cf->frames, framenum);
3572 /* Is this packet in the display? */
3573 if (fdata->flags.passed_dfilter) {
3574 /* Yes. Does it match the search criterion? */
3575 result = (*match_function)(cf, fdata, criterion);
3576 if (result == MR_ERROR) {
3577 /* Error; our caller has reported the error. Go back to the frame
3578 where we started. */
3581 } else if (result == MR_MATCHED) {
3582 /* Yes. Go to the new frame. */
3588 if (fdata == start_fd) {
3589 /* We're back to the frame we were on originally, and that frame
3590 doesn't match the search filter. The search failed. */
3595 /* We're done scanning the packets; destroy the progress bar if it
3597 if (progbar != NULL)
3598 destroy_progress_dlg(progbar);
3599 g_timer_destroy(prog_timer);
3602 if (new_fd != NULL) {
3603 /* Find and select */
3604 cf->search_in_progress = TRUE;
3605 found = packet_list_select_row_from_data(new_fd);
3606 cf->search_in_progress = FALSE;
3607 cf->search_pos = 0; /* Reset the position */
3608 cf->search_len = 0; /* Reset length */
3610 /* We didn't find a row corresponding to this frame.
3611 This means that the frame isn't being displayed currently,
3612 so we can't select it. */
3613 simple_message_box(ESD_TYPE_INFO, NULL,
3614 "The capture file is probably not fully dissected.",
3615 "End of capture exceeded.");
3618 return TRUE; /* success */
3620 return FALSE; /* failure */
3624 cf_goto_frame(capture_file *cf, guint fnumber)
3628 if (cf == NULL || cf->frames == NULL) {
3629 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3630 statusbar_push_temporary_msg("There is no file loaded");
3631 return FALSE; /* we failed to go to that packet */
3634 fdata = frame_data_sequence_find(cf->frames, fnumber);
3636 if (fdata == NULL) {
3637 /* we didn't find a packet with that packet number */
3638 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3639 return FALSE; /* we failed to go to that packet */
3641 if (!fdata->flags.passed_dfilter) {
3642 /* that packet currently isn't displayed */
3643 /* XXX - add it to the set of displayed packets? */
3644 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3645 return FALSE; /* we failed to go to that packet */
3648 if (!packet_list_select_row_from_data(fdata)) {
3649 /* We didn't find a row corresponding to this frame.
3650 This means that the frame isn't being displayed currently,
3651 so we can't select it. */
3652 simple_message_box(ESD_TYPE_INFO, NULL,
3653 "The capture file is probably not fully dissected.",
3654 "End of capture exceeded.");
3657 return TRUE; /* we got to that packet */
3661 * Go to frame specified by currently selected protocol tree item.
3664 cf_goto_framenum(capture_file *cf)
3666 header_field_info *hfinfo;
3669 if (cf->finfo_selected) {
3670 hfinfo = cf->finfo_selected->hfinfo;
3672 if (hfinfo->type == FT_FRAMENUM) {
3673 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3675 return cf_goto_frame(cf, framenum);
3682 /* Select the packet on a given row. */
3684 cf_select_packet(capture_file *cf, int row)
3686 epan_dissect_t *old_edt;
3689 /* Get the frame data struct pointer for this frame */
3690 fdata = packet_list_get_row_data(row);
3692 if (fdata == NULL) {
3696 /* Get the data in that frame. */
3697 if (!cf_read_record (cf, fdata)) {
3701 /* Record that this frame is the current frame. */
3702 cf->current_frame = fdata;
3703 cf->current_row = row;
3706 /* Create the logical protocol tree. */
3707 /* We don't need the columns here. */
3708 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3710 tap_build_interesting(cf->edt);
3711 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3712 cf->current_frame, NULL);
3714 dfilter_macro_build_ftv_cache(cf->edt->tree);
3716 cf_callback_invoke(cf_cb_packet_selected, cf);
3718 if (old_edt != NULL)
3719 epan_dissect_free(old_edt);
3723 /* Unselect the selected packet, if any. */
3725 cf_unselect_packet(capture_file *cf)
3727 epan_dissect_t *old_edt = cf->edt;
3731 /* No packet is selected. */
3732 cf->current_frame = NULL;
3733 cf->current_row = 0;
3735 cf_callback_invoke(cf_cb_packet_unselected, cf);
3737 /* No protocol tree means no selected field. */
3738 cf_unselect_field(cf);
3740 /* Destroy the epan_dissect_t for the unselected packet. */
3741 if (old_edt != NULL)
3742 epan_dissect_free(old_edt);
3745 /* Unset the selected protocol tree field, if any. */
3747 cf_unselect_field(capture_file *cf)
3749 cf->finfo_selected = NULL;
3751 cf_callback_invoke(cf_cb_field_unselected, cf);
3755 * Mark a particular frame.
3758 cf_mark_frame(capture_file *cf, frame_data *frame)
3760 if (! frame->flags.marked) {
3761 frame->flags.marked = TRUE;
3762 if (cf->count > cf->marked_count)
3768 * Unmark a particular frame.
3771 cf_unmark_frame(capture_file *cf, frame_data *frame)
3773 if (frame->flags.marked) {
3774 frame->flags.marked = FALSE;
3775 if (cf->marked_count > 0)
3781 * Ignore a particular frame.
3784 cf_ignore_frame(capture_file *cf, frame_data *frame)
3786 if (! frame->flags.ignored) {
3787 frame->flags.ignored = TRUE;
3788 if (cf->count > cf->ignored_count)
3789 cf->ignored_count++;
3794 * Un-ignore a particular frame.
3797 cf_unignore_frame(capture_file *cf, frame_data *frame)
3799 if (frame->flags.ignored) {
3800 frame->flags.ignored = FALSE;
3801 if (cf->ignored_count > 0)
3802 cf->ignored_count--;
3807 * Read the section comment.
3810 cf_read_section_comment(capture_file *cf)
3812 wtap_block_t shb_inf;
3816 /* XXX - support multiple SHBs */
3817 shb_inf = wtap_file_get_shb(cf->wth);
3819 /* Get the first comment from the SHB. */
3820 /* XXX - support multiple comments */
3821 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3827 * Modify the section comment.
3830 cf_update_section_comment(capture_file *cf, gchar *comment)
3832 wtap_block_t shb_inf;
3836 /* XXX - support multiple SHBs */
3837 shb_inf = wtap_file_get_shb(cf->wth);
3839 /* Get the first comment from the SHB. */
3840 /* XXX - support multiple comments */
3841 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3842 /* There's no comment - add one. */
3843 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3845 /* See if the comment has changed or not */
3846 if (strcmp(shb_comment, comment) == 0) {
3851 /* The comment has changed, let's update it */
3852 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3854 /* Mark the file as having unsaved changes */
3855 cf->unsaved_changes = TRUE;
3859 cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
3861 if (cf->frames_user_comments)
3862 return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
3869 * Get the comment on a packet (record).
3870 * If the comment has been edited, it returns the result of the edit,
3871 * otherwise it returns the comment from the file.
3874 cf_get_packet_comment(capture_file *cf, const frame_data *fd)
3878 /* fetch user comment */
3879 if (fd->flags.has_user_comment)
3880 return g_strdup(cf_get_user_packet_comment(cf, fd));
3882 /* fetch phdr comment */
3883 if (fd->flags.has_phdr_comment) {
3884 struct wtap_pkthdr phdr; /* Packet header */
3885 Buffer buf; /* Packet data */
3887 wtap_phdr_init(&phdr);
3888 ws_buffer_init(&buf, 1500);
3890 if (!cf_read_record_r(cf, fd, &phdr, &buf))
3891 { /* XXX, what we can do here? */ }
3893 comment = phdr.opt_comment;
3894 wtap_phdr_cleanup(&phdr);
3895 ws_buffer_free(&buf);
3902 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3904 const frame_data *fdata1 = (const frame_data *) a;
3905 const frame_data *fdata2 = (const frame_data *) b;
3907 return (fdata1->num < fdata2->num) ? -1 :
3908 (fdata1->num > fdata2->num) ? 1 :
3913 * Update(replace) the comment on a capture from a frame
3916 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3918 char *pkt_comment = cf_get_packet_comment(cf, fd);
3920 /* Check if the comment has changed */
3921 if (!g_strcmp0(pkt_comment, new_comment)) {
3922 g_free(pkt_comment);
3925 g_free(pkt_comment);
3928 cf->packet_comment_count--;
3931 cf->packet_comment_count++;
3933 fd->flags.has_user_comment = TRUE;
3935 if (!cf->frames_user_comments)
3936 cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
3938 /* insert new packet comment */
3939 g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
3941 expert_update_comment_count(cf->packet_comment_count);
3943 /* OK, we have unsaved changes. */
3944 cf->unsaved_changes = TRUE;
3949 * What types of comments does this capture file have?
3952 cf_comment_types(capture_file *cf)
3954 guint32 comment_types = 0;
3956 if (cf_read_section_comment(cf) != NULL)
3957 comment_types |= WTAP_COMMENT_PER_SECTION;
3958 if (cf->packet_comment_count != 0)
3959 comment_types |= WTAP_COMMENT_PER_PACKET;
3960 return comment_types;
3964 * Add a resolved address to this file's list of resolved addresses.
3967 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
3970 * XXX - support multiple resolved address lists, and add to the one
3971 * attached to this file?
3973 if (!add_ip_name_from_string(addr, name))
3976 /* OK, we have unsaved changes. */
3977 cf->unsaved_changes = TRUE;
3981 #ifdef WANT_PACKET_EDITOR
3983 g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3994 modified_frame_data_free(gpointer data)
3996 modified_frame_data *mfd = (modified_frame_data *)data;
4003 * Give a frame new, edited data.
4006 cf_set_frame_edited(capture_file *cf, frame_data *fd,
4007 struct wtap_pkthdr *phdr, guint8 *pd)
4009 modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data));
4012 mfd->pd = (char *)pd;
4014 if (cf->edited_frames == NULL)
4015 cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL,
4016 modified_frame_data_free);
4017 g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd);
4020 /* Mark the file as having unsaved changes */
4021 cf->unsaved_changes = TRUE;
4029 } save_callback_args_t;
4032 * Save a capture to a file, in a particular format, saving either
4033 * all packets, all currently-displayed packets, or all marked packets.
4035 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4036 * up a message box for the failure.
4039 save_record(capture_file *cf, frame_data *fdata,
4040 struct wtap_pkthdr *phdr, const guint8 *pd,
4043 save_callback_args_t *args = (save_callback_args_t *)argsp;
4044 struct wtap_pkthdr hdr;
4047 const char *pkt_comment;
4049 if (fdata->flags.has_user_comment)
4050 pkt_comment = cf_get_user_packet_comment(cf, fdata);
4052 pkt_comment = phdr->opt_comment;
4054 /* init the wtap header for saving */
4055 /* TODO: reuse phdr */
4056 /* XXX - these are the only flags that correspond to data that we have
4057 in the frame_data structure and that matter on a per-packet basis.
4059 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
4060 and "on the wire" lengths, or it doesn't.
4062 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
4065 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
4066 from the packet flags. */
4067 hdr.rec_type = phdr->rec_type;
4068 hdr.presence_flags = 0;
4069 if (fdata->flags.has_ts)
4070 hdr.presence_flags |= WTAP_HAS_TS;
4071 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
4072 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
4073 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
4074 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
4076 hdr.caplen = phdr->caplen;
4077 hdr.len = phdr->len;
4078 hdr.pkt_encap = phdr->pkt_encap;
4080 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
4082 hdr.pack_flags = phdr->pack_flags;
4083 hdr.opt_comment = g_strdup(pkt_comment);
4084 hdr.has_comment_changed = fdata->flags.has_user_comment ? TRUE : FALSE;
4087 hdr.pseudo_header = phdr->pseudo_header;
4090 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
4092 /* and save the packet */
4093 if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
4094 cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
4099 g_free(hdr.opt_comment);
4104 * Can this capture file be written out in any format using Wiretap
4105 * rather than by copying the raw data?
4108 cf_can_write_with_wiretap(capture_file *cf)
4110 /* We don't care whether we support the comments in this file or not;
4111 if we can't, we'll offer the user the option of discarding the
4113 return wtap_dump_can_write(cf->linktypes, 0);
4117 * Should we let the user do a save?
4121 * the file has unsaved changes, and we can save it in some
4122 * format through Wiretap
4126 * the file is a temporary file and has no unsaved changes (so
4127 * that "saving" it just means copying it).
4129 * XXX - we shouldn't allow files to be edited if they can't be saved,
4130 * so cf->unsaved_changes should be true only if the file can be saved.
4132 * We don't care whether we support the comments in this file or not;
4133 * if we can't, we'll offer the user the option of discarding the
4137 cf_can_save(capture_file *cf)
4139 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4140 /* Saved changes, and we can write it out with Wiretap. */
4144 if (cf->is_tempfile && !cf->unsaved_changes) {
4146 * Temporary file with no unsaved changes, so we can just do a
4152 /* Nothing to save. */
4157 * Should we let the user do a "save as"?
4161 * we can save it in some format through Wiretap
4165 * the file is a temporary file and has no unsaved changes (so
4166 * that "saving" it just means copying it).
4168 * XXX - we shouldn't allow files to be edited if they can't be saved,
4169 * so cf->unsaved_changes should be true only if the file can be saved.
4171 * We don't care whether we support the comments in this file or not;
4172 * if we can't, we'll offer the user the option of discarding the
4176 cf_can_save_as(capture_file *cf)
4178 if (wtap_dump_can_write(cf->linktypes, 0)) {
4179 /* We can write it out with Wiretap. */
4183 if (cf->is_tempfile && !cf->unsaved_changes) {
4185 * Temporary file with no unsaved changes, so we can just do a
4191 /* Nothing to save. */
4196 * Does this file have unsaved data?
4199 cf_has_unsaved_data(capture_file *cf)
4202 * If this is a temporary file, or a file with unsaved changes, it
4205 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4209 * Quick scan to find packet offsets.
4211 static cf_read_status_t
4212 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4214 const struct wtap_pkthdr *phdr;
4219 progdlg_t *progbar = NULL;
4220 GTimer *prog_timer = g_timer_new();
4223 GTimeVal start_time;
4224 gchar status_str[100];
4229 /* Close the old handle. */
4230 wtap_close(cf->wth);
4232 /* Open the new file. */
4233 /* XXX: this will go through all open_routines for a matching one. But right
4234 now rescan_file() is only used when a file is being saved to a different
4235 format than the original, and the user is not given a choice of which
4236 reader to use (only which format to save it in), so doing this makes
4238 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4239 if (cf->wth == NULL) {
4240 cfile_open_failure_alert_box(fname, err, err_info);
4241 return CF_READ_ERROR;
4244 /* We're scanning a file whose contents should be the same as what
4245 we had before, so we don't discard dissection state etc.. */
4248 /* Set the file name because we need it to set the follow stream filter.
4249 XXX - is that still true? We need it for other reasons, though,
4251 cf->filename = g_strdup(fname);
4253 /* Indicate whether it's a permanent or temporary file. */
4254 cf->is_tempfile = is_tempfile;
4256 /* No user changes yet. */
4257 cf->unsaved_changes = FALSE;
4259 cf->cd_t = wtap_file_type_subtype(cf->wth);
4260 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4262 cf->snap = wtap_snapshot_length(cf->wth);
4264 name_ptr = g_filename_display_basename(cf->filename);
4266 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4268 /* Record whether the file is compressed.
4269 XXX - do we know this at open time? */
4270 cf->iscompressed = wtap_iscompressed(cf->wth);
4272 /* Find the size of the file. */
4273 size = wtap_file_size(cf->wth, NULL);
4275 g_timer_start(prog_timer);
4277 cf->stop_flag = FALSE;
4278 g_get_current_time(&start_time);
4281 phdr = wtap_phdr(cf->wth);
4282 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
4284 fdata = frame_data_sequence_find(cf->frames, framenum);
4285 fdata->file_off = data_offset;
4288 cf->f_datalen = wtap_read_so_far(cf->wth);
4290 /* Create the progress bar if necessary. */
4291 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4292 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4293 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4294 TRUE, &cf->stop_flag, &start_time, progbar_val);
4298 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4299 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4300 * likely trigger UI paint events, which might take a while depending on
4301 * the platform and display. Reset our timer *after* painting.
4303 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4304 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4305 /* update the packet bar content on the first run or frequently on very large files */
4306 update_progress_dlg(progbar, progbar_val, status_str);
4307 compute_elapsed(cf, &start_time);
4308 packets_bar_update();
4309 g_timer_start(prog_timer);
4313 if (cf->stop_flag) {
4314 /* Well, the user decided to abort the rescan. Sadly, as this
4315 isn't a reread, recovering is difficult, so we'll just
4316 close the current capture. */
4320 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4321 it's not already there.
4322 XXX - yes, this is O(N), so if every packet had a different
4323 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4324 there are probably going to be a small number of encapsulation types
4326 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4329 /* Free the display name */
4332 /* We're done reading the file; destroy the progress bar if it was created. */
4333 if (progbar != NULL)
4334 destroy_progress_dlg(progbar);
4335 g_timer_destroy(prog_timer);
4337 /* We're done reading sequentially through the file. */
4338 cf->state = FILE_READ_DONE;
4340 /* Close the sequential I/O side, to free up memory it requires. */
4341 wtap_sequential_close(cf->wth);
4343 /* compute the time it took to load the file */
4344 compute_elapsed(cf, &start_time);
4346 /* Set the file encapsulation type now; we don't know what it is until
4347 we've looked at all the packets, as we don't know until then whether
4348 there's more than one type (and thus whether it's
4349 WTAP_ENCAP_PER_PACKET). */
4350 cf->lnk_t = wtap_file_encap(cf->wth);
4352 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4354 if (cf->stop_flag) {
4355 /* Our caller will give up at this point. */
4356 return CF_READ_ABORTED;
4360 /* Put up a message box noting that the read failed somewhere along
4361 the line. Don't throw out the stuff we managed to read, though,
4363 cfile_read_failure_alert_box(NULL, err, err_info);
4364 return CF_READ_ERROR;
4370 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4371 gboolean compressed, gboolean discard_comments,
4372 gboolean dont_reopen)
4375 gchar *fname_new = NULL;
4378 addrinfo_lists_t *addr_lists;
4382 gchar *display_basename;
4389 save_callback_args_t callback_args;
4390 gboolean needs_reload = FALSE;
4392 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4394 addr_lists = get_addrinfo_list();
4396 if (save_format == cf->cd_t && compressed == cf->iscompressed
4397 && !discard_comments && !cf->unsaved_changes
4398 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4399 /* We're saving in the format it's already in, and we're
4400 not discarding comments, and there are no changes we have
4401 in memory that aren't saved to the file, and we have no name
4402 resolution blocks to write, so we can just move or copy the raw data. */
4404 if (cf->is_tempfile) {
4405 /* The file being saved is a temporary file from a live
4406 capture, so it doesn't need to stay around under that name;
4407 first, try renaming the capture buffer file to the new name.
4408 This acts as a "safe save", in that, if the file already
4409 exists, the existing file will be removed only if the rename
4412 Sadly, on Windows, as we have the current capture file
4413 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4414 (to cause the rename to remove an existing target), as
4415 done by ws_stdio_rename() (ws_rename() is #defined to
4416 be ws_stdio_rename() on Windows) will fail.
4418 According to the MSDN documentation for CreateFile(), if,
4419 when we open a capture file, we were to directly do a CreateFile(),
4420 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4421 convert it to a file descriptor with _open_osfhandle(),
4422 that would allow the file to be renamed out from under us.
4424 However, that doesn't work in practice. Perhaps the problem
4425 is that the process doing the rename is the process that
4426 has the file open. */
4428 if (ws_rename(cf->filename, fname) == 0) {
4429 /* That succeeded - there's no need to copy the source file. */
4430 how_to_save = SAVE_WITH_MOVE;
4432 if (errno == EXDEV) {
4433 /* They're on different file systems, so we have to copy the
4435 how_to_save = SAVE_WITH_COPY;
4437 /* The rename failed, but not because they're on different
4438 file systems - put up an error message. (Or should we
4439 just punt and try to copy? The only reason why I'd
4440 expect the rename to fail and the copy to succeed would
4441 be if we didn't have permission to remove the file from
4442 the temporary directory, and that might be fixable - but
4443 is it worth requiring the user to go off and fix it?) */
4444 cf_rename_failure_alert_box(fname, errno);
4449 how_to_save = SAVE_WITH_COPY;
4452 /* It's a permanent file, so we should copy it, and not remove the
4454 how_to_save = SAVE_WITH_COPY;
4457 if (how_to_save == SAVE_WITH_COPY) {
4458 /* Copy the file, if we haven't moved it. If we're overwriting
4459 an existing file, we do it with a "safe save", by writing
4460 to a new file and, if the write succeeds, renaming the
4461 new file on top of the old file. */
4462 if (file_exists(fname)) {
4463 fname_new = g_strdup_printf("%s~", fname);
4464 if (!copy_file_binary_mode(cf->filename, fname_new))
4467 if (!copy_file_binary_mode(cf->filename, fname))
4472 /* Either we're saving in a different format or we're saving changes,
4473 such as added, modified, or removed comments, that haven't yet
4474 been written to the underlying file; we can't do that by copying
4475 or moving the capture file, we have to do it by writing the packets
4478 GArray *shb_hdrs = NULL;
4479 wtapng_iface_descriptions_t *idb_inf = NULL;
4480 GArray *nrb_hdrs = NULL;
4483 /* XXX: what free's this shb_hdr? */
4484 shb_hdrs = wtap_file_get_shb_for_new_file(cf->wth);
4485 idb_inf = wtap_file_get_idb_info(cf->wth);
4486 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
4488 /* Determine what file encapsulation type we should use. */
4489 encap = wtap_dump_file_encap_type(cf->linktypes);
4491 if (file_exists(fname)) {
4492 /* We're overwriting an existing file; write out to a new file,
4493 and, if that succeeds, rename the new file on top of the
4494 old file. That makes this a "safe save", so that we don't
4495 lose the old file if we have a problem writing out the new
4496 file. (If the existing file is the current capture file,
4497 we *HAVE* to do that, otherwise we're overwriting the file
4498 from which we're reading the packets that we're writing!) */
4499 fname_new = g_strdup_printf("%s~", fname);
4500 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4501 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4503 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4504 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4510 cfile_dump_open_failure_alert_box(fname, err, save_format);
4514 /* Add address resolution */
4515 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4517 /* Iterate through the list of packets, processing all the packets. */
4518 callback_args.pdh = pdh;
4519 callback_args.fname = fname;
4520 callback_args.file_type = save_format;
4521 switch (process_specified_records(cf, NULL, "Saving", "packets",
4522 TRUE, save_record, &callback_args, TRUE)) {
4525 /* Completed successfully. */
4529 /* The user decided to abort the saving.
4530 If we're writing to a temporary file, remove it.
4531 XXX - should we do so even if we're not writing to a
4533 wtap_dump_close(pdh, &err);
4534 if (fname_new != NULL)
4535 ws_unlink(fname_new);
4536 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4537 return CF_WRITE_ABORTED;
4540 /* Error while saving.
4541 If we're writing to a temporary file, remove it. */
4542 if (fname_new != NULL)
4543 ws_unlink(fname_new);
4544 wtap_dump_close(pdh, &err);
4548 needs_reload = wtap_dump_get_needs_reload(pdh);
4550 if (!wtap_dump_close(pdh, &err)) {
4551 cfile_close_failure_alert_box(fname, err);
4555 how_to_save = SAVE_WITH_WTAP;
4558 if (fname_new != NULL) {
4559 /* We wrote out to fname_new, and should rename it on top of
4560 fname. fname_new is now closed, so that should be possible even
4561 on Windows. However, on Windows, we first need to close whatever
4562 file descriptors we have open for fname. */
4564 wtap_fdclose(cf->wth);
4566 /* Now do the rename. */
4567 if (ws_rename(fname_new, fname) == -1) {
4568 /* Well, the rename failed. */
4569 cf_rename_failure_alert_box(fname, errno);
4571 /* Attempt to reopen the random file descriptor using the
4572 current file's filename. (At this point, the sequential
4573 file descriptor is closed.) */
4574 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4575 /* Oh, well, we're screwed. */
4576 display_basename = g_filename_display_basename(cf->filename);
4577 simple_error_message_box(
4578 file_open_error_message(err, FALSE), display_basename);
4579 g_free(display_basename);
4586 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4587 cf->unsaved_changes = FALSE;
4590 switch (how_to_save) {
4592 case SAVE_WITH_MOVE:
4593 /* We just moved the file, so the wtap structure refers to the
4594 new file, and all the information other than the filename
4595 and the "is temporary" status applies to the new file; just
4597 g_free(cf->filename);
4598 cf->filename = g_strdup(fname);
4599 cf->is_tempfile = FALSE;
4600 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4603 case SAVE_WITH_COPY:
4604 /* We just copied the file, s all the information other than
4605 the wtap structure, the filename, and the "is temporary"
4606 status applies to the new file; just update that. */
4607 wtap_close(cf->wth);
4608 /* Although we're just "copying" and then opening the copy, it will
4609 try all open_routine readers to open the copy, so we need to
4610 reset the cfile's open_type. */
4611 cf->open_type = WTAP_TYPE_AUTO;
4612 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4613 if (cf->wth == NULL) {
4614 cfile_open_failure_alert_box(fname, err, err_info);
4617 g_free(cf->filename);
4618 cf->filename = g_strdup(fname);
4619 cf->is_tempfile = FALSE;
4621 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4624 case SAVE_WITH_WTAP:
4625 /* Open and read the file we saved to.
4627 XXX - this is somewhat of a waste; we already have the
4628 packets, all this gets us is updated file type information
4629 (which we could just stuff into "cf"), and having the new
4630 file be the one we have opened and from which we're reading
4631 the data, and it means we have to spend time opening and
4632 reading the file, which could be a significant amount of
4633 time if the file is large.
4635 If the capture-file-writing code were to return the
4636 seek offset of each packet it writes, we could save that
4637 in the frame_data structure for the frame, and just open
4638 the file without reading it again...
4640 ...as long as, for gzipped files, the process of writing
4641 out the file *also* generates the information needed to
4642 support fast random access to the compressed file. */
4643 /* rescan_file will cause us to try all open_routines, so
4644 reset cfile's open_type */
4645 cf->open_type = WTAP_TYPE_AUTO;
4646 /* There are cases when SAVE_WITH_WTAP can result in new packets
4647 being written to the file, e.g ERF records
4648 In that case, we need to reload the whole file */
4650 if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) {
4651 if (cf_read(cf, TRUE) != CF_READ_OK) {
4652 /* The rescan failed; just close the file. Either
4653 a dialog was popped up for the failure, so the
4654 user knows what happened, or they stopped the
4655 rescan, in which case they know what happened. */
4656 /* XXX: This is inconsistent with normal open/reload behaviour. */
4662 if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4663 /* The rescan failed; just close the file. Either
4664 a dialog was popped up for the failure, so the
4665 user knows what happened, or they stopped the
4666 rescan, in which case they know what happened. */
4673 /* If we were told to discard the comments, do so. */
4674 if (discard_comments) {
4675 /* Remove SHB comment, if any. */
4676 wtap_write_shb_comment(cf->wth, NULL);
4678 /* remove all user comments */
4679 for (framenum = 1; framenum <= cf->count; framenum++) {
4680 fdata = frame_data_sequence_find(cf->frames, framenum);
4682 fdata->flags.has_phdr_comment = FALSE;
4683 fdata->flags.has_user_comment = FALSE;
4686 if (cf->frames_user_comments) {
4687 g_tree_destroy(cf->frames_user_comments);
4688 cf->frames_user_comments = NULL;
4691 cf->packet_comment_count = 0;
4697 if (fname_new != NULL) {
4698 /* We were trying to write to a temporary file; get rid of it if it
4699 exists. (We don't care whether this fails, as, if it fails,
4700 there's not much we can do about it. I guess if it failed for
4701 a reason other than "it doesn't exist", we could report an
4702 error, so the user knows there's a junk file that they might
4703 want to clean up.) */
4704 ws_unlink(fname_new);
4707 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4708 return CF_WRITE_ERROR;
4712 cf_export_specified_packets(capture_file *cf, const char *fname,
4713 packet_range_t *range, guint save_format,
4714 gboolean compressed)
4716 gchar *fname_new = NULL;
4719 save_callback_args_t callback_args;
4720 GArray *shb_hdrs = NULL;
4721 wtapng_iface_descriptions_t *idb_inf = NULL;
4722 GArray *nrb_hdrs = NULL;
4725 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4727 packet_range_process_init(range);
4729 /* We're writing out specified packets from the specified capture
4730 file to another file. Even if all captured packets are to be
4731 written, don't special-case the operation - read each packet
4732 and then write it out if it's one of the specified ones. */
4734 /* XXX: what free's this shb_hdr? */
4735 shb_hdrs = wtap_file_get_shb_for_new_file(cf->wth);
4736 idb_inf = wtap_file_get_idb_info(cf->wth);
4737 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
4739 /* Determine what file encapsulation type we should use. */
4740 encap = wtap_dump_file_encap_type(cf->linktypes);
4742 if (file_exists(fname)) {
4743 /* We're overwriting an existing file; write out to a new file,
4744 and, if that succeeds, rename the new file on top of the
4745 old file. That makes this a "safe save", so that we don't
4746 lose the old file if we have a problem writing out the new
4747 file. (If the existing file is the current capture file,
4748 we *HAVE* to do that, otherwise we're overwriting the file
4749 from which we're reading the packets that we're writing!) */
4750 fname_new = g_strdup_printf("%s~", fname);
4751 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4752 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4754 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4755 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4761 cfile_dump_open_failure_alert_box(fname, err, save_format);
4765 /* Add address resolution */
4766 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4768 /* Iterate through the list of packets, processing the packets we were
4771 XXX - we've already called "packet_range_process_init(range)", but
4772 "process_specified_records()" will do it again. Fortunately,
4773 that's harmless in this case, as we haven't done anything to
4774 "range" since we initialized it. */
4775 callback_args.pdh = pdh;
4776 callback_args.fname = fname;
4777 callback_args.file_type = save_format;
4778 switch (process_specified_records(cf, range, "Writing", "specified records",
4779 TRUE, save_record, &callback_args, TRUE)) {
4782 /* Completed successfully. */
4786 /* The user decided to abort the saving.
4787 If we're writing to a temporary file, remove it.
4788 XXX - should we do so even if we're not writing to a
4790 wtap_dump_close(pdh, &err);
4791 if (fname_new != NULL)
4792 ws_unlink(fname_new);
4793 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4794 return CF_WRITE_ABORTED;
4798 /* Error while saving.
4799 If we're writing to a temporary file, remove it. */
4800 if (fname_new != NULL)
4801 ws_unlink(fname_new);
4802 wtap_dump_close(pdh, &err);
4806 if (!wtap_dump_close(pdh, &err)) {
4807 cfile_close_failure_alert_box(fname, err);
4811 if (fname_new != NULL) {
4812 /* We wrote out to fname_new, and should rename it on top of
4813 fname; fname is now closed, so that should be possible even
4814 on Windows. Do the rename. */
4815 if (ws_rename(fname_new, fname) == -1) {
4816 /* Well, the rename failed. */
4817 cf_rename_failure_alert_box(fname, errno);
4822 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4826 if (fname_new != NULL) {
4827 /* We were trying to write to a temporary file; get rid of it if it
4828 exists. (We don't care whether this fails, as, if it fails,
4829 there's not much we can do about it. I guess if it failed for
4830 a reason other than "it doesn't exist", we could report an
4831 error, so the user knows there's a junk file that they might
4832 want to clean up.) */
4833 ws_unlink(fname_new);
4836 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4837 return CF_WRITE_ERROR;
4841 * XXX - whether we mention the source pathname, the target pathname,
4842 * or both depends on the error and on what we find if we look for
4843 * one or both of them.
4846 cf_rename_failure_alert_box(const char *filename, int err)
4848 gchar *display_basename;
4850 display_basename = g_filename_display_basename(filename);
4854 /* XXX - should check whether the source exists and, if not,
4855 report it as the problem and, if so, report the destination
4857 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4862 /* XXX - if we're doing a rename after a safe save, we should
4863 probably say something else. */
4864 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4869 /* XXX - this should probably mention both the source and destination
4871 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4872 display_basename, wtap_strerror(err));
4875 g_free(display_basename);
4878 /* Reload the current capture file. */
4880 cf_reload(capture_file *cf) {
4882 gboolean is_tempfile;
4885 /* If the file could be opened, "cf_open()" calls "cf_close()"
4886 to get rid of state for the old capture file before filling in state
4887 for the new capture file. "cf_close()" will remove the file if
4888 it's a temporary file; we don't want that to happen (for one thing,
4889 it'd prevent subsequent reopens from working). Remember whether it's
4890 a temporary file, mark it as not being a temporary file, and then
4891 reopen it as the type of file it was.
4893 Also, "cf_close()" will free "cf->filename", so we must make
4894 a copy of it first. */
4895 filename = g_strdup(cf->filename);
4896 is_tempfile = cf->is_tempfile;
4897 cf->is_tempfile = FALSE;
4898 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4899 switch (cf_read(cf, TRUE)) {
4903 /* Just because we got an error, that doesn't mean we were unable
4904 to read any of the file; we handle what we could get from the
4908 case CF_READ_ABORTED:
4909 /* The user bailed out of re-reading the capture file; the
4910 capture file has been closed - just free the capture file name
4911 string and return (without changing the last containing
4917 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4918 Instead, the file was left open, so we should restore "cf->is_tempfile"
4921 XXX - change the menu? Presumably "cf_open()" will do that;
4922 make sure it does! */
4923 cf->is_tempfile = is_tempfile;
4925 /* "cf_open()" made a copy of the file name we handed it, so
4926 we should free up our copy. */
4936 * indent-tabs-mode: nil
4939 * ex: set shiftwidth=2 tabstop=8 expandtab:
4940 * :indentSize=2:tabSize=8:noTabs=true: